PageRenderTime 6224ms CodeModel.GetById 39ms RepoModel.GetById 0ms app.codeStats 0ms

/QueryMachine.XQuery/XQueryNodeIterator.cs

#
C# | 469 lines | 385 code | 75 blank | 9 comment | 42 complexity | b771a79394281c4412ad838c6912d2e2 MD5 | raw file
Possible License(s): CC-BY-SA-3.0
  1. // Copyright (c) 2009-2011, Semyon A. Chertkov (semyonc@gmail.com)
  2. // All rights reserved.
  3. //
  4. // This program is free software: you can redistribute it and/or modify
  5. // it under the terms of the GNU General Public License as published by
  6. // the Free Software Foundation, either version 3 of the License, or
  7. // any later version.
  8. using System;
  9. using System.Collections;
  10. using System.Collections.Generic;
  11. using System.Text;
  12. using System.Threading;
  13. using System.Threading.Tasks;
  14. using System.Diagnostics;
  15. using System.Xml;
  16. using System.Xml.Schema;
  17. using System.Xml.XPath;
  18. using DataEngine.CoreServices;
  19. namespace DataEngine.XQuery
  20. {
  21. public delegate void ChangeContextDelegate(XQueryNodeIterator iter);
  22. public interface IContextProvider
  23. {
  24. XPathItem Context { get; }
  25. int CurrentPosition { get; }
  26. int LastPosition { get; }
  27. }
  28. internal sealed class ContextProvider : IContextProvider
  29. {
  30. private XQueryNodeIterator m_iter;
  31. public ContextProvider(XQueryNodeIterator iter)
  32. {
  33. m_iter = iter;
  34. }
  35. #region IContextProvider Members
  36. public XPathItem Context
  37. {
  38. get
  39. {
  40. return m_iter.Current;
  41. }
  42. }
  43. public int CurrentPosition
  44. {
  45. get
  46. {
  47. return m_iter.CurrentPosition + 1;
  48. }
  49. }
  50. public int LastPosition
  51. {
  52. get
  53. {
  54. return m_iter.Count;
  55. }
  56. }
  57. #endregion
  58. }
  59. [DebuggerDisplay("{curr}")]
  60. [DebuggerTypeProxy(typeof(XQueryNodeIteratorDebugView))]
  61. public abstract class XQueryNodeIterator: ICloneable, IThreadCloneable, IEnumerable, IEnumerable<XPathItem>
  62. {
  63. internal int count = -1;
  64. private XPathItem curr;
  65. private int pos;
  66. private bool iteratorStarted;
  67. private bool iteratorFinished;
  68. public event ChangeContextDelegate OnChange;
  69. public XQueryNodeIterator()
  70. {
  71. }
  72. public abstract XQueryNodeIterator Clone();
  73. public virtual object ThreadClone()
  74. {
  75. return new BufferedNodeIterator(this);
  76. }
  77. public virtual int Count
  78. {
  79. get
  80. {
  81. if (this.count == -1)
  82. {
  83. count = 0;
  84. XQueryNodeIterator iter = Clone();
  85. while (iter.MoveNext())
  86. count++;
  87. }
  88. return count;
  89. }
  90. }
  91. public virtual bool IsSingleIterator
  92. {
  93. get
  94. {
  95. XQueryNodeIterator iter = Clone();
  96. if (iter.MoveNext() && !iter.MoveNext())
  97. return true;
  98. return false;
  99. }
  100. }
  101. public virtual bool IsRange
  102. {
  103. get
  104. {
  105. return false;
  106. }
  107. }
  108. public XPathItem Current
  109. {
  110. get
  111. {
  112. if (!iteratorStarted)
  113. throw new InvalidOperationException();
  114. return curr;
  115. }
  116. }
  117. public int CurrentPosition
  118. {
  119. get
  120. {
  121. if (!iteratorStarted)
  122. throw new InvalidOperationException();
  123. return pos;
  124. }
  125. }
  126. public virtual bool IsFinished
  127. {
  128. get
  129. {
  130. return iteratorFinished;
  131. }
  132. }
  133. public virtual int SequentialPosition
  134. {
  135. get
  136. {
  137. return CurrentPosition + 1;
  138. }
  139. }
  140. public virtual void ResetSequentialPosition()
  141. {
  142. return;
  143. }
  144. public virtual bool IsOrderedSet
  145. {
  146. get
  147. {
  148. return false;
  149. }
  150. }
  151. [DebuggerStepThrough]
  152. public bool MoveNext()
  153. {
  154. if (!iteratorStarted)
  155. {
  156. Init();
  157. pos = -1;
  158. iteratorStarted = true;
  159. }
  160. XPathItem item = GetNextItem();
  161. if (item != null)
  162. {
  163. pos++;
  164. curr = item;
  165. if (OnChange != null)
  166. OnChange(this);
  167. return true;
  168. }
  169. iteratorFinished = true;
  170. return false;
  171. }
  172. public virtual List<XPathItem> ToList()
  173. {
  174. XQueryNodeIterator iter = Clone();
  175. List<XPathItem> res = new List<XPathItem>();
  176. while (iter.MoveNext())
  177. res.Add(iter.Current.Clone());
  178. return res;
  179. }
  180. public abstract XQueryNodeIterator CreateBufferedIterator();
  181. protected virtual void Init()
  182. {
  183. }
  184. protected virtual XPathItem GetNextItem()
  185. {
  186. //Trace.WriteLine(String.Format("[{0}] {1} {2}",
  187. // Thread.CurrentThread.ManagedThreadId, GetHashCode(), GetType().Name));
  188. return NextItem();
  189. }
  190. protected abstract XPathItem NextItem();
  191. public static XQueryNodeIterator Create(object value)
  192. {
  193. if (value == Undefined.Value)
  194. return EmptyIterator.Shared;
  195. XQueryNodeIterator iter = value as XQueryNodeIterator;
  196. if (iter != null)
  197. return iter.Clone();
  198. XPathItem item = value as XPathItem;
  199. if (item == null)
  200. item = new XQueryItem(value);
  201. return new SingleIterator(item);
  202. }
  203. #region ICloneable Members
  204. object ICloneable.Clone()
  205. {
  206. return this.Clone();
  207. }
  208. #endregion
  209. #region IEnumerable Members
  210. public IEnumerator GetEnumerator()
  211. {
  212. return new Enumerator(this);
  213. }
  214. #endregion
  215. #region IEnumerable<XPathItem> Members
  216. IEnumerator<XPathItem> IEnumerable<XPathItem>.GetEnumerator()
  217. {
  218. return new Enumerator(this);
  219. }
  220. #endregion
  221. private class Enumerator : IEnumerator, IEnumerator<XPathItem>
  222. {
  223. private XQueryNodeIterator current;
  224. private bool iterationStarted;
  225. private XQueryNodeIterator original;
  226. public Enumerator(XQueryNodeIterator iter)
  227. {
  228. original = iter.Clone();
  229. }
  230. public object Current
  231. {
  232. get
  233. {
  234. if (!iterationStarted || current == null)
  235. throw new InvalidOperationException();
  236. return current.Current;
  237. }
  238. }
  239. [DebuggerStepThrough]
  240. public bool MoveNext()
  241. {
  242. if (!iterationStarted)
  243. {
  244. current = original.Clone();
  245. iterationStarted = true;
  246. }
  247. if (current != null && current.MoveNext())
  248. return true;
  249. current = null;
  250. return false;
  251. }
  252. public void Reset()
  253. {
  254. iterationStarted = false;
  255. }
  256. #region IEnumerator<XPathItem> Members
  257. XPathItem IEnumerator<XPathItem>.Current
  258. {
  259. get
  260. {
  261. if (!iterationStarted || current == null)
  262. throw new InvalidOperationException();
  263. return current.Current;
  264. }
  265. }
  266. #endregion
  267. #region IDisposable Members
  268. public void Dispose()
  269. {
  270. return;
  271. }
  272. #endregion
  273. }
  274. internal class SingleIterator : XQueryNodeIterator
  275. {
  276. private XPathItem _item;
  277. public SingleIterator(XPathItem item)
  278. {
  279. _item = item;
  280. }
  281. public override XQueryNodeIterator Clone()
  282. {
  283. return new SingleIterator(_item);
  284. }
  285. public override bool IsSingleIterator
  286. {
  287. get
  288. {
  289. return true;
  290. }
  291. }
  292. protected override XPathItem NextItem()
  293. {
  294. if (CurrentPosition == -1)
  295. return _item;
  296. return null;
  297. }
  298. public override XQueryNodeIterator CreateBufferedIterator()
  299. {
  300. return Clone();
  301. }
  302. }
  303. internal class XQueryNodeIteratorDebugView
  304. {
  305. private XQueryNodeIterator iter;
  306. public XQueryNodeIteratorDebugView(XQueryNodeIterator iter)
  307. {
  308. this.iter = iter;
  309. }
  310. [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
  311. public XPathItem[] Items
  312. {
  313. get
  314. {
  315. List<XPathItem> res = new List<XPathItem>();
  316. foreach (XPathItem item in iter)
  317. {
  318. if (res.Count == 10)
  319. break;
  320. res.Add(item.Clone());
  321. }
  322. return res.ToArray();
  323. }
  324. }
  325. public XPathItem Current
  326. {
  327. get
  328. {
  329. return iter.curr;
  330. }
  331. }
  332. public int CurrentPosition
  333. {
  334. get
  335. {
  336. return iter.pos;
  337. }
  338. }
  339. }
  340. public class Combinator
  341. {
  342. private XQueryNodeIterator[] baseIter;
  343. private XQueryNodeIterator[] curr;
  344. private XPathItem[] items;
  345. public Combinator(XQueryNodeIterator[] iter)
  346. {
  347. baseIter = iter;
  348. curr = new XQueryNodeIterator[iter.Length];
  349. curr[0] = iter[0].Clone();
  350. items = new XPathItem[iter.Length];
  351. }
  352. private bool Next(int index)
  353. {
  354. if (curr[index] != null && curr[index].MoveNext())
  355. return true;
  356. else
  357. if (index > 0)
  358. {
  359. if (Next(index - 1))
  360. {
  361. curr[index] = baseIter[index].Clone();
  362. if (curr[index].MoveNext())
  363. return true;
  364. }
  365. }
  366. return false;
  367. }
  368. public bool Next()
  369. {
  370. if (Next(baseIter.Length - 1))
  371. {
  372. for (int k = 0; k < curr.Length; k++)
  373. items[k] = curr[k].Current;
  374. return true;
  375. }
  376. return false;
  377. }
  378. public XPathItem[] Current
  379. {
  380. get
  381. {
  382. return items;
  383. }
  384. }
  385. public Combinator Clone()
  386. {
  387. XQueryNodeIterator[] iter = new XQueryNodeIterator[baseIter.Length];
  388. for (int k = 0; k < iter.Length; k++)
  389. iter[k] = baseIter[k].Clone();
  390. return new Combinator(iter);
  391. }
  392. }
  393. }
  394. }