2006-01-11 Atsushi Enomoto <atsushi@ximian.com>
[mono.git] / mcs / class / System.XML / System.Xml.XPath / Iterator.cs
1 //
2 // System.Xml.XPath.BaseIterator
3 //
4 // Author:
5 //   Piers Haken (piersh@friskit.com)
6 //   Atsushi Enomoto (atsushi@ximian.com)
7 //
8 // (C) 2002 Piers Haken
9 // (C) 2003 Atsushi Enomoto
10 //
11
12 //
13 // Permission is hereby granted, free of charge, to any person obtaining
14 // a copy of this software and associated documentation files (the
15 // "Software"), to deal in the Software without restriction, including
16 // without limitation the rights to use, copy, modify, merge, publish,
17 // distribute, sublicense, and/or sell copies of the Software, and to
18 // permit persons to whom the Software is furnished to do so, subject to
19 // the following conditions:
20 // 
21 // The above copyright notice and this permission notice shall be
22 // included in all copies or substantial portions of the Software.
23 // 
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 //
32
33 using System;
34 using System.Collections;
35 using System.Xml;
36 using System.Xml.XPath;
37 using System.Xml.Xsl;
38
39 #if NET_2_0
40 using NSResolver = System.Xml.IXmlNamespaceResolver;
41 #else
42 using NSResolver = System.Xml.XmlNamespaceManager;
43 #endif
44
45 namespace System.Xml.XPath
46 {
47         internal abstract class BaseIterator : XPathNodeIterator
48         {
49                 NSResolver _nsm;
50                 int position;
51
52                 internal BaseIterator (BaseIterator other)
53                 {
54                         _nsm = other._nsm;
55                         position = other.position;
56                 }
57                 internal BaseIterator (NSResolver nsm)
58                 {
59                         _nsm = nsm;
60                 }
61
62                 public NSResolver NamespaceManager
63                 {
64                         get { return _nsm; }
65                         set { _nsm = value; }
66                 }
67
68                 public virtual bool ReverseAxis {
69                         get { return false; }
70                 }
71
72                 public int ComparablePosition {
73                         get {
74                                 if (ReverseAxis) {
75                                         int diff = Count - CurrentPosition + 1;
76                                         return diff < 1 ? 1 : diff;
77                                 }
78                                 else
79                                         return CurrentPosition;
80                         }
81                 }
82
83                 public override int CurrentPosition {
84                         get { return position; }
85                 }
86
87                 public override bool MoveNext ()
88                 {
89                         if (!MoveNextCore ())
90                                 return false;
91                         position++;
92                         if (Current != null &&
93                                 Current.NodeType == XPathNodeType.Whitespace &&
94                                 _nsm is XsltContext &&
95                                 !((XsltContext) _nsm).PreserveWhitespace (Current))
96                                 return MoveNext ();
97                         return true;
98                 }
99
100                 public abstract bool MoveNextCore ();
101
102                 public override string ToString ()
103                 {
104                         if (Current != null)
105                                 return Current.NodeType.ToString () + "[" + CurrentPosition + "] : " + Current.Name + " = " + Current.Value;
106                         else
107                                 return this.GetType().ToString () + "[" + CurrentPosition + "]";
108                 }
109         }
110
111         internal class WrapperIterator : BaseIterator
112         {
113                 XPathNodeIterator iter;
114
115                 public WrapperIterator (XPathNodeIterator iter, NSResolver nsm)
116                         : base (nsm)
117                 {
118                         this.iter = iter;
119                 }
120
121                 private WrapperIterator (WrapperIterator other)
122                         : base (other)
123                 {
124                         iter = other.iter.Clone ();
125                 }
126
127                 public override XPathNodeIterator Clone ()
128                 {
129                         return new WrapperIterator (this);
130                 }
131
132                 public override bool MoveNextCore ()
133                 {
134                         return iter.MoveNext ();
135                 }
136
137                 public override XPathNavigator Current {
138                         get { return iter.Current; }
139                 }
140         }
141
142         internal abstract class SimpleIterator : BaseIterator
143         {
144                 protected readonly XPathNavigator _nav;
145                 protected XPathNavigator _current;
146
147                 public SimpleIterator (BaseIterator iter) : base (iter.NamespaceManager)
148                 {
149                         _nav = iter.Current.Clone ();
150                 }
151                 protected SimpleIterator (SimpleIterator other, bool clone) : base (other)
152                 {
153                         _nav = other._nav.Clone ();
154                 }
155                 public SimpleIterator (XPathNavigator nav, NSResolver nsm) : base (nsm)
156                 {
157                         _nav = nav.Clone ();
158                 }
159
160                 public override XPathNavigator Current {
161                         get {
162                                 if (_current == null) // position == 0
163                                         _current = _nav.Clone ();
164                                 return _current;
165                         }
166                 }
167         }
168
169         internal class SelfIterator : SimpleIterator
170         {
171                 public SelfIterator (BaseIterator iter) : base (iter) {}
172                 public SelfIterator (XPathNavigator nav, NSResolver nsm) : base (nav, nsm) {}
173                 protected SelfIterator (SelfIterator other, bool clone) : base (other, true) 
174                 {
175                 }
176
177                 public override XPathNodeIterator Clone () { return new SelfIterator (this, true); }
178                 public override bool MoveNextCore ()
179                 {
180                         if (CurrentPosition == 0)
181                         {
182                                 return true;
183                         }
184                         return false;
185                 }
186
187                 public override XPathNavigator Current {
188                         get { return _nav; }
189                 }
190         }
191
192         internal class NullIterator : SelfIterator
193         {
194                 public NullIterator (BaseIterator iter) : base (iter) {}
195                 public NullIterator (XPathNavigator nav) : this (nav, null) {}
196                 public NullIterator (XPathNavigator nav, NSResolver nsm) : base (nav, nsm) {}
197                 private NullIterator (NullIterator other) : base (other, true) {}
198                 public override XPathNodeIterator Clone () { return new NullIterator (this); }
199                 public override bool MoveNextCore ()
200                 {
201                         return false;
202                 }
203         }
204
205         internal class ParensIterator : BaseIterator
206         {
207                 BaseIterator _iter;
208
209                 public ParensIterator (BaseIterator iter) : base (iter.NamespaceManager) 
210                 {
211                         _iter = iter;
212                 }
213                 private ParensIterator (ParensIterator other) : base (other) 
214                 {
215                         _iter = (BaseIterator) other._iter.Clone ();
216                 }
217                 public override XPathNodeIterator Clone () { return new ParensIterator (this); }
218                 public override bool MoveNextCore ()
219                 {
220                         return _iter.MoveNext ();
221                 }
222
223                 public override XPathNavigator Current { get { return _iter.Current; }}
224
225                 public override int Count { get { return _iter.Count; } }
226         }
227
228         internal class ParentIterator : SimpleIterator
229         {
230                 bool canMove;
231                 public ParentIterator (BaseIterator iter) : base (iter)
232                 {
233                         canMove = _nav.MoveToParent ();
234                         _current = _nav;
235                 }
236                 private ParentIterator (ParentIterator other, bool dummy) : base (other, true)
237                 {
238                         _current = _nav;
239                         canMove = other.canMove;
240                 }
241                 public ParentIterator (XPathNavigator nav, NSResolver nsm) : base (nav, nsm) {}
242                 public override XPathNodeIterator Clone () { return new ParentIterator (this, true); }
243                 public override bool MoveNextCore ()
244                 {
245                         if (!canMove)
246                                 return false;
247                         canMove = false;
248                         return true;
249                 }
250         }
251
252         internal class ChildIterator : SimpleIterator
253         {
254                 public ChildIterator (BaseIterator iter) : base (iter) {}
255                 private ChildIterator (ChildIterator other) : base (other, true) {}
256                 public override XPathNodeIterator Clone () { return new ChildIterator (this); }
257                 public override bool MoveNextCore ()
258                 {
259                         bool fSuccess = (CurrentPosition == 0) ? _nav.MoveToFirstChild () : _nav.MoveToNext ();
260                         if (fSuccess) {
261                                 Current.MoveTo (_nav);
262                         }
263                         return fSuccess;
264                 }
265         }
266
267         internal class FollowingSiblingIterator : SimpleIterator
268         {
269                 public FollowingSiblingIterator (BaseIterator iter) : base (iter) {}
270                 private FollowingSiblingIterator (FollowingSiblingIterator other) : base (other, true) {}
271                 public override XPathNodeIterator Clone () { return new FollowingSiblingIterator (this); }
272                 public override bool MoveNextCore ()
273                 {
274                         switch (_nav.NodeType) {
275                         case XPathNodeType.Attribute:
276                         case XPathNodeType.Namespace:
277                                 // They have no siblings.
278                                 return false;
279                         }
280                         if (_nav.MoveToNext ())
281                         {
282                                 Current.MoveTo (_nav);
283                                 return true;
284                         }
285                         return false;
286                 }
287         }
288
289         internal class PrecedingSiblingIterator : SimpleIterator
290         {
291                 bool finished;
292                 bool started;
293                 XPathNavigator startPosition;
294
295                 public PrecedingSiblingIterator (BaseIterator iter) : base (iter)
296                 {
297                         startPosition = iter.Current.Clone ();
298                 }
299                 private PrecedingSiblingIterator (PrecedingSiblingIterator other) : base (other, true) 
300                 {
301                         startPosition = other.startPosition;
302                         started = other.started;
303                         finished = other.finished;
304                 }
305
306                 public override XPathNodeIterator Clone () { return new PrecedingSiblingIterator (this); }
307                 public override bool MoveNextCore ()
308                 {
309                         if (finished)
310                                 return false;
311                         if (!started) {
312                                 started = true;
313                                 switch (_nav.NodeType) {
314                                 case XPathNodeType.Attribute:
315                                 case XPathNodeType.Namespace:
316                                         // They have no siblings.
317                                         finished = true;
318                                         return false;
319                                 }
320
321                                 _nav.MoveToFirst ();
322                                 if (!_nav.IsSamePosition (startPosition)) {
323                                         Current.MoveTo (_nav);
324                                         return true;
325                                 }
326                         } else {
327                                 if (!_nav.MoveToNext ()) {
328                                         finished = true;
329                                         return false;
330                                 }
331                         }
332                         if (_nav.ComparePosition (startPosition) != XmlNodeOrder.Before) {
333                                 // Note that if _nav contains only 1 node, it won't be Same.
334                                 finished = true;
335                                 return false;
336                         } else {
337                                 Current.MoveTo (_nav);
338                                 return true;
339                         }
340                 }
341                 public override bool ReverseAxis {
342                         get { return true; }
343                 }
344         }
345
346         internal class AncestorIterator : SimpleIterator
347         {
348                 int currentPosition;
349                 ArrayList navigators;
350                 XPathNavigator startPosition;
351
352                 public AncestorIterator (BaseIterator iter) : base (iter)
353                 {
354                         startPosition = iter.Current.Clone ();
355                 }
356
357                 private AncestorIterator (AncestorIterator other)
358                         : base (other, true)
359                 {
360                         startPosition = other.startPosition;
361                         if (other.navigators != null)
362                                 navigators = (ArrayList) other.navigators;
363                         currentPosition = other.currentPosition;
364                 }
365
366                 public override XPathNodeIterator Clone ()
367                 {
368                         return new AncestorIterator (this);
369                 }
370
371                 private void CollectResults ()
372                 {
373                         navigators = new ArrayList ();
374
375                         XPathNavigator ancestors = startPosition.Clone ();
376                         if (!ancestors.MoveToParent ())
377                                 return;
378                         while (ancestors.NodeType != XPathNodeType.Root) {
379                                 navigators.Add (ancestors.Clone ());
380                                 ancestors.MoveToParent ();
381                         }
382                         currentPosition = navigators.Count;
383                 }
384
385                 public override bool MoveNextCore ()
386                 {
387                         if (navigators == null) {
388                                 CollectResults ();
389                                 if (startPosition.NodeType != XPathNodeType.Root) {
390                                         // First time it returns Root
391                                         _nav.MoveToRoot ();
392                                         Current.MoveTo (_nav);
393                                         return true;
394                                 }
395                         }
396                         if (currentPosition == 0)
397                                 return false;
398                         _nav.MoveTo ((XPathNavigator) navigators [--currentPosition]);
399                         Current.MoveTo (_nav);
400                         return true;
401                 }
402
403                 public override bool ReverseAxis {
404                         get { return true; }
405                 }
406
407                 public override int Count {
408                         get {
409                                 if (navigators == null)
410                                         CollectResults ();
411                                 return navigators.Count;
412                         }
413                 }
414         }
415
416         internal class AncestorOrSelfIterator : SimpleIterator
417         {
418                 int currentPosition;
419                 ArrayList navigators;
420                 XPathNavigator startPosition;
421
422                 public AncestorOrSelfIterator (BaseIterator iter) : base (iter)
423                 {
424                         startPosition = iter.Current.Clone ();
425                 }
426
427                 private AncestorOrSelfIterator (AncestorOrSelfIterator other)
428                         : base (other, true)
429                 {
430                         startPosition = other.startPosition;
431                         if (other.navigators != null)
432                                 navigators = (ArrayList) other.navigators.Clone ();
433                         currentPosition = other.currentPosition;
434                 }
435
436                 public override XPathNodeIterator Clone ()
437                 {
438                         return new AncestorOrSelfIterator (this);
439                 }
440
441                 private void CollectResults ()
442                 {
443                         navigators = new ArrayList ();
444
445                         XPathNavigator ancestors = startPosition.Clone ();
446                         if (!ancestors.MoveToParent ())
447                                 return;
448                         while (ancestors.NodeType != XPathNodeType.Root) {
449                                 navigators.Add (ancestors.Clone ());
450                                 ancestors.MoveToParent ();
451                         }
452                         currentPosition = navigators.Count;
453                 }
454
455                 public override bool MoveNextCore ()
456                 {
457                         if (navigators == null) {
458                                 CollectResults ();
459                                 if (startPosition.NodeType != XPathNodeType.Root) {
460                                         // First time it returns Root
461                                         _nav.MoveToRoot ();
462                                         Current.MoveTo (_nav);
463                                         return true;
464                                 }
465                         }
466                         if (currentPosition == -1)
467                                 return false;
468                         if (currentPosition-- == 0) {
469                                 _nav.MoveTo (startPosition);
470                                 Current.MoveTo (_nav);
471                                 return true; // returns self.
472                         }
473                         _nav.MoveTo ((XPathNavigator) navigators [currentPosition]);
474                         Current.MoveTo (_nav);
475                         return true;
476                 }
477
478                 public override bool ReverseAxis {
479                         get { return true; }
480                 }
481
482                 public override int Count {
483                         get {
484                                 if (navigators == null)
485                                         CollectResults ();
486                                 return navigators.Count + 1;
487                         }
488                 }
489         }
490
491         internal class DescendantIterator : SimpleIterator
492         {
493                 private int _depth;
494                 private bool _finished;
495
496                 public DescendantIterator (BaseIterator iter) : base (iter) {}
497
498                 private DescendantIterator (DescendantIterator other) : base (other)
499                 {
500                         _depth = other._depth;
501                         _finished = other._finished;
502                 }
503
504                 public override XPathNodeIterator Clone () { return new DescendantIterator (this); }
505
506                 public override bool MoveNextCore ()
507                 {
508                         if (_finished)
509                                 return false;
510
511                         if (_nav.MoveToFirstChild ())
512                         {
513                                 _depth ++;
514                                 Current.MoveTo (_nav);
515                                 return true;
516                         }
517                         while (_depth != 0)
518                         {
519                                 if (_nav.MoveToNext ())
520                                 {
521                                         Current.MoveTo (_nav);
522                                         return true;
523                                 }
524                                 if (!_nav.MoveToParent ())      // should NEVER fail!
525                                         throw new XPathException ("There seems some bugs on the XPathNavigator implementation class: " + _nav.GetType ());
526                                 _depth --;
527                         }
528                         _finished = true;
529                         return false;
530                 }
531         }
532
533         internal class DescendantOrSelfIterator : SimpleIterator
534         {
535                 private int _depth;
536                 private bool _finished;
537
538                 public DescendantOrSelfIterator (BaseIterator iter) : base (iter) {}
539
540                 private DescendantOrSelfIterator (DescendantOrSelfIterator other) : base (other, true)
541                 {
542                         _depth = other._depth;
543                 }
544
545                 public override XPathNodeIterator Clone () { return new DescendantOrSelfIterator (this); }
546
547                 public override bool MoveNextCore ()
548                 {
549                         if (_finished)
550                                 return false;
551
552                         if (CurrentPosition == 0)
553                         {
554                                 // self
555                                 Current.MoveTo (_nav);
556                                 return true;
557                         }
558                         if (_nav.MoveToFirstChild ())
559                         {
560                                 _depth ++;
561                                 Current.MoveTo (_nav);
562                                 return true;
563                         }
564                         while (_depth != 0)
565                         {
566                                 if (_nav.MoveToNext ())
567                                 {
568                                         Current.MoveTo (_nav);
569                                         return true;
570                                 }
571                                 if (!_nav.MoveToParent ())      // should NEVER fail!
572                                         throw new XPathException ("There seems some bugs on the XPathNavigator implementation class: " + _nav.GetType ());
573                                 _depth --;
574                         }
575                         _finished = true;
576                         return false;
577                 }
578         }
579
580         internal class FollowingIterator : SimpleIterator
581         {
582                 private bool _finished = false;
583                 public FollowingIterator (BaseIterator iter) : base (iter) {}
584                 private FollowingIterator (FollowingIterator other) : base (other, true) {}
585                 public override XPathNodeIterator Clone () { return new FollowingIterator (this); }
586                 public override bool MoveNextCore ()
587                 {
588                         if (_finished)
589                                 return false;
590                         bool checkChildren = true;
591                         if (CurrentPosition == 0)
592                         {
593                                 checkChildren = false;
594                                 switch (_nav.NodeType) {
595                                 case XPathNodeType.Attribute:
596                                 case XPathNodeType.Namespace:
597                                         _nav.MoveToParent ();
598                                         checkChildren = true;
599                                         break;
600                                 default:
601                                         if (_nav.MoveToNext ())
602                                         {
603                                                 Current.MoveTo (_nav);
604                                                 return true;
605                                         } else {
606                                                 while (_nav.MoveToParent ()) {
607                                                         if (_nav.MoveToNext ()) {
608                                                                 Current.MoveTo (_nav);
609                                                                 return true;
610                                                         }
611                                                 }
612                                         }
613                                         break;
614                                 }
615                         }
616                         if (checkChildren)
617                         {
618                                 if (_nav.MoveToFirstChild ())
619                                 {
620                                         Current.MoveTo (_nav);
621                                         return true;
622                                 }
623                                 do
624                                 {
625                                         if (_nav.MoveToNext ())
626                                         {
627                                                 Current.MoveTo (_nav);
628                                                 return true;
629                                         }
630                                 }
631                                 while (_nav.MoveToParent ());
632                         }
633                         _finished = true;
634                         return false;
635                 }
636         }
637
638         internal class PrecedingIterator : SimpleIterator
639         {
640                 bool finished;
641                 bool started;
642                 XPathNavigator startPosition;
643
644                 public PrecedingIterator (BaseIterator iter) : base (iter) 
645                 {
646                         startPosition = iter.Current.Clone ();
647                 }
648                 private PrecedingIterator (PrecedingIterator other) : base (other, true) 
649                 {
650                         startPosition = other.startPosition;
651                         started = other.started;
652                         finished = other.finished;
653                 }
654                 public override XPathNodeIterator Clone () { return new PrecedingIterator (this); }
655                 public override bool MoveNextCore ()
656                 {
657                         if (finished)
658                                 return false;
659                         if (!started) {
660                                 started = true;
661                                 _nav.MoveToRoot ();
662                         }
663                         bool loop = true;
664                         while (loop) {
665                                 while (!_nav.MoveToFirstChild ()) {
666                                         while (!_nav.MoveToNext ()) {
667                                                 if (!_nav.MoveToParent ()) { // Should not finish, at least before startPosition.
668                                                         finished = true;
669                                                         return false;
670                                                 }
671                                         }
672                                         break;
673                                 }
674                                 if (_nav.IsDescendant (startPosition))
675                                         continue;
676                                 loop = false;
677                                 break;
678                         }
679                         if (_nav.ComparePosition (startPosition) != XmlNodeOrder.Before) {
680                                 // Note that if _nav contains only 1 node, it won't be Same.
681                                 finished = true;
682                                 return false;
683                         } else {
684                                 Current.MoveTo (_nav);
685                                 return true;
686                         }
687                 }
688                 public override bool ReverseAxis {
689                         get { return true; }
690                 }
691         }
692
693         internal class NamespaceIterator : SimpleIterator
694         {
695                 public NamespaceIterator (BaseIterator iter) : base (iter) {}
696                 private NamespaceIterator (NamespaceIterator other) : base (other, true) {}
697                 public override XPathNodeIterator Clone () { return new NamespaceIterator (this); }
698                 public override bool MoveNextCore ()
699                 {
700                         if (CurrentPosition == 0)
701                         {
702                                 if (_nav.MoveToFirstNamespace ())
703                                 {
704                                         Current.MoveTo (_nav);
705                                         return true;
706                                 }
707                         }
708                         else if (_nav.MoveToNextNamespace ())
709                         {
710                                 Current.MoveTo (_nav);
711                                 return true;
712                         }
713                         return false;
714                 }
715         }
716
717         internal class AttributeIterator : SimpleIterator
718         {
719                 public AttributeIterator (BaseIterator iter) : base (iter) {}
720                 private AttributeIterator (AttributeIterator other) : base (other, true) {}
721                 public override XPathNodeIterator Clone () { return new AttributeIterator (this); }
722                 public override bool MoveNextCore ()
723                 {
724                         if (CurrentPosition == 0)
725                         {
726                                 if (_nav.MoveToFirstAttribute ())
727                                 {
728                                         Current.MoveTo (_nav);
729                                         return true;
730                                 }
731                         }
732                         else if (_nav.MoveToNextAttribute ())
733                         {
734                                 Current.MoveTo (_nav);
735                                 return true;
736                         }
737                         return false;                   
738                 }
739         }
740
741         internal class AxisIterator : BaseIterator
742         {
743                 private SimpleIterator _iter;
744                 private NodeTest _test;
745                         
746                 string name, ns;
747                 XPathNodeType matchType;
748
749                 public AxisIterator (SimpleIterator iter, NodeTest test) : base (iter.NamespaceManager)
750                 {
751                         _iter = iter;
752                         _test = test;
753                         test.GetInfo (out name, out ns, out matchType, NamespaceManager);
754 //                      if (name != null)
755 //                              name = Current.NameTable.Add (name);
756
757 //                      if (ns != null)
758 //                              ns = Current.NameTable.Add (ns);
759                 }
760
761                 private AxisIterator (AxisIterator other) : base (other)
762                 {
763                         _iter = (SimpleIterator) other._iter.Clone ();
764                         _test = other._test;
765                         name = other.name;
766                         ns = other.ns;
767                         matchType = other.matchType;
768                 }
769                 public override XPathNodeIterator Clone () { return new AxisIterator (this); }
770
771                 public override bool MoveNextCore ()
772                 {
773                         while (_iter.MoveNext ())
774                         {
775                                 if (_test.Match (NamespaceManager, Current))
776                                 {
777                                         return true;
778                                 }
779                         }
780                         return false;
781                 }
782                 public override XPathNavigator Current { get { return _iter.Current; }}
783
784                 public override bool ReverseAxis {
785                         get { return _iter.ReverseAxis; }
786                 }
787         }
788
789         internal class SimpleSlashIterator : BaseIterator
790         {
791                 private NodeSet _expr;
792                 private BaseIterator _left, _right;
793                 private XPathNavigator _current;
794
795                 public SimpleSlashIterator (BaseIterator left, NodeSet expr)
796                         : base (left.NamespaceManager)
797                 {
798                         this._left = left;
799                         this._expr = expr;
800                 }
801
802                 private SimpleSlashIterator (SimpleSlashIterator other)
803                         : base (other)
804                 {
805                         _expr = other._expr;
806                         _left = (BaseIterator) other._left.Clone ();
807                         if (other._right != null)
808                                 _right = (BaseIterator) other._right.Clone ();
809                 }
810
811                 public override XPathNodeIterator Clone () { return new SimpleSlashIterator (this); }
812
813                 public override bool MoveNextCore ()
814                 {
815                         while (_right == null || !_right.MoveNext ()) {
816                                 if (!_left.MoveNext ())
817                                         return false;
818                                 _right = _expr.EvaluateNodeSet (_left);
819                         }
820                         if (_current == null)
821                                 _current = _right.Current.Clone ();
822                         else
823                                 if (! _current.MoveTo (_right.Current) )
824                                         _current = _right.Current.Clone ();
825                         return true;
826                 }
827
828                 public override XPathNavigator Current {
829                         get { return _current; }
830                 }
831         }
832
833         internal class SlashIterator : BaseIterator
834         {
835                 private BaseIterator _iterLeft;
836                 private BaseIterator _iterRight;
837                 private NodeSet _expr;
838                 ArrayList _navStore;
839                 SortedList _iterList;
840                 bool _finished;
841                 BaseIterator _nextIterRight;
842
843                 public SlashIterator (BaseIterator iter, NodeSet expr, bool requireSorting) : base (iter.NamespaceManager)
844                 {
845                         _iterLeft = iter;
846                         _expr = expr;
847
848                         if (requireSorting)
849                                 CollectResults ();
850                 }
851
852                 private SlashIterator (SlashIterator other) : base (other)
853                 {
854                         _iterLeft = (BaseIterator) other._iterLeft.Clone ();
855                         if (other._iterRight != null)
856                                 _iterRight = (BaseIterator) other._iterRight.Clone ();
857                         _expr = other._expr;
858                         if (other._iterList != null)
859                                 _iterList = (SortedList) other._iterList.Clone ();
860                         if (other._navStore != null)
861                                 _navStore = (ArrayList) other._navStore.Clone ();
862                         _finished = other._finished;
863                         if (other._nextIterRight != null)
864                                 _nextIterRight = (BaseIterator) other._nextIterRight.Clone ();
865                 }
866                 public override XPathNodeIterator Clone () { return new SlashIterator (this); }
867
868                 public override bool MoveNextCore ()
869                 {
870                         if (_finished)
871                                 return false;
872                         if (_navStore != null) {
873                                 // Which requires sorting::
874                                 if (_navStore.Count < CurrentPosition + 1) {
875                                         _finished = true;
876                                         return false;
877                                 }
878                                 while (_navStore.Count > CurrentPosition + 1) {
879                                         if (((XPathNavigator) _navStore [CurrentPosition + 1]).IsSamePosition (
880                                                 (XPathNavigator) _navStore [CurrentPosition]))
881                                                 _navStore.RemoveAt (CurrentPosition + 1);
882                                         else
883                                                 break;
884                                 }
885
886                                 return true;
887                         }
888                         // Which does not require sorting::
889                         
890                         if (_iterRight == null) { // First time
891                                 if (!_iterLeft.MoveNext ())
892                                         return false;
893                                 _iterRight = _expr.EvaluateNodeSet (_iterLeft);
894                                 _iterList = new SortedList (XPathIteratorComparer.Instance);
895                         }
896
897                         while (true) {
898                                 while (!_iterRight.MoveNext ()) {
899                                         if (_iterList.Count > 0) {
900                                                 int last = _iterList.Count - 1;
901                                                 _iterRight = (BaseIterator) _iterList.GetByIndex (last);
902                                                 _iterList.RemoveAt (last);
903                                                 break;
904                                         } else if (_nextIterRight != null) {
905                                                 _iterRight = _nextIterRight;
906                                                 _nextIterRight = null;
907                                                 break;
908                                         } else if (!_iterLeft.MoveNext ()) {
909                                                 _finished = true;
910                                                 return false;
911                                         }
912                                         else
913                                                 _iterRight = _expr.EvaluateNodeSet (_iterLeft);
914                                 }
915                                 bool loop = true;
916                                 while (loop) {
917                                         loop = false;
918                                         if (_nextIterRight == null) {
919                                                 bool noMoreNext = false;
920                                                 while (_nextIterRight == null || !_nextIterRight.MoveNext ()) {
921                                                         if(_iterLeft.MoveNext ())
922                                                                 _nextIterRight = _expr.EvaluateNodeSet (_iterLeft);
923                                                         else {
924                                                                 noMoreNext = true;
925                                                                 break;
926                                                         }
927                                                 }
928                                                 if (noMoreNext)
929                                                         _nextIterRight = null; // FIXME: More efficient code. Maybe making noMoreNext class scope would be better.
930                                         }
931                                         if (_nextIterRight != null) {
932                                                 switch (_iterRight.Current.ComparePosition (_nextIterRight.Current)) {
933                                                 case XmlNodeOrder.After:
934                                                         _iterList [_iterRight] = _iterRight;
935                                                         _iterRight = _nextIterRight;
936                                                         _nextIterRight = null;
937                                                         loop = true;
938                                                         break;
939                                                 case XmlNodeOrder.Same:
940                                                         if (!_nextIterRight.MoveNext ())
941                                                                 _nextIterRight = null;
942
943                                                         else {
944                                                                 int last = _iterList.Count;
945                                                                 _iterList [_nextIterRight] = _nextIterRight;
946                                                                 if (last != _iterList.Count) {
947                                                                         _nextIterRight = (BaseIterator) _iterList.GetByIndex (last);
948                                                                         _iterList.RemoveAt (last);
949                                                                 }
950                                                         }
951
952                                                         loop = true;
953                                                         break;
954                                                 }
955                                         }
956                                 }
957                                 return true;
958                         }
959                 }
960
961                 private void CollectResults ()
962                 {
963                         _navStore = new ArrayList ();
964                         while (true) {
965                                 while (_iterRight == null || !_iterRight.MoveNext ()) {
966                                         if (!_iterLeft.MoveNext ()) {
967                                                 _navStore.Sort (XPathNavigatorComparer.Instance);
968                                                 return;
969                                         }
970                                         _iterRight = _expr.EvaluateNodeSet (_iterLeft);
971                                 }
972                                 XPathNavigator nav = _iterRight.Current;
973                                 _navStore.Add (nav.Clone ());
974                         }
975                 }
976
977                 public override XPathNavigator Current { 
978                         get {
979                                 if (CurrentPosition <= 0) return null;
980                                 if (_navStore != null) {
981                                         return (XPathNavigator) _navStore [CurrentPosition - 1];
982                                 } else {
983                                         return _iterRight.Current;
984                                 }
985                         }
986                 }
987
988                 public override int Count { get { return _navStore == null ? base.Count : _navStore.Count; } }
989         }
990
991         internal class PredicateIterator : BaseIterator
992         {
993                 private BaseIterator _iter;
994                 private Expression _pred;
995                 private XPathResultType resType;
996                 private bool finished;
997
998                 public PredicateIterator (BaseIterator iter, Expression pred) : base (iter.NamespaceManager)
999                 {
1000                         _iter = iter;
1001                         _pred = pred;
1002                         resType = pred.GetReturnType (iter);
1003                 }
1004
1005                 private PredicateIterator (PredicateIterator other) : base (other)
1006                 {
1007                         _iter = (BaseIterator) other._iter.Clone ();
1008                         _pred = other._pred;
1009                         resType = other.resType;
1010                         finished = other.finished;
1011                 }
1012                 public override XPathNodeIterator Clone () { return new PredicateIterator (this); }
1013
1014                 public override bool MoveNextCore ()
1015                 {
1016                         if (finished)
1017                                 return false;
1018                         while (_iter.MoveNext ())
1019                         {
1020                                 switch (resType) {
1021                                         case XPathResultType.Number:
1022                                                 if (_pred.EvaluateNumber (_iter) != _iter.ComparablePosition)
1023                                                         continue;
1024                                                 finished = true;
1025                                                 break;
1026                                         case XPathResultType.Any: {
1027                                                 object result = _pred.Evaluate (_iter);
1028                                                 if (result is double)
1029                                                 {
1030                                                         if ((double) result != _iter.ComparablePosition)
1031                                                                 continue;
1032                                                         finished = true;
1033                                                 }
1034                                                 else if (!XPathFunctions.ToBoolean (result))
1035                                                         continue;
1036                                         }
1037                                                 break;
1038                                         default:
1039                                                 if (!_pred.EvaluateBoolean (_iter))
1040                                                         continue;
1041                                                 break;
1042                                 }
1043
1044                                 return true;
1045                         }
1046                         return false;
1047                 }
1048                 public override XPathNavigator Current { get { return _iter.Current; }}
1049                 public override bool ReverseAxis {
1050                         get { return _iter.ReverseAxis; }
1051                 }
1052         }
1053
1054         internal class ListIterator : BaseIterator
1055         {
1056                 private IList _list;
1057
1058                 public ListIterator (BaseIterator iter, IList list) : base (iter.NamespaceManager)
1059                 {
1060                         if (!(list is ICloneable))
1061                                 throw new ArgumentException ("Target enumerator must be cloneable.");
1062                         _list = list;
1063                 }
1064                 
1065                 public ListIterator (IList list, NSResolver nsm) : base (nsm)
1066                 {
1067                         if (!(list is ICloneable))
1068                                 throw new ArgumentException ("Target enumerator must be cloneable.");
1069                         _list = list;
1070                 }
1071
1072                 private ListIterator (ListIterator other) : base (other)
1073                 {
1074                         ICloneable listClone = other._list as ICloneable;
1075                         _list = (IList) listClone.Clone ();
1076                 }
1077                 public override XPathNodeIterator Clone () { return new ListIterator (this); }
1078
1079                 public override bool MoveNextCore ()
1080                 {
1081                         if (CurrentPosition >= _list.Count)
1082                                 return false;
1083                         return true;
1084                 }
1085                 public override XPathNavigator Current {
1086                         get {
1087                                 if (_list.Count == 0)
1088                                         return null;
1089                                 return (XPathNavigator) _list [CurrentPosition - 1]; 
1090                         }
1091                 }
1092
1093                 public override int Count { get { return _list.Count; } }
1094         }
1095
1096         
1097         internal class UnionIterator : BaseIterator
1098         {
1099                 private BaseIterator _left, _right;
1100                 private bool keepLeft;
1101                 private bool keepRight;
1102                 XPathNavigator _current;
1103
1104                 public UnionIterator (BaseIterator iter, BaseIterator left, BaseIterator right) : base (iter.NamespaceManager)
1105                 {
1106                         _left = left;
1107                         _right = right;
1108                 }
1109
1110                 private UnionIterator (UnionIterator other) : base (other)
1111                 {
1112                         _left = (BaseIterator) other._left.Clone ();
1113                         _right = (BaseIterator) other._right.Clone ();
1114                         keepLeft = other.keepLeft;
1115                         keepRight = other.keepRight;
1116                         if (other._current != null)
1117                                 _current = other._current.Clone ();
1118                 }
1119                 public override XPathNodeIterator Clone () { return new UnionIterator (this); }
1120
1121                 public override bool MoveNextCore ()
1122                 {
1123                         if (!keepLeft)
1124                                 keepLeft = _left.MoveNext ();
1125                         if (!keepRight)
1126                                 keepRight = _right.MoveNext ();
1127
1128                         if (!keepLeft && !keepRight)
1129                                 return false;
1130
1131                         if (!keepRight) {
1132                                 keepLeft = false;
1133                                 SetCurrent (_left);
1134                                 return true;
1135                         } else if (!keepLeft) {
1136                                 keepRight = false;
1137                                 SetCurrent (_right);
1138                                 return true;
1139                         }
1140
1141                         switch (_left.Current.ComparePosition (_right.Current)) {
1142                         case XmlNodeOrder.Same:
1143                                 // consume both. i.e. don't output duplicate result.
1144                                 keepLeft = keepRight = false;
1145                                 SetCurrent (_right);
1146                                 return true;
1147                         case XmlNodeOrder.Before:
1148                         case XmlNodeOrder.Unknown: // Maybe happen because of "document(a) | document(b)"
1149                                 keepLeft = false;
1150                                 SetCurrent (_left);
1151                                 return true;
1152                         case XmlNodeOrder.After:
1153                                 keepRight = false;
1154                                 SetCurrent (_right);
1155                                 return true;
1156                         default:
1157                                 throw new InvalidOperationException ("Should not happen.");
1158                         }
1159                 }
1160
1161                 private void SetCurrent (XPathNodeIterator iter)
1162                 {
1163                         if (_current == null)
1164                                 _current = iter.Current.Clone ();
1165                         else
1166                                 if (! _current.MoveTo (iter.Current) )
1167                                         _current = iter.Current.Clone ();
1168                 }
1169
1170                 public override XPathNavigator Current
1171                 {
1172                         get { return _current; }
1173                 }
1174         }
1175
1176         internal class OrderedIterator : BaseIterator
1177         {
1178                 BaseIterator iter;
1179                 ArrayList list;
1180                 int index = -1;
1181
1182                 public OrderedIterator (BaseIterator iter)
1183                         : base (iter.NamespaceManager)
1184                 {
1185 //                      if (iter.Ordered)
1186                         if (false)
1187                                 this.iter = iter;
1188                         else {
1189                                 list = new ArrayList ();
1190                                 while (iter.MoveNext ())
1191                                         list.Add (iter.Current);
1192                                 list.Sort (XPathNavigatorComparer.Instance);
1193                         }
1194                 }
1195
1196                 private OrderedIterator (OrderedIterator other, bool dummy)
1197                         : base (other)
1198                 {
1199                         if (other.iter != null)
1200                                 iter = (BaseIterator) other.iter.Clone ();
1201                         list = other.list;
1202                         index = other.index;
1203                 }
1204
1205                 public override XPathNodeIterator Clone ()
1206                 {
1207                         return new OrderedIterator (this);
1208                 }
1209
1210                 public override bool MoveNextCore ()
1211                 {
1212                         if (iter != null)
1213                                 return iter.MoveNext ();
1214                         else if (index++ < list.Count)
1215                                 return true;
1216                         index--;
1217                         return false;
1218                 }
1219
1220                 public override XPathNavigator Current {
1221                         get { return iter != null ? iter.Current : index < 0 ? null : (XPathNavigator) list [index]; }
1222                 }
1223         }
1224 }