@@ -66,19 +66,19 @@ class Graph {
66
66
void addTripleToGroups (dynamic s, dynamic p, dynamic o) {
67
67
// TODO: subject as a BlankNode
68
68
try {
69
- URIRef sub = (s.runtimeType == URIRef ) ? s : item (s) as URIRef ;
69
+ dynamic sub =
70
+ (s.runtimeType == URIRef || s.runtimeType == BNode ) ? s : item (s);
70
71
_updateCtx (sub, ctx);
71
72
if (! groups.containsKey (sub)) {
72
73
groups[sub] = Map ();
73
74
}
74
- URIRef pre = (p.runtimeType == URIRef ) ? p : item (p) as URIRef ;
75
+ dynamic pre = (p.runtimeType == URIRef ) ? p : item (p);
75
76
_updateCtx (pre, ctx);
76
77
if (! groups[sub]! .containsKey (pre)) {
77
78
groups[sub]! [pre] = Set ();
78
79
}
79
- // var obj = (o.runtimeType == URIRef) ? o : item(o);
80
80
var obj = (o.runtimeType == String ) ? item (o) : o;
81
- if (obj.runtimeType == URIRef ) {
81
+ if (obj.runtimeType == URIRef || obj.runtimeType == BNode ) {
82
82
_updateCtx (obj, ctx);
83
83
} else if (obj.runtimeType == Literal ) {
84
84
Literal objLiteral = obj as Literal ;
@@ -88,8 +88,8 @@ class Graph {
88
88
} else if (obj.runtimeType == String ) {
89
89
_updateCtx (XSD .string, ctx);
90
90
}
91
+ // Updates triple sets as well.
91
92
groups[sub]! [pre]! .add (obj);
92
- // Update the triples set as well.
93
93
triples.add (Triple (sub: sub, pre: pre, obj: obj));
94
94
} catch (e) {
95
95
print ('Error occurred when adding triple ($s , $p , $o ), '
@@ -688,22 +688,22 @@ class Graph {
688
688
return ;
689
689
}
690
690
List tripleContent = tripleList[0 ];
691
- URIRef sub = item (tripleContent[0 ]) as URIRef ;
691
+ dynamic sub = item (tripleContent[0 ]);
692
692
if (! groups.containsKey (sub)) {
693
693
groups[sub] = Map ();
694
694
}
695
695
List predicateObjectLists = tripleContent[1 ];
696
696
for (List predicateObjectList in predicateObjectLists) {
697
697
// Predicate is always an iri.
698
698
// Uses URIRef as we translate PrefixedName to full form of [URIRef]
699
- URIRef pre;
700
- pre = item (predicateObjectList[0 ]);
701
- // Use a set to store the triples.
699
+ dynamic pre = item (predicateObjectList[0 ]);
702
700
groups[sub]! [pre] = Set ();
703
701
List objectList = predicateObjectList[1 ];
704
- for (String obj in objectList) {
705
- groups[sub]! [pre]! .add (item (obj));
706
- triples.add (Triple (sub: sub, pre: pre, obj: item (obj)));
702
+ for (var obj in objectList) {
703
+ var parsedObj =
704
+ (obj is List ) ? item (_combineListItems (obj)) : item (obj);
705
+ groups[sub]! [pre]! .add (parsedObj);
706
+ triples.add (Triple (sub: sub, pre: pre, obj: parsedObj));
707
707
}
708
708
}
709
709
}
@@ -730,83 +730,79 @@ class Graph {
730
730
/// Case 4: abc^^xsd:string -> Literal('abc', datatype:xsd:string)
731
731
/// Case 5: abc@en -> Literal('abc', lang:'en')
732
732
/// Case 6: abc -> Literal('abc')
733
- item (String s) {
734
- s = s. trim ();
735
- // 0. a is short for rdf:type
736
- if (s == 'a' ) {
737
- _saveToContext ([ '@prefix' , 'rdf:' , '<${ RDF . rdf }>' ]);
738
- return a;
739
- }
740
- // 1. <>
741
- else if (s. startsWith ( '<' ) && s. endsWith ( '>' )) {
742
- String uri = s. substring ( 1 , s.length - 1 );
743
- if (URIRef . isValidUri (uri )) {
744
- // Valid uri is sufficient as URIRef.
733
+ item (dynamic s) {
734
+ if (s is String ) {
735
+ s = s. trim ();
736
+
737
+ // 0. a is short for rdf:type
738
+ if (s == 'a' ) {
739
+ _saveToContext ([ '@prefix' , 'rdf:' , '<${ RDF . rdf }>' ]);
740
+ return a;
741
+ }
742
+ // 1. <>
743
+ else if (s. startsWith ( '<' ) && s. endsWith ( '>' )) {
744
+ String uri = s. substring ( 1 , s.length - 1 );
745
745
return URIRef (uri);
746
- } else {
747
- if (ctx.containsKey (':' )) {
748
- // FIXME: if context has base, do we need to stitch them?
749
- // Examples:
750
- // 1. <> -> URIRef('')
751
- // 2. <./> -> URIRef('./')
752
- // 3. <bob#me> -> e.g., URIRef('http://example.org/bob#me')
753
- // or just URIRef('bob#m3') [current implementation]?
754
- return URIRef (uri);
755
- // return URIRef('${ctx[':']!.value}${uri}');
756
- } else {
757
- return URIRef (uri); // or it's just a string within <>
746
+ }
747
+ // 4. abc^^xsd:string
748
+ // Note this needs to come before :abc or abc:efg cases.
749
+ else if (s.contains ('^^' )) {
750
+ List <String > lst = s.split ('^^' );
751
+ String value = lst[0 ];
752
+ String datatype = lst[1 ];
753
+ // Note: Literal only supports XSD, OWL namespaces currently
754
+ return Literal (value, datatype: item (datatype));
755
+ }
756
+ // 2. :abc
757
+ else if (s.startsWith (':' )) {
758
+ // When using @base.
759
+ if (ctx[':' ] == null ) {
760
+ throw Exception ('Base is not defined yet. (caused by $s )' );
758
761
}
762
+ return URIRef ('${ctx [":" ]!.value }${s .substring (1 )}' );
759
763
}
760
- }
761
- // 4. abc^^xsd:string
762
- // Note this needs to come before :abc or abc:efg cases.
763
- else if (s.contains ('^^' )) {
764
- List <String > lst = s.split ('^^' );
765
- String value = lst[0 ];
766
- String datatype = lst[1 ];
767
- // Note: Literal only supports XSD, OWL namespaces currently
768
- return Literal (value, datatype: item (datatype));
769
- }
770
- // 2. :abc
771
- else if (s.startsWith (':' )) {
772
- // When using @base.
773
- if (ctx[':' ] == null ) {
774
- throw Exception ('Base is not defined yet. (caused by $s )' );
764
+ // 3. abc:efg
765
+ else if (s.contains (':' ) && ! s.startsWith ('_:' )) {
766
+ // When using @prefix
767
+ int firstColonPos = s.indexOf (':' );
768
+ String namespace = s.substring (0 , firstColonPos + 1 ); // including ':'
769
+ String localname = s.substring (firstColonPos + 1 );
770
+ // If the namespace is not defined, we can't proceed.
771
+ if (ctx[namespace] == null ) {
772
+ throw Exception (
773
+ 'Namespace ${namespace .substring (0 , namespace .length - 1 )} is used '
774
+ 'but not defined. (caused by $s )' );
775
+ }
776
+ return URIRef ('${ctx [namespace ]?.value }$localname ' );
775
777
}
776
- return URIRef ('${ctx [":" ]!.value }${s .substring (1 )}' );
777
- }
778
- // 3. abc:efg
779
- else if (s.contains (':' )) {
780
- // When using @prefix
781
- int firstColonPos = s.indexOf (':' );
782
- String namespace = s.substring (0 , firstColonPos + 1 ); // including ':'
783
- String localname = s.substring (firstColonPos + 1 );
784
- // If the namespace is not defined, we can't proceed.
785
- if (ctx[namespace] == null ) {
786
- throw Exception (
787
- 'Namespace ${namespace .substring (0 , namespace .length - 1 )} is used '
788
- 'but not defined. (caused by $s )' );
778
+ // 5. abc@en
779
+ else if (_existsLangTag (s)) {
780
+ String lang = _getLangTag (s);
781
+ String value = s.replaceAll ('@$lang ' , '' );
782
+ return Literal (value, lang: lang);
789
783
}
790
- return URIRef ('${ctx [namespace ]?.value }$localname ' );
791
- }
792
- // 5. abc@en
793
- else if (_existsLangTag (s)) {
794
- String lang = _getLangTag (s);
795
- String value = s.replaceAll ('@$lang ' , '' );
796
- return Literal (value, lang: lang);
797
- }
798
- // AV-20240621: commenting the following and adding above
799
- // as the following will identify non language tags as well
800
- // else if (s.contains('@')) {
801
- // List<String> lst = s.split('@');
802
- // String value = lst[0];
803
- // String lang = lst[1];
804
- // return Literal(value, lang: lang);
805
- // }
806
- // 6. abc
807
- else {
808
- // Treat it as a normal string.
809
- return Literal (s);
784
+ // AV-20240621: commenting the following and adding above
785
+ // as the following will identify non language tags as well
786
+ // else if (s.contains('@')) {
787
+ // List<String> lst = s.split('@');
788
+ // String value = lst[0];
789
+ // String lang = lst[1];
790
+ // return Literal(value, lang: lang);
791
+ // }
792
+ // 6. _:
793
+ else if (s.startsWith ('_:' )) {
794
+ return BNode (s);
795
+ } else {
796
+ // Treat it as a normal string.
797
+ return Literal (s);
798
+ }
799
+ } else if (s is List ) {
800
+ // Combine all items and sub-items in the list into a single string.
801
+ String combinedString = _combineListItems (s);
802
+ if (combinedString.startsWith ('_:' )) {
803
+ return BNode (combinedString);
804
+ }
805
+ return item (combinedString);
810
806
}
811
807
}
812
808
@@ -1064,4 +1060,20 @@ class Graph {
1064
1060
String _getLangTag (String literal) {
1065
1061
return langTags.firstWhere ((element) => literal.contains ('@$element ' ));
1066
1062
}
1063
+
1064
+ /// Recursively combines all items in a list and its sub-items into a single string.
1065
+ ///
1066
+ /// This function traverses a list and concatenates all its elements,
1067
+ /// including elements of nested lists, into a single string.
1068
+ /// It handles various data types by converting them to their string representations.
1069
+ ///
1070
+ String _combineListItems (dynamic item) {
1071
+ if (item is List ) {
1072
+ // Recursively call combineListItems on each sub-item and join them into a single string.
1073
+ return item.map ((subItem) => _combineListItems (subItem)).join ('' );
1074
+ } else {
1075
+ // Convert non-list item to a string.
1076
+ return item.toString ();
1077
+ }
1078
+ }
1067
1079
}
0 commit comments