PageRenderTime 55ms CodeModel.GetById 29ms RepoModel.GetById 0ms app.codeStats 0ms

/Libraries/core/net40/Query/Algebra/PropertyPathOperators.cs

http://dotnetrdf.codeplex.com
C# | 325 lines | 204 code | 25 blank | 96 comment | 25 complexity | 37def388b048453e46e769e40f1c9125 MD5 | raw file
Possible License(s): MIT
  1. /*
  2. dotNetRDF is free and open source software licensed under the MIT License
  3. -----------------------------------------------------------------------------
  4. Copyright (c) 2009-2012 dotNetRDF Project (dotnetrdf-developer@lists.sf.net)
  5. Permission is hereby granted, free of charge, to any person obtaining a copy
  6. of this software and associated documentation files (the "Software"), to deal
  7. in the Software without restriction, including without limitation the rights
  8. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. copies of the Software, and to permit persons to whom the Software is furnished
  10. to do so, subject to the following conditions:
  11. The above copyright notice and this permission notice shall be included in all
  12. copies or substantial portions of the Software.
  13. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  14. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  15. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  16. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  17. WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  18. CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  19. */
  20. using System;
  21. using System.Collections.Generic;
  22. using System.Linq;
  23. using VDS.RDF.Query.Paths;
  24. using VDS.RDF.Query.Patterns;
  25. namespace VDS.RDF.Query.Algebra
  26. {
  27. /// <summary>
  28. /// Interface for Property Path Operators
  29. /// </summary>
  30. public interface IPathOperator : ISparqlAlgebra
  31. {
  32. /// <summary>
  33. /// Gets the Path Start
  34. /// </summary>
  35. PatternItem PathStart
  36. {
  37. get;
  38. }
  39. /// <summary>
  40. /// Gets the Path End
  41. /// </summary>
  42. PatternItem PathEnd
  43. {
  44. get;
  45. }
  46. /// <summary>
  47. /// Gets the Property Path
  48. /// </summary>
  49. ISparqlPath Path
  50. {
  51. get;
  52. }
  53. }
  54. /// <summary>
  55. /// Abstract Base Class for Path Operators
  56. /// </summary>
  57. public abstract class BasePathOperator
  58. : IPathOperator
  59. {
  60. private PatternItem _start, _end;
  61. private ISparqlPath _path;
  62. private HashSet<String> _vars = new HashSet<string>();
  63. /// <summary>
  64. /// Creates a new Path Operator
  65. /// </summary>
  66. /// <param name="start">Path Start</param>
  67. /// <param name="path">Property Path</param>
  68. /// <param name="end">Path End</param>
  69. public BasePathOperator(PatternItem start, ISparqlPath path, PatternItem end)
  70. {
  71. this._start = start;
  72. this._end = end;
  73. this._path = path;
  74. if (this._start.VariableName != null) this._vars.Add(this._start.VariableName);
  75. if (this._end.VariableName != null) this._vars.Add(this._end.VariableName);
  76. }
  77. /// <summary>
  78. /// Gets the Path Start
  79. /// </summary>
  80. public PatternItem PathStart
  81. {
  82. get
  83. {
  84. return this._start;
  85. }
  86. }
  87. /// <summary>
  88. /// Gets the Path End
  89. /// </summary>
  90. public PatternItem PathEnd
  91. {
  92. get
  93. {
  94. return this._end;
  95. }
  96. }
  97. /// <summary>
  98. /// Gets the Property Path
  99. /// </summary>
  100. public ISparqlPath Path
  101. {
  102. get
  103. {
  104. return this._path;
  105. }
  106. }
  107. /// <summary>
  108. /// Evaluates the Property Path
  109. /// </summary>
  110. /// <param name="context">SPARQL Evaluation Context</param>
  111. /// <returns></returns>
  112. public abstract BaseMultiset Evaluate(SparqlEvaluationContext context);
  113. /// <summary>
  114. /// Gets the Variables used in the Algebra
  115. /// </summary>
  116. public IEnumerable<string> Variables
  117. {
  118. get
  119. {
  120. return this._vars;
  121. }
  122. }
  123. /// <summary>
  124. /// Transforms the Algebra back into a Query
  125. /// </summary>
  126. /// <returns></returns>
  127. public SparqlQuery ToQuery()
  128. {
  129. SparqlQuery q = new SparqlQuery();
  130. q.RootGraphPattern = this.ToGraphPattern();
  131. q.Optimise();
  132. return q;
  133. }
  134. /// <summary>
  135. /// Transforms the Algebra back into a Graph Pattern
  136. /// </summary>
  137. /// <returns></returns>
  138. public abstract GraphPattern ToGraphPattern();
  139. /// <summary>
  140. /// Gets the String representation of the Algebra
  141. /// </summary>
  142. /// <returns></returns>
  143. public abstract override string ToString();
  144. }
  145. /// <summary>
  146. /// Abstract Base Class for Arbitrary Length Path Operators
  147. /// </summary>
  148. public abstract class BaseArbitraryLengthPathOperator : BasePathOperator
  149. {
  150. /// <summary>
  151. /// Creates a new Arbitrary Lengh Path Operator
  152. /// </summary>
  153. /// <param name="start">Path Start</param>
  154. /// <param name="end">Path End</param>
  155. /// <param name="path">Property Path</param>
  156. public BaseArbitraryLengthPathOperator(PatternItem start, PatternItem end, ISparqlPath path)
  157. : base(start, path, end) { }
  158. /// <summary>
  159. /// Determines the starting points for Path evaluation
  160. /// </summary>
  161. /// <param name="context">Evaluation Context</param>
  162. /// <param name="paths">Paths</param>
  163. /// <param name="reverse">Whether to evaluate Paths in reverse</param>
  164. protected void GetPathStarts(SparqlEvaluationContext context, List<List<INode>> paths, bool reverse)
  165. {
  166. HashSet<KeyValuePair<INode, INode>> nodes = new HashSet<KeyValuePair<INode, INode>>();
  167. if (this.Path is Property)
  168. {
  169. INode predicate = ((Property)this.Path).Predicate;
  170. foreach (Triple t in context.Data.GetTriplesWithPredicate(predicate))
  171. {
  172. if (reverse)
  173. {
  174. nodes.Add(new KeyValuePair<INode, INode>(t.Object, t.Subject));
  175. }
  176. else
  177. {
  178. nodes.Add(new KeyValuePair<INode, INode>(t.Subject, t.Object));
  179. }
  180. }
  181. }
  182. else
  183. {
  184. BaseMultiset initialInput = context.InputMultiset;
  185. context.InputMultiset = new IdentityMultiset();
  186. VariablePattern x = new VariablePattern("?x");
  187. VariablePattern y = new VariablePattern("?y");
  188. Bgp bgp = new Bgp(new PropertyPathPattern(x, this.Path, y));
  189. BaseMultiset results = context.Evaluate(bgp);//bgp.Evaluate(context);
  190. context.InputMultiset = initialInput;
  191. if (!results.IsEmpty)
  192. {
  193. foreach (ISet s in results.Sets)
  194. {
  195. if (s["x"] != null && s["y"] != null)
  196. {
  197. if (reverse)
  198. {
  199. nodes.Add(new KeyValuePair<INode, INode>(s["y"], s["x"]));
  200. }
  201. else
  202. {
  203. nodes.Add(new KeyValuePair<INode, INode>(s["x"], s["y"]));
  204. }
  205. }
  206. }
  207. }
  208. }
  209. paths.AddRange(nodes.Select(kvp => new List<INode>(new INode[] { kvp.Key, kvp.Value })));
  210. }
  211. /// <summary>
  212. /// Evaluates a setp of the Path
  213. /// </summary>
  214. /// <param name="context">Context</param>
  215. /// <param name="path">Paths</param>
  216. /// <param name="reverse">Whether to evaluate Paths in reverse</param>
  217. /// <returns></returns>
  218. protected List<INode> EvaluateStep(SparqlEvaluationContext context, List<INode> path, bool reverse)
  219. {
  220. if (this.Path is Property)
  221. {
  222. HashSet<INode> nodes = new HashSet<INode>();
  223. INode predicate = ((Property)this.Path).Predicate;
  224. IEnumerable<Triple> ts = (reverse ? context.Data.GetTriplesWithPredicateObject(predicate, path[path.Count - 1]) : context.Data.GetTriplesWithSubjectPredicate(path[path.Count - 1], predicate));
  225. foreach (Triple t in ts)
  226. {
  227. if (reverse)
  228. {
  229. if (!path.Contains(t.Subject))
  230. {
  231. nodes.Add(t.Subject);
  232. }
  233. }
  234. else
  235. {
  236. if (!path.Contains(t.Object))
  237. {
  238. nodes.Add(t.Object);
  239. }
  240. }
  241. }
  242. return nodes.ToList();
  243. }
  244. else
  245. {
  246. HashSet<INode> nodes = new HashSet<INode>();
  247. BaseMultiset initialInput = context.InputMultiset;
  248. Multiset currInput = new Multiset();
  249. VariablePattern x = new VariablePattern("?x");
  250. VariablePattern y = new VariablePattern("?y");
  251. Set temp = new Set();
  252. if (reverse)
  253. {
  254. temp.Add("y", path[path.Count - 1]);
  255. }
  256. else
  257. {
  258. temp.Add("x", path[path.Count - 1]);
  259. }
  260. currInput.Add(temp);
  261. context.InputMultiset = currInput;
  262. Bgp bgp = new Bgp(new PropertyPathPattern(x, this.Path, y));
  263. BaseMultiset results = context.Evaluate(bgp);//bgp.Evaluate(context);
  264. context.InputMultiset = initialInput;
  265. if (!results.IsEmpty)
  266. {
  267. foreach (ISet s in results.Sets)
  268. {
  269. if (reverse)
  270. {
  271. if (s["x"] != null)
  272. {
  273. if (!path.Contains(s["x"]))
  274. {
  275. nodes.Add(s["x"]);
  276. }
  277. }
  278. }
  279. else
  280. {
  281. if (s["y"] != null)
  282. {
  283. if (!path.Contains(s["y"]))
  284. {
  285. nodes.Add(s["y"]);
  286. }
  287. }
  288. }
  289. }
  290. }
  291. return nodes.ToList();
  292. }
  293. }
  294. }
  295. }