From 2b77c30af5eca4c5f73cecab77da6f35a34e9c6c Mon Sep 17 00:00:00 2001 From: Zheyuan-Robert-Xu <79696631+Zheyuan-Robert-Xu@users.noreply.github.com> Date: Tue, 9 Jul 2024 21:45:33 +1000 Subject: [PATCH 01/10] add turtle_utils --- lib/rdflib.dart | 1 + lib/src/turtle_utils.dart | 52 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+) create mode 100644 lib/src/turtle_utils.dart diff --git a/lib/rdflib.dart b/lib/rdflib.dart index b32c782..de79fd6 100644 --- a/lib/rdflib.dart +++ b/lib/rdflib.dart @@ -4,6 +4,7 @@ export 'src/term.dart'; export 'src/namespace.dart'; export 'src/triple.dart'; export 'src/graph.dart'; +export 'src/turtle_utils.dart'; export 'parser/naive_parser.dart'; export 'parser/grammar_parser.dart'; diff --git a/lib/src/turtle_utils.dart b/lib/src/turtle_utils.dart new file mode 100644 index 0000000..ae34f7b --- /dev/null +++ b/lib/src/turtle_utils.dart @@ -0,0 +1,52 @@ +import 'graph.dart'; + +/// Parses Turtle (Terse RDF Triple Language) content and extracts it into a map. +/// +/// This function processes the provided Turtle content string. It uses a graph-based +/// approach to parse the Turtle data and extract key attributes and their values. +/// The resulting map will have subjects as keys, and their corresponding predicates +/// and objects as nested key-value pairs. +/// +/// Example usage: +/// ```dart +/// final ttlContent = ''' +/// @prefix ex: . +/// ex:subject ex:predicate "object" . +/// '''; +/// final data = parseTTL(ttlContent); +/// print(data); +/// // Output: {subject: {predicate: object}} +/// ``` +Map parseTTL(String ttlContent) { + // Create a new graph instance and parse the Turtle content into it. + final g = Graph(); + g.parseTurtle(ttlContent); + + // Initialize an empty map to store the parsed data. + final dataMap = {}; + + // A helper function to extract the local name from a URI or blank node. + String extract(String str) => str.contains('#') ? str.split('#')[1] : str; + + // Iterate over all triples in the graph. + for (final t in g.triples) { + // Extract the subject, predicate, and object from the triple. + final sub = extract(t.sub.value as String); + final pre = extract(t.pre.value as String); + final obj = extract(t.obj.value as String); + + // Check if the subject already exists in the map. + if (dataMap.containsKey(sub)) { + // Ensure that the predicate does not already exist for the subject. + assert(!(dataMap[sub] as Map).containsKey(pre)); + // Add the predicate and object to the existing subject entry. + dataMap[sub][pre] = obj; + } else { + // Create a new entry for the subject with the predicate and object. + dataMap[sub] = {pre: obj}; + } + } + + // Return the populated map. + return dataMap; +} From 665c609f6ca1f0975dfed739e5c0578351d111ae Mon Sep 17 00:00:00 2001 From: Zheyuan-Robert-Xu <79696631+Zheyuan-Robert-Xu@users.noreply.github.com> Date: Tue, 9 Jul 2024 23:37:14 +1000 Subject: [PATCH 02/10] add predicates --- lib/src/graph.dart | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/lib/src/graph.dart b/lib/src/graph.dart index aaa7fa1..b62689d 100644 --- a/lib/src/graph.dart +++ b/lib/src/graph.dart @@ -291,6 +291,17 @@ class Graph { return objs; } + /// Finds all predicates which have a certain subject and object. + Set predicates(URIRef sub, dynamic obj) { + Set pres = {}; + for (Triple t in triples) { + if (t.sub == sub && t.obj == obj) { + pres.add(t.pre); + } + } + return pres; + } + /// Parses file and update graph accordingly. @Deprecated('Use [Graph.parseTurtle] instead for parsing a turtle string') parse(String filePath) async { From cf4ff831f54aae7ca5c784ff69a9a4606b1c7e16 Mon Sep 17 00:00:00 2001 From: Zheyuan-Robert-Xu <79696631+Zheyuan-Robert-Xu@users.noreply.github.com> Date: Wed, 10 Jul 2024 10:56:23 +1000 Subject: [PATCH 03/10] update methods --- example/main.dart | 4 +- lib/src/graph.dart | 95 ++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 90 insertions(+), 9 deletions(-) diff --git a/example/main.dart b/example/main.dart index 63696b1..7dc7653 100644 --- a/example/main.dart +++ b/example/main.dart @@ -43,8 +43,8 @@ main() { // Print out each person's mailbox value print('-------\nMailboxes:'); - for (var sub in g.subjects(a, FOAF.Person)) { - for (var mbox in g.objects(sub, FOAF.mbox)) { + for (var sub in g.subjects(pre: a, obj: FOAF.Person)) { + for (var mbox in g.objects(sub: sub, pre: FOAF.mbox)) { print('${sub}\'s mailbox: ${mbox.value}'); } } diff --git a/lib/src/graph.dart b/lib/src/graph.dart index b62689d..5e11f0f 100644 --- a/lib/src/graph.dart +++ b/lib/src/graph.dart @@ -270,35 +270,116 @@ class Graph { } /// Finds all subjects which have a certain predicate and object. - Set subjects(URIRef pre, dynamic obj) { + /// + /// If `pre` is provided, it checks for the predicate. + /// If `obj` is provided, it checks for the object. + /// If both are provided, it checks for both predicate and object. + /// If neither is provided, it returns all subjects in the triples. + Set subjects({URIRef? pre, dynamic obj}) { + // Initialize an empty set to store the subjects. Set subs = {}; + + // Iterate over all triples in the graph. for (Triple t in triples) { - if (t.pre == pre && t.obj == obj) { + // Check conditions based on the presence of pre and obj. + if (pre != null && obj != null) { + // Both pre and obj are provided. + if (t.pre == pre && t.obj == obj) { + subs.add(t.sub); + } + } else if (pre != null) { + // Only pre is provided. + if (t.pre == pre) { + subs.add(t.sub); + } + } else if (obj != null) { + // Only obj is provided. + if (t.obj == obj) { + subs.add(t.sub); + } + } else { + // Neither pre nor obj is provided, return all subjects. subs.add(t.sub); } } + + // Return the set of subjects. return subs; } /// Finds all objects which have a certain subject and predicate. - Set objects(URIRef sub, URIRef pre) { - Set objs = {}; + /// + /// If `sub` is provided, it checks for the subject. + /// If `pre` is provided, it checks for the predicate. + /// If both are provided, it checks for both subject and predicate. + /// If neither is provided, it returns all objects in the triples. + Set objects({URIRef? sub, URIRef? pre}) { + // Initialize an empty set to store the objects. + Set objs = {}; + + // Iterate over all triples in the graph. for (Triple t in triples) { - if (t.sub == sub && t.pre == pre) { + // Check conditions based on the presence of sub and pre. + if (sub != null && pre != null) { + // Both sub and pre are provided. + if (t.sub == sub && t.pre == pre) { + objs.add(t.obj); + } + } else if (sub != null) { + // Only sub is provided. + if (t.sub == sub) { + objs.add(t.obj); + } + } else if (pre != null) { + // Only pre is provided. + if (t.pre == pre) { + objs.add(t.obj); + } + } else { + // Neither sub nor pre is provided, return all objects. objs.add(t.obj); } } + + // Return the set of objects. return objs; } /// Finds all predicates which have a certain subject and object. - Set predicates(URIRef sub, dynamic obj) { + /// + /// If `sub` is provided, it checks for the subject. + /// If `obj` is provided, it checks for the object. + /// If both are provided, it checks for both subject and object. + /// If neither is provided, it returns all predicates in the triples. + Set predicates({URIRef? sub, dynamic obj}) { + // Initialize an empty set to store the predicates. Set pres = {}; + + // Iterate over all triples in the graph. for (Triple t in triples) { - if (t.sub == sub && t.obj == obj) { + // Check conditions based on the presence of sub and obj. + if (sub != null && obj != null) { + // Both sub and obj are provided. + if (t.sub == sub && t.obj == obj) { + pres.add(t.pre); + } + } else if (sub != null) { + // Only sub is provided. + if (t.sub == sub) { + pres.add(t.pre); + } + } else if (obj != null) { + // Only obj is provided. + if (t.obj == obj) { + pres.add(t.pre); + } + } else { + // Neither sub nor obj is provided, return all predicates. pres.add(t.pre); } } + + // Return the set of predicates. return pres; } From 3e026c20ed5c18e3b46dd1b3863dec59b3f9f74e Mon Sep 17 00:00:00 2001 From: Zheyuan-Robert-Xu <79696631+Zheyuan-Robert-Xu@users.noreply.github.com> Date: Wed, 10 Jul 2024 15:24:03 +1000 Subject: [PATCH 04/10] rename parsettl --- lib/rdflib.dart | 2 +- lib/src/{turtle_utils.dart => turtle/parsettl.dart} | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename lib/src/{turtle_utils.dart => turtle/parsettl.dart} (98%) diff --git a/lib/rdflib.dart b/lib/rdflib.dart index de79fd6..ba7eefa 100644 --- a/lib/rdflib.dart +++ b/lib/rdflib.dart @@ -4,7 +4,7 @@ export 'src/term.dart'; export 'src/namespace.dart'; export 'src/triple.dart'; export 'src/graph.dart'; -export 'src/turtle_utils.dart'; +export 'src/turtle/parsettl.dart'; export 'parser/naive_parser.dart'; export 'parser/grammar_parser.dart'; diff --git a/lib/src/turtle_utils.dart b/lib/src/turtle/parsettl.dart similarity index 98% rename from lib/src/turtle_utils.dart rename to lib/src/turtle/parsettl.dart index ae34f7b..75811a9 100644 --- a/lib/src/turtle_utils.dart +++ b/lib/src/turtle/parsettl.dart @@ -1,4 +1,4 @@ -import 'graph.dart'; +import '../graph.dart'; /// Parses Turtle (Terse RDF Triple Language) content and extracts it into a map. /// From d2b55fa1907ec307f984098c5ac83c70cc7b183c Mon Sep 17 00:00:00 2001 From: Zheyuan-Robert-Xu <79696631+Zheyuan-Robert-Xu@users.noreply.github.com> Date: Wed, 10 Jul 2024 18:48:57 +1000 Subject: [PATCH 05/10] add method parseTTLStr --- lib/src/turtle/parsettl.dart | 64 ++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/lib/src/turtle/parsettl.dart b/lib/src/turtle/parsettl.dart index 75811a9..89db502 100644 --- a/lib/src/turtle/parsettl.dart +++ b/lib/src/turtle/parsettl.dart @@ -50,3 +50,67 @@ Map parseTTL(String ttlContent) { // Return the populated map. return dataMap; } + +/// Parses a TTL (Terse RDF Triple Language) string [ttlStr] and returns +/// the key-value pairs from triples where the subject matches [webId]. +/// +/// This function processes the provided TTL string and extracts the key-value, +/// based on the given Web ID. It ensures there are no duplicate keys for the +/// same subject. +/// +/// Example usage: +/// ```dart +/// final ttlStr = ''' +/// @prefix ex: . +/// ex:webID ex:key "value" . +/// '''; +/// final webId = 'http://example.com/webID'; +/// final result = await parseTTLStr(ttlStr, webId); +/// print(result); +/// // Output: [{key: key, value: value}] +/// ``` +Future> parseTTLStr( + String ttlStr, String? webId) async { + // Ensure that the TTL string is not empty. + assert(ttlStr.isNotEmpty, 'The TTL string should not be empty.'); + + // Create a new graph instance and parse the TTL content into it. + final g = Graph(); + g.parseTurtle(ttlStr); + + // Initialize a set to track unique keys and a list to store key-value pairs. + final keys = {}; + final pairs = <({String key, dynamic value})>[]; + + // Ensure that webId is not null. + assert(webId != null, 'Web ID should not be null.'); + + // Helper function to extract the local name from a URI or blank node. + String extract(String str) => str.contains('#') ? str.split('#')[1] : str; + + // Iterate over all triples in the graph. + for (final t in g.triples) { + // Extract the subject from the triple. + final sub = t.sub.value as String; + + // Check if the subject matches the given webId. + if (sub == webId) { + // Extract the predicate and object from the triple. + final pre = extract(t.pre.value as String); + final obj = extract(t.obj.value as String); + + // Ensure that the key (predicate) is unique for the subject. + assert(!keys.contains(pre), 'Duplicate key found for the subject.'); + + // Add the key to the set of unique keys and the key-value pair to the list. + keys.add(pre); + pairs.add((key: pre, value: obj)); + } + } + + // Ensure that the parsed TTL content contains at least one matching triple. + assert(pairs.isNotEmpty, 'No matching triples found for the given Web ID.'); + + // Return the list of key-value pairs. + return pairs; +} From 1abe6905771c4d27c9c5834ca7b88273282d50cc Mon Sep 17 00:00:00 2001 From: Zheyuan-Robert-Xu <79696631+Zheyuan-Robert-Xu@users.noreply.github.com> Date: Wed, 10 Jul 2024 19:47:11 +1000 Subject: [PATCH 06/10] add tripleValues --- lib/src/graph.dart | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/lib/src/graph.dart b/lib/src/graph.dart index 5e11f0f..e1442e1 100644 --- a/lib/src/graph.dart +++ b/lib/src/graph.dart @@ -383,6 +383,37 @@ class Graph { return pres; } + /// Finds all triples which have a certain value. + /// + /// This method checks if the given [value] matches any of the components + /// (subject, predicate, or object) of the triples in the graph. It returns + /// a set of triples where any of these components matches the [value]. + /// + /// Example usage: + /// ```dart + /// final value = 'exampleValue'; + /// final matchingTriples = values(value); + /// print(matchingTriples); + /// ``` + Set tripleValues(String value) { + // Initialize an empty set to store the matching triples. + Set matchingTriples = {}; + + // Iterate over all triples in the graph. + for (Triple t in triples) { + // Check if the subject, predicate, or object matches the given value. + if (t.sub.value == value || + t.pre.value == value || + t.obj.toString() == value) { + // If any component matches, add the triple to the set of matching triples. + matchingTriples.add(t); + } + } + + // Return the set of matching triples. + return matchingTriples; + } + /// Parses file and update graph accordingly. @Deprecated('Use [Graph.parseTurtle] instead for parsing a turtle string') parse(String filePath) async { From 7f91a51a3343fadd5bb89f3d4a996a88bce65736 Mon Sep 17 00:00:00 2001 From: Zheyuan-Robert-Xu <79696631+Zheyuan-Robert-Xu@users.noreply.github.com> Date: Wed, 10 Jul 2024 20:16:03 +1000 Subject: [PATCH 07/10] add print of using tripleValues --- example/main.dart | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/example/main.dart b/example/main.dart index 7dc7653..04cd028 100644 --- a/example/main.dart +++ b/example/main.dart @@ -48,4 +48,10 @@ main() { print('${sub}\'s mailbox: ${mbox.value}'); } } + + // Print out predicates of triples having donna + print('-------\nDonna predicates values:'); + for (Triple tri in g.tripleValues(donna.value)) { + print(tri.pre.value); + } } From e2be5a03ad7a7add11e4ffb38ba458db6e7831cf Mon Sep 17 00:00:00 2001 From: Zheyuan-Robert-Xu <79696631+Zheyuan-Robert-Xu@users.noreply.github.com> Date: Wed, 17 Jul 2024 11:26:02 +1000 Subject: [PATCH 08/10] remove parsettl.dart --- lib/rdflib.dart | 1 - lib/src/turtle/parsettl.dart | 116 ----------------------------------- 2 files changed, 117 deletions(-) delete mode 100644 lib/src/turtle/parsettl.dart diff --git a/lib/rdflib.dart b/lib/rdflib.dart index ba7eefa..b32c782 100644 --- a/lib/rdflib.dart +++ b/lib/rdflib.dart @@ -4,7 +4,6 @@ export 'src/term.dart'; export 'src/namespace.dart'; export 'src/triple.dart'; export 'src/graph.dart'; -export 'src/turtle/parsettl.dart'; export 'parser/naive_parser.dart'; export 'parser/grammar_parser.dart'; diff --git a/lib/src/turtle/parsettl.dart b/lib/src/turtle/parsettl.dart deleted file mode 100644 index 89db502..0000000 --- a/lib/src/turtle/parsettl.dart +++ /dev/null @@ -1,116 +0,0 @@ -import '../graph.dart'; - -/// Parses Turtle (Terse RDF Triple Language) content and extracts it into a map. -/// -/// This function processes the provided Turtle content string. It uses a graph-based -/// approach to parse the Turtle data and extract key attributes and their values. -/// The resulting map will have subjects as keys, and their corresponding predicates -/// and objects as nested key-value pairs. -/// -/// Example usage: -/// ```dart -/// final ttlContent = ''' -/// @prefix ex: . -/// ex:subject ex:predicate "object" . -/// '''; -/// final data = parseTTL(ttlContent); -/// print(data); -/// // Output: {subject: {predicate: object}} -/// ``` -Map parseTTL(String ttlContent) { - // Create a new graph instance and parse the Turtle content into it. - final g = Graph(); - g.parseTurtle(ttlContent); - - // Initialize an empty map to store the parsed data. - final dataMap = {}; - - // A helper function to extract the local name from a URI or blank node. - String extract(String str) => str.contains('#') ? str.split('#')[1] : str; - - // Iterate over all triples in the graph. - for (final t in g.triples) { - // Extract the subject, predicate, and object from the triple. - final sub = extract(t.sub.value as String); - final pre = extract(t.pre.value as String); - final obj = extract(t.obj.value as String); - - // Check if the subject already exists in the map. - if (dataMap.containsKey(sub)) { - // Ensure that the predicate does not already exist for the subject. - assert(!(dataMap[sub] as Map).containsKey(pre)); - // Add the predicate and object to the existing subject entry. - dataMap[sub][pre] = obj; - } else { - // Create a new entry for the subject with the predicate and object. - dataMap[sub] = {pre: obj}; - } - } - - // Return the populated map. - return dataMap; -} - -/// Parses a TTL (Terse RDF Triple Language) string [ttlStr] and returns -/// the key-value pairs from triples where the subject matches [webId]. -/// -/// This function processes the provided TTL string and extracts the key-value, -/// based on the given Web ID. It ensures there are no duplicate keys for the -/// same subject. -/// -/// Example usage: -/// ```dart -/// final ttlStr = ''' -/// @prefix ex: . -/// ex:webID ex:key "value" . -/// '''; -/// final webId = 'http://example.com/webID'; -/// final result = await parseTTLStr(ttlStr, webId); -/// print(result); -/// // Output: [{key: key, value: value}] -/// ``` -Future> parseTTLStr( - String ttlStr, String? webId) async { - // Ensure that the TTL string is not empty. - assert(ttlStr.isNotEmpty, 'The TTL string should not be empty.'); - - // Create a new graph instance and parse the TTL content into it. - final g = Graph(); - g.parseTurtle(ttlStr); - - // Initialize a set to track unique keys and a list to store key-value pairs. - final keys = {}; - final pairs = <({String key, dynamic value})>[]; - - // Ensure that webId is not null. - assert(webId != null, 'Web ID should not be null.'); - - // Helper function to extract the local name from a URI or blank node. - String extract(String str) => str.contains('#') ? str.split('#')[1] : str; - - // Iterate over all triples in the graph. - for (final t in g.triples) { - // Extract the subject from the triple. - final sub = t.sub.value as String; - - // Check if the subject matches the given webId. - if (sub == webId) { - // Extract the predicate and object from the triple. - final pre = extract(t.pre.value as String); - final obj = extract(t.obj.value as String); - - // Ensure that the key (predicate) is unique for the subject. - assert(!keys.contains(pre), 'Duplicate key found for the subject.'); - - // Add the key to the set of unique keys and the key-value pair to the list. - keys.add(pre); - pairs.add((key: pre, value: obj)); - } - } - - // Ensure that the parsed TTL content contains at least one matching triple. - assert(pairs.isNotEmpty, 'No matching triples found for the given Web ID.'); - - // Return the list of key-value pairs. - return pairs; -} From 5a30ca99b64190c4c0da6c5581352b3510c39090 Mon Sep 17 00:00:00 2001 From: Zheyuan-Robert-Xu <79696631+Zheyuan-Robert-Xu@users.noreply.github.com> Date: Wed, 17 Jul 2024 21:19:51 +1000 Subject: [PATCH 09/10] matchTriples --- example/main.dart | 2 +- lib/src/graph.dart | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/example/main.dart b/example/main.dart index 04cd028..86eefbf 100644 --- a/example/main.dart +++ b/example/main.dart @@ -51,7 +51,7 @@ main() { // Print out predicates of triples having donna print('-------\nDonna predicates values:'); - for (Triple tri in g.tripleValues(donna.value)) { + for (Triple tri in g.matchTriples(donna.value)) { print(tri.pre.value); } } diff --git a/lib/src/graph.dart b/lib/src/graph.dart index e1442e1..9e196a6 100644 --- a/lib/src/graph.dart +++ b/lib/src/graph.dart @@ -392,10 +392,10 @@ class Graph { /// Example usage: /// ```dart /// final value = 'exampleValue'; - /// final matchingTriples = values(value); + /// final matchingTriples = matchTriples(value); /// print(matchingTriples); /// ``` - Set tripleValues(String value) { + Set matchTriples(String value) { // Initialize an empty set to store the matching triples. Set matchingTriples = {}; From 57693c98305a38b8196bdc1e55996136c32c57a5 Mon Sep 17 00:00:00 2001 From: Zheyuan-Robert-Xu <79696631+Zheyuan-Robert-Xu@users.noreply.github.com> Date: Wed, 17 Jul 2024 21:45:33 +1000 Subject: [PATCH 10/10] simplify conditions --- lib/src/graph.dart | 75 +++++++++++++--------------------------------- 1 file changed, 21 insertions(+), 54 deletions(-) diff --git a/lib/src/graph.dart b/lib/src/graph.dart index 9e196a6..7c4512d 100644 --- a/lib/src/graph.dart +++ b/lib/src/graph.dart @@ -281,24 +281,13 @@ class Graph { // Iterate over all triples in the graph. for (Triple t in triples) { - // Check conditions based on the presence of pre and obj. - if (pre != null && obj != null) { - // Both pre and obj are provided. - if (t.pre == pre && t.obj == obj) { - subs.add(t.sub); - } - } else if (pre != null) { - // Only pre is provided. - if (t.pre == pre) { - subs.add(t.sub); - } - } else if (obj != null) { - // Only obj is provided. - if (t.obj == obj) { - subs.add(t.sub); - } - } else { - // Neither pre nor obj is provided, return all subjects. + // Check if the pre condition matches, if provided. + bool preMatches = pre == null || t.pre == pre; + // Check if the obj condition matches, if provided. + bool objMatches = obj == null || t.obj == obj; + + // If both conditions match (or are not provided), add the subject. + if (preMatches && objMatches) { subs.add(t.sub); } } @@ -319,24 +308,13 @@ class Graph { // Iterate over all triples in the graph. for (Triple t in triples) { - // Check conditions based on the presence of sub and pre. - if (sub != null && pre != null) { - // Both sub and pre are provided. - if (t.sub == sub && t.pre == pre) { - objs.add(t.obj); - } - } else if (sub != null) { - // Only sub is provided. - if (t.sub == sub) { - objs.add(t.obj); - } - } else if (pre != null) { - // Only pre is provided. - if (t.pre == pre) { - objs.add(t.obj); - } - } else { - // Neither sub nor pre is provided, return all objects. + // Check if the sub condition matches, if provided. + bool subMatches = sub == null || t.sub == sub; + // Check if the pre condition matches, if provided. + bool preMatches = pre == null || t.pre == pre; + + // If both conditions match (or are not provided), add the object. + if (subMatches && preMatches) { objs.add(t.obj); } } @@ -357,24 +335,13 @@ class Graph { // Iterate over all triples in the graph. for (Triple t in triples) { - // Check conditions based on the presence of sub and obj. - if (sub != null && obj != null) { - // Both sub and obj are provided. - if (t.sub == sub && t.obj == obj) { - pres.add(t.pre); - } - } else if (sub != null) { - // Only sub is provided. - if (t.sub == sub) { - pres.add(t.pre); - } - } else if (obj != null) { - // Only obj is provided. - if (t.obj == obj) { - pres.add(t.pre); - } - } else { - // Neither sub nor obj is provided, return all predicates. + // Check if the sub condition matches, if provided. + bool subMatches = sub == null || t.sub == sub; + // Check if the obj condition matches, if provided. + bool objMatches = obj == null || t.obj == obj; + + // If both conditions match (or are not provided), add the predicate. + if (subMatches && objMatches) { pres.add(t.pre); } }