Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
SparqlQuery.cs
1using System;
3using System.Text;
4using System.Threading.Tasks;
19using Waher.Things;
20
22{
26 public enum QueryType
27 {
31 Select,
32
36 Ask,
37
41 Construct
42 }
43
48 {
49 private readonly ScriptNode[] columns;
50 private readonly ScriptNode[] columnNames;
51 private readonly ScriptNode[] groupBy;
52 private readonly ScriptNode[] groupByNames;
53 private readonly ScriptNode[] from;
54 private readonly ISparqlPattern where;
55 private readonly ScriptNode having;
56 private readonly KeyValuePair<ScriptNode, bool>[] orderBy;
57 private readonly SparqlRegularPattern construct;
58 private readonly QueryType queryType;
59 private readonly int? limit;
60 private readonly int? offset;
61 private readonly bool distinct;
62 private readonly bool reduced;
63 private Dictionary<UriNode, ISemanticCube> namedGraphs;
64 private UriNode[] namedGraphNames;
65
87 public SparqlQuery(QueryType QueryType, bool Distinct, bool Reduced, ScriptNode[] Columns,
88 ScriptNode[] ColumnNames, ScriptNode[] From, Dictionary<UriNode, ISemanticCube> NamedGraphs,
89 ISparqlPattern Where, ScriptNode[] GroupBy, ScriptNode[] GroupByNames, ScriptNode Having,
90 KeyValuePair<ScriptNode, bool>[] OrderBy, int? Limit, int? Offset,
92 : base(Start, Length, Expression)
93 {
94 this.queryType = QueryType;
95 this.distinct = Distinct;
96 this.reduced = Reduced;
97 this.limit = Limit;
98 this.offset = Offset;
99 this.construct = Construct;
100
101 this.columns = Columns;
102 this.columns?.SetParent(this);
103
104 this.columnNames = ColumnNames;
105 this.columnNames?.SetParent(this);
106
107 this.from = From;
108 this.from?.SetParent(this);
109 this.namedGraphs = NamedGraphs;
110
111 this.namedGraphNames = new UriNode[NamedGraphs?.Count ?? 0];
112 NamedGraphs?.Keys.CopyTo(this.namedGraphNames, 0);
113
114 this.where = Where;
115 this.where?.SetParent(this);
116
117 this.groupBy = GroupBy;
118 this.groupBy?.SetParent(this);
119
120 this.groupByNames = GroupByNames;
121 this.groupByNames?.SetParent(this);
122
123 this.having = Having;
124 this.having?.SetParent(this);
125
126 this.orderBy = OrderBy;
127
128 if (!(this.orderBy is null))
129 {
130 foreach (KeyValuePair<ScriptNode, bool> P in this.orderBy)
131 P.Key.SetParent(this);
132 }
133 }
134
139 public override bool IsAsynchronous => true;
140
144 public UriNode[] NamedGraphNames => this.namedGraphNames;
145
152 {
153 return this.EvaluateAsync(Variables).Result;
154 }
155
162 public override Task<IElement> EvaluateAsync(Variables Variables)
163 {
164 return this.EvaluateAsync(Variables, null);
165 }
166
174 public async Task<IElement> EvaluateAsync(Variables Variables,
175 IEnumerable<Possibility> ExistingMatches)
176 {
177 SemanticDataSet DataSet = new SemanticDataSet();
178 object From;
179
180 if (this.from is null)
181 {
182 if (Variables.TryGetVariable(" Default Graph ", out Variable v))
183 From = v.ValueObject;
184 else
185 throw new ScriptRuntimeException("Default graph not defined.", this);
186
187 DataSet.Add(await this.GetDataSource(From, Variables, false));
188 }
189 else
190 {
191 foreach (ScriptNode Source in this.from)
192 {
193 From = (await Source.EvaluateAsync(Variables)).AssociatedObjectValue;
194 DataSet.Add(await this.GetDataSource(From, Variables, false));
195 }
196 }
197
198 IEnumerable<ISparqlResultRecord> Possibilities;
199
200 if (this.where is null)
201 Possibilities = ExistingMatches;
202 else
203 Possibilities = await this.where.Search(DataSet, Variables, ExistingMatches, this);
204
205 if (!(this.groupBy is null) && !(Possibilities is null))
206 {
207 Dictionary<string, bool> VectorProperties = null;
208
209 if (!(this.columns is null))
210 {
211 foreach (ScriptNode Node in this.columns)
212 {
213 if (!(Node is VariableReference))
214 {
215 Node.ForAllChildNodes((ScriptNode Descendant, out ScriptNode NewNode, object State) =>
216 {
217 if (Descendant is VariableReference Ref)
218 {
219 if (VectorProperties is null)
220 VectorProperties = new Dictionary<string, bool>();
221
222 VectorProperties[Ref.VariableName] = true;
223 }
224
225 NewNode = null;
226 return true;
227 }, null, SearchMethod.TreeOrder);
228 }
229 }
230 }
231
232 GroupResultSet GroupComparer = new GroupResultSet(this.groupBy, this.groupByNames);
233 SortedDictionary<ISparqlResultRecord, KeyValuePair<ISparqlResultRecord, ChunkedList<ISparqlResultRecord>>> Groups =
234 new SortedDictionary<ISparqlResultRecord, KeyValuePair<ISparqlResultRecord, ChunkedList<ISparqlResultRecord>>>(GroupComparer);
235 ChunkedList<ISparqlResultRecord> LastList = null;
236 ISparqlResultRecord LastRecord = null;
237 bool First = false;
238
239 foreach (ISparqlResultRecord P in Possibilities)
240 {
241 if (LastRecord is null || GroupComparer.Compare(LastRecord, P) != 0)
242 {
243 if (Groups.TryGetValue(P, out KeyValuePair<ISparqlResultRecord, ChunkedList<ISparqlResultRecord>> P2))
244 {
245 LastRecord = P2.Key;
246 LastList = P2.Value;
247 First = false;
248 }
249 else
250 {
251 LastList = new ChunkedList<ISparqlResultRecord>();
252 Groups[P] = new KeyValuePair<ISparqlResultRecord, ChunkedList<ISparqlResultRecord>>(P, LastList);
253 LastRecord = P;
254 First = true;
255 }
256 }
257
258 LastList.Add(P);
259
260 if (!(VectorProperties is null))
261 {
262 foreach (string VectorProperty in VectorProperties.Keys)
263 {
264 ISemanticElement Element = LastRecord[VectorProperty];
265 if (!(Element is SemanticElementVector Vector))
266 {
267 Vector = new SemanticElementVector();
268 LastRecord[VectorProperty] = Vector;
269 }
270
271 if (First)
272 Vector.Add(Element);
273 else
274 Vector.Add(P[VectorProperty]);
275 }
276 }
277
278 First = false;
279 }
280
281 Possibilities = Groups.Keys;
282
283 if (!(this.having is null))
284 {
286 ObjectProperties RecordVariables = null;
287
288 foreach (ISparqlResultRecord Record in Possibilities)
289 {
290 try
291 {
292 if (RecordVariables is null)
293 RecordVariables = new ObjectProperties(Record, Variables);
294 else
295 RecordVariables.Object = Record;
296
297 object Value = await EvaluateValue(RecordVariables, this.having);
298 if (Value is bool b && b)
299 Filtered.Add(Record);
300 }
301 catch (Exception)
302 {
303 // Ignore record
304 }
305 }
306
307 Possibilities = Filtered;
308 }
309 }
310
311 switch (this.queryType)
312 {
313 case QueryType.Ask:
314 if (!(Possibilities is null))
315 {
316 using (IEnumerator<ISparqlResultRecord> e = Possibilities.GetEnumerator())
317 {
318 return new ObjectValue(new SparqlResultSet(e.MoveNext()));
319 }
320 }
321
322 return new ObjectValue(new SparqlResultSet(false));
323
324 case QueryType.Select:
325 Dictionary<string, int> ColumnVariables = new Dictionary<string, int>();
327 ChunkedList<string> ColumnNames = new ChunkedList<string>();
328 string Name;
329 int i, c;
330 bool AllNames;
331
332 if (this.columns is null)
333 AllNames = true;
334 else
335 {
336 AllNames = false;
337
338 int Columns = this.columns.Length;
339
340 c = this.columnNames?.Length ?? 0;
341
342 for (i = 0; i < Columns; i++)
343 {
344 if (i < c && !(this.columnNames[i] is null))
345 {
346 if (this.columnNames[i] is VariableReference Ref2)
347 Name = Ref2.VariableName;
348 else
349 Name = ToString(await this.columnNames[i].EvaluateAsync(Variables));
350
351 ColumnVariables[Name] = i;
352 ColumnNames.Add(Name);
353 }
354 else
355 Name = null;
356
357 if (this.columns[i] is VariableReference Ref)
358 {
359 if (Name is null)
360 {
361 Name = Ref.VariableName;
362
363 ColumnVariables[Name] = i;
364 ColumnNames.Add(Name);
365 }
366 else
367 {
368 if (ColumnScript is null)
369 ColumnScript = new ChunkedList<KeyValuePair<ScriptNode, int>>();
370
371 ColumnScript.Add(new KeyValuePair<ScriptNode, int>(Ref, i));
372 }
373 }
374 else
375 {
376 if (ColumnScript is null)
377 ColumnScript = new ChunkedList<KeyValuePair<ScriptNode, int>>();
378
379 ColumnScript.Add(new KeyValuePair<ScriptNode, int>(this.columns[i], i));
380
381 if (Name is null)
382 {
383 Name = " c" + i.ToString();
384 ColumnNames.Add(Name);
385 }
386 }
387 }
388 }
389
390 List<ISparqlResultRecord> Records = new List<ISparqlResultRecord>();
391 bool MakeUnique = this.distinct || this.reduced;
392 Dictionary<string, bool> Distinct = MakeUnique ? new Dictionary<string, bool>() : null;
393 StringBuilder sb = MakeUnique ? new StringBuilder() : null;
394 ObjectProperties RecordVariables = null;
395
396 if (!(Possibilities is null))
397 {
398 foreach (ISparqlResultRecord P in Possibilities)
399 {
400 Dictionary<string, ISparqlResultItem> Record = new Dictionary<string, ISparqlResultItem>();
401
402 foreach (ISparqlResultItem Loop in P)
403 {
404 Name = Loop.Name;
405
406 if (ColumnVariables.TryGetValue(Name, out i))
407 Record[Name] = new SparqlResultItem(Name, Loop.Value, i);
408 else if (AllNames)
409 {
410 i = ColumnNames.Count;
411 ColumnNames.Add(Name);
412 ColumnVariables[Name] = i;
413
414 Record[Name] = new SparqlResultItem(Name, Loop.Value, i);
415 }
416 }
417
418 if (!(ColumnScript is null))
419 {
420 if (RecordVariables is null)
421 RecordVariables = new ObjectProperties(P, Variables);
422 else
423 RecordVariables.Object = P;
424
425 foreach (KeyValuePair<ScriptNode, int> P2 in ColumnScript)
426 {
427 Name = ColumnNames[P2.Value];
428 ISemanticElement Literal = await this.EvaluateSemanticElement(RecordVariables, P2.Key);
429
430 if (!(Literal is null))
431 {
432 Record[Name] = new SparqlResultItem(Name, Literal, P2.Value);
433 P[Name] = Literal;
434 }
435 }
436 }
437
438 if (MakeUnique)
439 {
440 bool First = true;
441
442 sb.Clear();
443
444 foreach (ISparqlResultItem Value in Record.Values)
445 {
446 if (First)
447 First = false;
448 else
449 sb.Append(';');
450
451 sb.Append(Value.Name);
452 sb.Append('=');
453 sb.Append(Value.Value?.ToString());
454 }
455
456 string Key = sb.ToString();
457
458 if (Distinct.ContainsKey(Key))
459 continue;
460
461 Distinct[Key] = true;
462 }
463
464 Records.Add(new SparqlPatternResultRecord(Record));
465 }
466 }
467
468 if (!(this.orderBy is null))
469 Records.Sort(new OrderResultSet(this.orderBy));
470
471 if (this.offset.HasValue || this.limit.HasValue)
472 {
473 int Offset = this.offset ?? 0;
474 int MaxCount = this.limit ?? int.MaxValue;
475 int Count = Records.Count;
476
477 while (Offset > 0 && Count > 0)
478 {
479 Records.RemoveAt(0);
480 Count--;
481 Offset--;
482 }
483
484 while (Count > MaxCount)
485 {
486 Records.RemoveAt(MaxCount);
487 Count--;
488 }
489 }
490
491 return new ObjectValue(new SparqlResultSet(ColumnNames.ToArray(), Array.Empty<Uri>(),
492 Records.ToArray()));
493
494 case QueryType.Construct:
495 Dictionary<string, string> BlankNodeDictionary = null;
497 IEnumerable<ISparqlResultRecord> Items = Possibilities;
498
499 RecordVariables = null;
500
501 if (!(Items is null))
502 {
503 if (!(this.orderBy is null))
504 {
505 List<ISparqlResultRecord> Ordered = new List<ISparqlResultRecord>();
506
507 foreach (ISparqlResultRecord Record in Items)
508 Ordered.Add(Record);
509
510 Ordered.Sort(new OrderResultSet(this.orderBy));
511 Items = Ordered;
512 }
513
514 int Offset = this.offset ?? 0;
515 int MaxCount = this.limit ?? int.MaxValue;
516
517 foreach (ISparqlResultRecord P in Items)
518 {
519 if (Offset > 0)
520 {
521 Offset--;
522 continue;
523 }
524
525 if (--MaxCount < 0)
526 break;
527
528 BlankNodeDictionary?.Clear();
529
530 if (RecordVariables is null)
531 RecordVariables = new ObjectProperties(P, Variables);
532 else
533 RecordVariables.Object = P;
534
535 foreach (ISemanticTriple T in this.construct.Triples)
536 {
537 ISemanticElement Subject = await this.EvaluateSemanticElement(RecordVariables, T.Subject);
538 if (Subject is null)
539 continue;
540 else if (Subject is BlankNode BnS)
541 {
542 if (BlankNodeDictionary is null)
543 BlankNodeDictionary = new Dictionary<string, string>();
544
545 if (!BlankNodeDictionary.TryGetValue(BnS.NodeId, out string NewLabel))
546 {
547 NewLabel = "n" + Guid.NewGuid().ToString();
548 BlankNodeDictionary[BnS.NodeId] = NewLabel;
549 }
550
551 Subject = new BlankNode(NewLabel);
552 }
553
554 ISemanticElement Predicate = await this.EvaluateSemanticElement(RecordVariables, T.Predicate);
555 if (Predicate is null)
556 continue;
557 else if (Predicate is BlankNode BnP)
558 {
559 if (BlankNodeDictionary is null)
560 BlankNodeDictionary = new Dictionary<string, string>();
561
562 if (!BlankNodeDictionary.TryGetValue(BnP.NodeId, out string NewLabel))
563 {
564 NewLabel = "n" + Guid.NewGuid().ToString();
565 BlankNodeDictionary[BnP.NodeId] = NewLabel;
566 }
567
568 Predicate = new BlankNode(NewLabel);
569 }
570
571 ISemanticElement Object = await this.EvaluateSemanticElement(RecordVariables, T.Object);
572 if (Object is null)
573 continue;
574 else if (Object is BlankNode BnO)
575 {
576 if (BlankNodeDictionary is null)
577 BlankNodeDictionary = new Dictionary<string, string>();
578
579 if (!BlankNodeDictionary.TryGetValue(BnO.NodeId, out string NewLabel))
580 {
581 NewLabel = "n" + Guid.NewGuid().ToString();
582 BlankNodeDictionary[BnO.NodeId] = NewLabel;
583 }
584
585 Object = new BlankNode(NewLabel);
586 }
587
588 Construction.Add(new SemanticTriple(Subject, Predicate, Object));
589 }
590 }
591 }
592
593 return new ObjectValue(new InMemorySemanticModel(Construction));
594
595 default:
596 throw new ScriptRuntimeException("Query type not supported.", this);
597 }
598 }
599
600 private async Task<ISemanticCube> GetDataSource(object From, Variables Variables,
601 bool NullIfNotFound)
602 {
603 if (From is UriNode UriNode)
604 return await this.LoadGraph(UriNode.Uri, Variables, NullIfNotFound);
605 else if (From is Uri Uri)
606 return await this.LoadGraph(Uri, Variables, NullIfNotFound);
607 else if (From is string s)
608 return await this.LoadGraph(new Uri(s, UriKind.RelativeOrAbsolute), Variables, NullIfNotFound);
609 else if (From is ISemanticCube Cube)
610 return Cube;
611 else if (From is ISemanticModel Model)
612 return await InMemorySemanticCube.Create(Model);
613
614 if (NullIfNotFound)
615 return null;
616 else
617 throw new ScriptRuntimeException("Graph not a semantic cube or semantic model.", this);
618 }
619
620 internal static async Task<object> EvaluateValue(Variables RecordVariables, ScriptNode Node)
621 {
622 try
623 {
624 return (await Node.EvaluateAsync(RecordVariables)).AssociatedObjectValue;
625 }
627 {
629 //object ReturnValue = ex.ReturnValue.AssociatedObjectValue;
630 //ScriptReturnValueException.Reuse(ex);
631 //return ReturnValue;
632 }
633 catch (ScriptBreakLoopException ex)
634 {
636 //ScriptBreakLoopException.Reuse(ex);
637 }
639 {
641 //ScriptContinueLoopException.Reuse(ex);
642 }
643 catch (Exception)
644 {
645 return null;
646 }
647 }
648
649 internal static async Task<object> EvaluateValue(Variables RecordVariables,
651 {
652 try
653 {
654 return (await Node.EvaluateAsync(RecordVariables, Cube, Query, P)).AssociatedObjectValue;
655 }
657 {
659 //object ReturnValue = ex.ReturnValue.AssociatedObjectValue;
660 //ScriptReturnValueException.Reuse(ex);
661 //return ReturnValue;
662 }
663 catch (ScriptBreakLoopException ex)
664 {
666 //ScriptBreakLoopException.Reuse(ex);
667 }
669 {
671 //ScriptContinueLoopException.Reuse(ex);
672 }
673 catch (Exception ex)
674 {
675 return ex;
676 }
677 }
678
679 internal Task<ISemanticElement> EvaluateSemanticElement(Variables RecordVariables, ISemanticElement Element)
680 {
681 if (Element is SemanticScriptElement ScriptElement)
682 return this.EvaluateSemanticElement(RecordVariables, ScriptElement.Node);
683 else
684 return Task.FromResult(Element);
685 }
686
687 internal async Task<ISemanticElement> EvaluateSemanticElement(Variables RecordVariables, ScriptNode Node)
688 {
689 object Value = await EvaluateValue(RecordVariables, Node);
690 if (Value is null)
691 return null;
692 else
693 return SemanticElements.Encapsulate(Value);
694 }
695
703 public override bool ForAllChildNodes(ScriptNodeEventHandler Callback, object State, SearchMethod Order)
704 {
705 if (Order == SearchMethod.DepthFirst)
706 {
707 if (!this.columns.ForAllChildNodes(Callback, State, Order))
708 return false;
709
710 if (!(this.where is null) && !this.where.ForAllChildNodes(Callback, State, Order))
711 return false;
712
713 if (!(this.construct is null) && !this.construct.ForAllChildNodes(Callback, State, Order))
714 return false;
715 }
716
717 if (!this.columns.ForAll(Callback, this, State, Order == SearchMethod.TreeOrder))
718 return false;
719
720 if (!(this.where is null) && !this.where.ForAll(Callback, State, Order))
721 return false;
722
723 if (!(this.construct is null) && !this.construct.ForAll(Callback, State, Order))
724 return false;
725
726 if (Order == SearchMethod.BreadthFirst)
727 {
728 if (!this.columns.ForAllChildNodes(Callback, State, Order))
729 return false;
730
731 if (!(this.where is null) && !this.where.ForAllChildNodes(Callback, State, Order))
732 return false;
733
734 if (!(this.construct is null) && !this.construct.ForAllChildNodes(Callback, State, Order))
735 return false;
736 }
737
738 return true;
739 }
740
742 public override bool Equals(object obj)
743 {
744 if (!(obj is SparqlQuery O) ||
745 !AreEqual(this.columns, O.columns) ||
746 ((this.where is null) ^ (O.where is null)) ||
747 ((this.construct is null) ^ (O.construct is null)) ||
748 this.distinct != O.distinct ||
749 this.reduced != O.reduced ||
750 !base.Equals(obj))
751 {
752 return false;
753 }
754
755 if (!(this.where is null) && !this.where.Equals(O.where))
756 return false;
757
758 if (!(this.construct is null) && !this.construct.Equals(O.construct))
759 return false;
760
761 return true;
762 }
763
765 public override int GetHashCode()
766 {
767 int Result = base.GetHashCode();
768
769 Result ^= Result << 5 ^ GetHashCode(this.columns);
770 Result ^= Result << 5 ^ this.distinct.GetHashCode();
771 Result ^= Result << 5 ^ this.reduced.GetHashCode();
772
773 if (!(this.where is null))
774 Result ^= Result << 5 ^ this.where.GetHashCode();
775
776 if (!(this.construct is null))
777 Result ^= Result << 5 ^ this.construct.GetHashCode();
778
779 return Result;
780 }
781
782 private async Task<ISemanticCube> LoadGraph(Uri Uri, Variables Variables, bool NullIfNotFound)
783 {
784 if (Variables.TryGetVariable(" " + Uri.ToString() + " ", out Variable v) &&
785 v.ValueObject is ISemanticCube Cube)
786 {
787 return Cube;
788 }
789
790 IGraphSource Source = await GetSourceHandler(Uri, NullIfNotFound);
791 if (Source is null)
792 return null;
793
794 if (Variables.TryGetVariable("QuickLoginUser", out v) &&
795 v.ValueObject is IRequestOrigin Caller)
796 {
797 return await Source.LoadGraph(Uri, this, NullIfNotFound, await Caller.GetOrigin());
798 }
799 else if (Variables.TryGetVariable("User", out v) &&
800 v.ValueObject is IRequestOrigin Caller2)
801 {
802 return await Source.LoadGraph(Uri, this, NullIfNotFound, await Caller2.GetOrigin());
803 }
804 else
805 return await Source.LoadGraph(Uri, this, NullIfNotFound, RequestOrigin.Empty);
806 }
807
815 public static async Task<IGraphSource> GetSourceHandler(Uri Uri, bool NullIfNotFound)
816 {
817 GraphReference Ref = await Database.FindFirstIgnoreRest<GraphReference>(
818 new FilterFieldEqualTo("GraphUri", Uri.AbsoluteUri));
819
820 if (!(Ref is null))
821 return await Ref.GetGraphSource();
822
823 IGraphSource Source = Types.FindBest<IGraphSource, Uri>(Uri);
824
825 if (Source is null && !NullIfNotFound)
826 throw new InvalidOperationException("Unable to get access to graph source: " + Uri.ToString());
827
828 return Source;
829 }
830
836 internal UriNode GetGraphName(object Name)
837 {
838 if (Name is UriNode UriNode)
839 return UriNode;
840 else if (Name is Uri Uri)
841 return new UriNode(Uri, Uri.ToString());
842 else if (Name is string s && System.Uri.TryCreate(s, UriKind.RelativeOrAbsolute, out Uri))
843 return new UriNode(Uri, s);
844 else
845 return null;
846 }
847
854 internal Task<ISemanticCube> GetNamedGraph(object Name, Variables Variables)
855 {
856 UriNode UriNode = this.GetGraphName(Name);
857 if (UriNode is null)
858 return Task.FromResult<ISemanticCube>(null);
859 else
860 return this.GetNamedGraph(UriNode, Variables);
861 }
862
869 internal async Task<ISemanticCube> GetNamedGraph(UriNode Uri, Variables Variables)
870 {
871 ISemanticCube Cube;
872
873 if (this.namedGraphs is null)
874 this.namedGraphs = new Dictionary<UriNode, ISemanticCube>();
875
876 lock (this.namedGraphs)
877 {
878 if (!(this.namedGraphs is null) &&
879 this.namedGraphs.TryGetValue(Uri, out Cube) &&
880 !(Cube is null))
881 {
882 return Cube;
883 }
884 }
885
886 Cube = await this.GetDataSource(Uri, Variables, true);
887 if (Cube is null)
888 Cube = new InMemorySemanticCube();
889
890 lock (this.namedGraphs)
891 {
892 this.namedGraphs[Uri] = Cube;
893 }
894
895 return Cube;
896 }
897
902 internal Task LoadUnloadedNamedGraphs(Variables Variables)
903 {
904 ChunkedList<UriNode> NotLoaded = null;
905
906 lock (this.namedGraphs)
907 {
908 foreach (KeyValuePair<UriNode, ISemanticCube> P in this.namedGraphs)
909 {
910 if (P.Value is null)
911 {
912 if (NotLoaded is null)
913 NotLoaded = new ChunkedList<UriNode>();
914
915 NotLoaded.Add(P.Key);
916 }
917 }
918 }
919
920 if (NotLoaded is null)
921 return Task.CompletedTask;
922
923 return this.LoadUnloadedNamedGraphs(Variables, NotLoaded.ToArray());
924 }
925
931 internal Task LoadUnloadedNamedGraphs(Variables Variables, params string[] Names)
932 {
933 return this.LoadUnloadedNamedGraphs(Variables, Convert(Names));
934 }
935
941 internal Task LoadUnloadedNamedGraphs(Variables Variables, params Uri[] Names)
942 {
943 return this.LoadUnloadedNamedGraphs(Variables, Convert(Names));
944 }
945
951 internal async Task LoadUnloadedNamedGraphs(Variables Variables, params UriNode[] Names)
952 {
954
955 foreach (UriNode Name in Names)
956 Tasks.Add(this.GetNamedGraph(Name, Variables));
957
958 await Task.WhenAll(Tasks.ToArray());
959 }
960
966 public void RegisterNamedGraph(params string[] Names)
967 {
968 this.RegisterNamedGraph(Convert(Names));
969 }
970
971 private static UriNode[] Convert(string[] Names)
972 {
973 int i, c = Names.Length;
974 UriNode[] Nodes = new UriNode[Names.Length];
975
976 for (i = 0; i < c; i++)
977 {
978 if (!Uri.TryCreate(Names[i], UriKind.RelativeOrAbsolute, out Uri Name))
979 throw new ArgumentException("Not a valid URI.", nameof(Names));
980
981 Nodes[i] = new UriNode(Name, Names[i]);
982 }
983
984 return Nodes;
985 }
986
992 public void RegisterNamedGraph(params Uri[] Names)
993 {
994 this.RegisterNamedGraph(Convert(Names));
995 }
996
997 private static UriNode[] Convert(Uri[] Names)
998 {
999 int i, c = Names.Length;
1000 UriNode[] Nodes = new UriNode[Names.Length];
1001
1002 for (i = 0; i < c; i++)
1003 Nodes[i] = new UriNode(Names[i], Names[i].ToString());
1004
1005 return Nodes;
1006 }
1007
1013 public void RegisterNamedGraph(params UriNode[] Names)
1014 {
1015 if (this.namedGraphs is null)
1016 this.namedGraphs = new Dictionary<UriNode, ISemanticCube>();
1017
1018 lock (this.namedGraphs)
1019 {
1020 foreach (UriNode Name in Names)
1021 {
1022 if (!this.namedGraphs.ContainsKey(Name))
1023 this.namedGraphs[Name] = null;
1024 }
1025
1026 this.namedGraphNames = new UriNode[this.namedGraphs.Count];
1027 this.namedGraphs.Keys.CopyTo(this.namedGraphNames, 0);
1028 }
1029 }
1030
1031 }
1032}
static async Task< InMemorySemanticCube > Create(ISemanticModel Model)
Creates an in-memory semantic cube from a semantic model.
Represents a blank node
Definition: BlankNode.cs:7
static ISemanticElement Encapsulate(object Value)
Encapsulates an object as a semantic element.
void Add(ISemanticCube Source)
Adds a source to the data set.
Contains a record from the results of a SPARQL query.
Contains an item in a record from the results of a SPARQL query.
Contains the results of a SPARQL query. https://www.w3.org/TR/2023/WD-sparql12-results-xml-20230516/ ...
Static interface for database persistence. In order to work, a database provider has to be assigned t...
Definition: Database.cs:21
This filter selects objects that have a named field equal to a given value.
A chunked list is a linked list of chunks of objects of type T .
Definition: ChunkedList.cs:54
int Count
Number of elements in collection.
Definition: ChunkedList.cs:68
void Add(T Item)
Adds an item to the collection.
Definition: ChunkedList.cs:272
T[] ToArray()
Returns an array containing all elements of the collection.
Static class that dynamically manages types and interfaces available in the runtime environment.
Definition: Types.cs:15
Base class for all types of elements.
Definition: Element.cs:14
IElement LoopValue
Value to include in the loop's result.
IElement LoopValue
Value to include in the loop's result.
Class managing a script expression.
Definition: Expression.cs:41
Base class for all nodes in a parsed script tree.
Definition: ScriptNode.cs:69
bool ForAllChildNodes(ScriptNodeEventHandler Callback, object State, bool DepthFirst)
Calls the callback method for all child nodes.
Definition: ScriptNode.cs:243
int Length
Length of expression covered by node.
Definition: ScriptNode.cs:101
override string ToString()
Definition: ScriptNode.cs:359
static bool AreEqual(ScriptNode S1, ScriptNode S2)
Compares if two script nodes are equal.
Definition: ScriptNode.cs:275
int Start
Start position in script expression.
Definition: ScriptNode.cs:92
void SetParent(ScriptNode Parent)
Sets the parent node. Can only be used when expression is being parsed or created.
Definition: ScriptNode.cs:132
virtual Task< IElement > EvaluateAsync(Variables Variables)
Evaluates the node, using the variables provided in the Variables collection. This method should be ...
Definition: ScriptNode.cs:158
Represents a variable reference.
Comparer for grouping a SPARQL result set.
Comparer for ordering a SPARQL result set.
Represents a possible solution during SPARQL evaluation.
Definition: Possibility.cs:13
Contains a reference to a graph in the graph store.
async Task< IGraphSource > GetGraphSource()
Gets a Graph Source object corresponding to the graph referenced by the object.
async Task< IElement > EvaluateAsync(Variables Variables, IEnumerable< Possibility > ExistingMatches)
Evaluates the node asynchronously, using the variables provided in the Variables collection.
Definition: SparqlQuery.cs:174
static async Task< IGraphSource > GetSourceHandler(Uri Uri, bool NullIfNotFound)
Gets a graph source handler, given the Graph URI
Definition: SparqlQuery.cs:815
void RegisterNamedGraph(params UriNode[] Names)
Registers implicitly defined named graphs, that may be used by GRAPH patterns, even if they are not n...
override bool ForAllChildNodes(ScriptNodeEventHandler Callback, object State, SearchMethod Order)
Calls the callback method for all child nodes.
Definition: SparqlQuery.cs:703
override Task< IElement > EvaluateAsync(Variables Variables)
Evaluates the node asynchronously, using the variables provided in the Variables collection.
Definition: SparqlQuery.cs:162
void RegisterNamedGraph(params string[] Names)
Registers implicitly defined named graphs, that may be used by GRAPH patterns, even if they are not n...
Definition: SparqlQuery.cs:966
void RegisterNamedGraph(params Uri[] Names)
Registers implicitly defined named graphs, that may be used by GRAPH patterns, even if they are not n...
Definition: SparqlQuery.cs:992
SparqlQuery(QueryType QueryType, bool Distinct, bool Reduced, ScriptNode[] Columns, ScriptNode[] ColumnNames, ScriptNode[] From, Dictionary< UriNode, ISemanticCube > NamedGraphs, ISparqlPattern Where, ScriptNode[] GroupBy, ScriptNode[] GroupByNames, ScriptNode Having, KeyValuePair< ScriptNode, bool >[] OrderBy, int? Limit, int? Offset, SparqlRegularPattern Construct, int Start, int Length, Expression Expression)
Executes a SPARQL query.
Definition: SparqlQuery.cs:87
override IElement Evaluate(Variables Variables)
Evaluates the node, using the variables provided in the Variables collection.
Definition: SparqlQuery.cs:151
UriNode[] NamedGraphNames
Names of named graphs, may be null.
Definition: SparqlQuery.cs:144
override bool IsAsynchronous
If the node (or its decendants) include asynchronous evaluation. Asynchronous nodes should be evaluat...
Definition: SparqlQuery.cs:139
Represents one record.
Definition: Record.cs:9
Executes a SELECT statement against the object database.
Definition: Select.cs:21
Contains information about a variable.
Definition: Variable.cs:10
Collection of variables.
Definition: Variables.cs:25
virtual bool TryGetVariable(string Name, out Variable Variable)
Tries to get a variable object, given its name.
Definition: Variables.cs:56
Tokens available in request.
Definition: RequestOrigin.cs:9
static readonly RequestOrigin Empty
Empty request origin.
Interface for semantic cubes.
Interface for semantic nodes.
Interface for semantic models.
Interface for semantic triples.
ISemanticElement Object
Object element
ISemanticElement Predicate
Predicate element
ISemanticElement Subject
Subject element
Interface for items in a record from the results of a SPARQL query.
string Name
Name of item in record.
ISemanticElement Value
Value of item in record.
Interface for result records of a SPARQL query.
Basic interface for all types of elements.
Definition: IElement.cs:21
object AssociatedObjectValue
Associated object value.
Definition: IElement.cs:34
Interface for script nodes with asynchronous evaluation
Task< IElement > EvaluateAsync(Variables Variables, ISemanticCube Cube, SparqlQuery Query, Possibility Possibility)
Evaluates the node, using the variables provided in the Variables collection.
Task< ISemanticCube > LoadGraph(Uri Source, ScriptNode Node, bool NullIfNotFound, RequestOrigin Caller)
Loads the graph
void SetParent(ScriptNode Parent)
Sets the parent node. Can only be used when expression is being parsed or created.
Interface for requestors that can act as an origin for distributed requests.
delegate bool ScriptNodeEventHandler(ScriptNode Node, out ScriptNode NewNode, object State)
Delegate for ScriptNode callback methods.
SearchMethod
Method to traverse the expression structure
Definition: ScriptNode.cs:38
QueryType
SPARQL query type.
Definition: SparqlQuery.cs:27