2003-02-16 Atsushi Enomoto <ginga@kit.hi-ho.ne.jp>
[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 //
7 // (C) 2002 Piers Haken
8 //
9
10 using System;
11 using System.Collections;
12 using System.Xml;
13 using System.Xml.XPath;
14 using System.Xml.Xsl;
15
16 namespace System.Xml.XPath
17 {
18         internal abstract class BaseIterator : XPathNodeIterator
19         {
20                 private XmlNamespaceManager _nsm;
21
22                 internal BaseIterator (BaseIterator other)
23                 {
24                         _nsm = other._nsm;
25                 }
26                 internal BaseIterator (XmlNamespaceManager nsm)
27                 {
28                         _nsm = nsm;
29                 }
30
31                 public XmlNamespaceManager NamespaceManager { get { return _nsm; } }
32                 
33                 public override string ToString ()
34                 {
35                         return Current.NodeType.ToString () + "[" + CurrentPosition + "] : " + Current.Name + " = " + Current.Value;
36                 }
37         }
38
39         internal class MergedIterator : BaseIterator
40         {
41                 protected ArrayList _iters = new ArrayList ();
42                 protected int _pos;
43                 protected int _index;
44
45                 public MergedIterator (BaseIterator iter ) : base (iter) {}
46                 protected MergedIterator (MergedIterator other) : base (other)
47                 {
48                         foreach (object obj in other._iters)
49                                 _iters.Add (obj);
50                         _pos = other._pos;
51                         _index = other._index;
52                 }
53                 public override XPathNodeIterator Clone () { return new MergedIterator (this); }
54
55                 public void Add (BaseIterator iter)
56                 {
57                         _iters.Add (iter);
58                 }
59
60                 public override bool MoveNext ()
61                 {
62                         while (_index < _iters.Count)
63                         {
64                                 BaseIterator iter = (BaseIterator) _iters [_index];
65                                 if (iter.MoveNext ())
66                                 {
67                                         _pos ++;
68                                         return true;
69                                 }
70                                 _index ++;
71                         }
72                         return false;
73                 }
74                 public override XPathNavigator Current
75                 {
76                         get
77                         {
78                                 if (_index >= _iters.Count)
79                                         return null;
80                                 BaseIterator iter = (BaseIterator) _iters [_index];
81                                 return iter.Current;
82                         }
83                 }
84                 public override int CurrentPosition { get { return _pos; }}
85         }
86
87         internal abstract class SimpleIterator : BaseIterator
88         {
89                 protected XPathNavigator _nav;
90                 protected int _pos;
91
92                 public SimpleIterator (BaseIterator iter) : base (iter)
93                 {
94                         _nav = iter.Current.Clone ();
95                 }
96                 protected SimpleIterator (SimpleIterator other) : base (other)
97                 {
98                         _nav = other._nav.Clone ();
99                         _pos = other._pos;
100                 }
101                 public SimpleIterator (XPathNavigator nav, XmlNamespaceManager nsm) : base (nsm)
102                 {
103                         _nav = nav.Clone ();
104                 }
105
106                 public override XPathNavigator Current { get { return _nav; }}
107                 public override int CurrentPosition { get { return _pos; }}
108         }
109
110         internal class SelfIterator : SimpleIterator
111         {
112                 public SelfIterator (BaseIterator iter) : base (iter) {}
113                 public SelfIterator (XPathNavigator nav, XmlNamespaceManager nsm) : base (nav, nsm) {}
114                 protected SelfIterator (SimpleIterator other) : base (other) {}
115                 public override XPathNodeIterator Clone () { return new SelfIterator (this); }
116                 public override bool MoveNext ()
117                 {
118                         if (_pos == 0)
119                         {
120                                 _pos = 1;
121                                 return true;
122                         }
123                         return false;
124                 }
125         }
126
127         internal class NullIterator : SelfIterator
128         {
129                 public NullIterator (BaseIterator iter) : base (iter) {}
130                 public NullIterator (XPathNavigator nav, XmlNamespaceManager nsm) : base (nav, nsm) {}
131                 protected NullIterator (SimpleIterator other) : base (other) {}
132                 public override XPathNodeIterator Clone () { return new NullIterator (this); }
133                 public override bool MoveNext ()
134                 {
135                         return false;
136                 }
137         }
138
139         internal class ParentIterator : SimpleIterator
140         {
141                 public ParentIterator (BaseIterator iter) : base (iter) {}
142                 protected ParentIterator (SimpleIterator other) : base (other) {}
143                 public override XPathNodeIterator Clone () { return new ParentIterator (this); }
144                 public override bool MoveNext ()
145                 {
146                         if (_pos == 0 && _nav.MoveToParent ())
147                         {
148                                 _pos = 1;
149                                 return true;
150                         }
151                         return false;
152                 }
153         }
154
155         internal class ChildIterator : SimpleIterator
156         {
157                 public ChildIterator (BaseIterator iter) : base (iter) {}
158                 protected ChildIterator (SimpleIterator other) : base (other) {}
159                 public override XPathNodeIterator Clone () { return new ChildIterator (this); }
160                 public override bool MoveNext ()
161                 {
162                         bool fSuccess = (_pos == 0) ? _nav.MoveToFirstChild () : _nav.MoveToNext ();
163                         if (fSuccess)
164                                 _pos ++;
165                         return fSuccess;
166                 }
167         }
168
169         internal class FollowingSiblingIterator : SimpleIterator
170         {
171                 public FollowingSiblingIterator (BaseIterator iter) : base (iter) {}
172                 protected FollowingSiblingIterator (SimpleIterator other) : base (other) {}
173                 public override XPathNodeIterator Clone () { return new FollowingSiblingIterator (this); }
174                 public override bool MoveNext ()
175                 {
176                         if (_nav.MoveToNext ())
177                         {
178                                 _pos ++;
179                                 return true;
180                         }
181                         return false;
182                 }
183         }
184
185         internal class PrecedingSiblingIterator : SimpleIterator
186         {
187                 public PrecedingSiblingIterator (BaseIterator iter) : base (iter) {}
188                 protected PrecedingSiblingIterator (SimpleIterator other) : base (other) {}
189                 public override XPathNodeIterator Clone () { return new PrecedingSiblingIterator (this); }
190                 public override bool MoveNext ()
191                 {
192                         if (_nav.MoveToPrevious ())
193                         {
194                                 _pos ++;
195                                 return true;
196                         }
197                         return false;
198                 }
199         }
200
201         internal class AncestorIterator : SimpleIterator
202         {
203                 public AncestorIterator (BaseIterator iter) : base (iter) {}
204                 protected AncestorIterator (SimpleIterator other) : base (other) {}
205                 public override XPathNodeIterator Clone () { return new AncestorIterator (this); }
206                 public override bool MoveNext ()
207                 {
208                         if (_nav.MoveToParent ())
209                         {
210                                 _pos ++;
211                                 return true;
212                         }
213                         return false;
214                 }
215         }
216
217         internal class AncestorOrSelfIterator : MergedIterator
218         {
219                 public AncestorOrSelfIterator (BaseIterator iter) : base (iter)
220                 {
221                         Add (new SelfIterator (iter));
222                         Add (new AncestorIterator (iter));
223                 }
224                 protected AncestorOrSelfIterator (MergedIterator other) : base (other) {}
225                 public override XPathNodeIterator Clone () { return new AncestorOrSelfIterator (this); }
226         }
227
228         internal class DescendantIterator : SimpleIterator
229         {
230                 protected int _depth;
231                 public DescendantIterator (BaseIterator iter) : base (iter) {}
232                 protected DescendantIterator (SimpleIterator other) : base (other) {}
233                 public override XPathNodeIterator Clone () { return new DescendantIterator (this); }
234                 [MonoTODO]
235                 public override bool MoveNext ()
236                 {
237                         if (_nav.MoveToFirstChild ())
238                         {
239                                 _depth ++;
240                                 _pos ++;
241                                 return true;
242                         }
243                         while (_depth != 0)
244                         {
245                                 if (_nav.MoveToNext ())
246                                 {
247                                         _pos ++;
248                                         return true;
249                                 }
250                                 if (!_nav.MoveToParent ())      // should NEVER fail!
251                                         throw new XPathException ("unexpected depth");  // TODO: better message
252                                 _depth --;
253                         }
254                         return false;
255                 }
256         }
257
258         internal class DescendantOrSelfIterator : MergedIterator
259         {
260                 public DescendantOrSelfIterator (BaseIterator iter) : base (iter)
261                 {
262                         Add (new SelfIterator (iter));
263                         Add (new DescendantIterator (iter));
264                 }
265                 protected DescendantOrSelfIterator (MergedIterator other) : base (other) {}
266                 public override XPathNodeIterator Clone () { return new DescendantOrSelfIterator (this); }
267         }
268
269         internal class FollowingIterator : SimpleIterator
270         {
271                 public FollowingIterator (BaseIterator iter) : base (iter) {}
272                 protected FollowingIterator (SimpleIterator other) : base (other) {}
273                 public override XPathNodeIterator Clone () { return new FollowingIterator (this); }
274                 public override bool MoveNext ()
275                 {
276                         if (_pos == 0)
277                         {
278                                 if (_nav.MoveToNext ())
279                                 {
280                                         _pos ++;
281                                         return true;
282                                 }
283                         }
284                         else
285                         {
286                                 if (_nav.MoveToFirstChild ())
287                                 {
288                                         _pos ++;
289                                         return true;
290                                 }
291                                 do
292                                 {
293                                         if (_nav.MoveToNext ())
294                                         {
295                                                 _pos ++;
296                                                 return true;
297                                         }
298                                 }
299                                 while (_nav.MoveToParent ());
300                         }
301                         return false;
302                 }
303         }
304
305         internal class PrecedingIterator : SimpleIterator
306         {
307                 public PrecedingIterator (BaseIterator iter) : base (iter) {}
308                 protected PrecedingIterator (SimpleIterator other) : base (other) {}
309                 public override XPathNodeIterator Clone () { return new PrecedingIterator (this); }
310                 public override bool MoveNext ()
311                 {
312                         if (_pos == 0)
313                         {
314                                 if (_nav.MoveToPrevious ())
315                                 {
316                                         _pos ++;
317                                         return true;
318                                 }
319                         }
320                         else
321                         {
322                                 if (_nav.MoveToFirstChild ())
323                                 {
324                                         while (_nav.MoveToNext ())
325                                                 ;
326                                         _pos ++;
327                                         return true;
328                                 }
329                                 do
330                                 {
331                                         if (_nav.MoveToPrevious ())
332                                         {
333                                                 _pos ++;
334                                                 return true;
335                                         }
336                                 }
337                                 while (_nav.MoveToParent ());
338                         }
339                         return false;
340                 }
341         }
342
343         internal class NamespaceIterator : SimpleIterator
344         {
345                 public NamespaceIterator (BaseIterator iter) : base (iter) {}
346                 protected NamespaceIterator (SimpleIterator other) : base (other) {}
347                 public override XPathNodeIterator Clone () { return new NamespaceIterator (this); }
348                 public override bool MoveNext ()
349                 {
350                         if (_pos == 0)
351                         {
352                                 if (_nav.MoveToFirstNamespace ())
353                                 {
354                                         _pos ++;
355                                         return true;
356                                 }
357                         }
358                         else if (_nav.MoveToNextNamespace ())
359                         {
360                                 _pos ++;
361                                 return true;
362                         }
363                         return false;
364                 }
365         }
366
367         internal class AttributeIterator : SimpleIterator
368         {
369                 public AttributeIterator (BaseIterator iter) : base (iter) {}
370                 protected AttributeIterator (SimpleIterator other) : base (other) {}
371                 public override XPathNodeIterator Clone () { return new AttributeIterator (this); }
372                 public override bool MoveNext ()
373                 {
374                         if (_pos == 0)
375                         {
376                                 if (_nav.MoveToFirstAttribute ())
377                                 {
378                                         _pos += 1;
379                                         return true;
380                                 }
381                         }
382                         else if (_nav.MoveToNextAttribute ())
383                         {
384                                 _pos ++;
385                                 return true;
386                         }
387                         return false;                   
388                 }
389         }
390
391         internal class AxisIterator : BaseIterator
392         {
393                 protected BaseIterator _iter;
394                 protected NodeTest _test;
395                 protected int _pos;
396
397                 public AxisIterator (BaseIterator iter, NodeTest test) : base (iter)
398                 {
399                         _iter = iter;
400                         _test = test;
401                 }
402
403                 protected AxisIterator (AxisIterator other) : base (other)
404                 {
405                         _iter = (BaseIterator) other._iter.Clone ();
406                         _test = other._test;
407                         _pos = other._pos;
408                 }
409                 public override XPathNodeIterator Clone () { return new AxisIterator (this); }
410
411                 public override bool MoveNext ()
412                 {
413                         while (_iter.MoveNext ())
414                         {
415                                 if (_test.Match (NamespaceManager, Current))
416                                 {
417                                         _pos ++;
418                                         return true;
419                                 }
420                         }
421                         return false;
422                 }
423                 public override XPathNavigator Current { get { return _iter.Current; }}
424                 public override int CurrentPosition { get { return _pos; }}
425         }
426
427         internal class SlashIterator : BaseIterator
428         {
429                 protected BaseIterator _iterLeft;
430                 protected BaseIterator _iterRight;
431                 protected Expression _expr;
432                 protected int _pos;
433
434                 public SlashIterator (BaseIterator iter, Expression expr) : base (iter)
435                 {
436                         _iterLeft = iter;
437                         _expr = expr;
438                 }
439
440                 protected SlashIterator (SlashIterator other) : base (other)
441                 {
442                         _iterLeft = (BaseIterator) other._iterLeft.Clone ();
443                         if (other._iterRight != null)
444                                 _iterRight = (BaseIterator) other._iterRight.Clone ();
445                         _expr = other._expr;
446                         _pos = other._pos;
447                 }
448                 public override XPathNodeIterator Clone () { return new SlashIterator (this); }
449
450                 public override bool MoveNext ()
451                 {
452                         while (_iterRight == null || !_iterRight.MoveNext ())
453                         {
454                                 if (!_iterLeft.MoveNext ())
455                                         return false;
456                                 _iterRight = _expr.EvaluateNodeSet (_iterLeft);
457                         }
458                         _pos ++;
459                         return true;
460                 }
461                 public override XPathNavigator Current { get { return _iterRight.Current; }}
462                 public override int CurrentPosition { get { return _pos; }}
463         }
464         internal class PredicateIterator : BaseIterator
465         {
466                 protected BaseIterator _iter;
467                 protected Expression [] _preds;
468                 protected int _pos;
469
470                 public PredicateIterator (BaseIterator iter, Expression [] preds) : base (iter)
471                 {
472                         _iter = iter;
473                         _preds = preds;
474                 }
475
476                 protected PredicateIterator (PredicateIterator other) : base (other)
477                 {
478                         _iter = (BaseIterator) other._iter.Clone ();
479                         _preds = other._preds;
480                         _pos = other._pos;
481                 }
482                 public override XPathNodeIterator Clone () { return new PredicateIterator (this); }
483
484                 public override bool MoveNext ()
485                 {
486                         while (_iter.MoveNext ())
487                         {
488                                 bool fTrue = true;
489                                 foreach (Expression pred in _preds)
490                                 {
491                                         object result = pred.Evaluate ((BaseIterator) _iter.Clone ());
492                                         if (result is double)
493                                         {
494                                                 if ((double) result != _iter.CurrentPosition)
495                                                 {
496                                                         fTrue = false;
497                                                         break;
498                                                 }
499                                         }
500                                         else if (!XPathFunctions.ToBoolean (result))
501                                         {
502                                                 fTrue = false;
503                                                 break;
504                                         }
505                                 }
506                                 if (fTrue)
507                                         return true;
508                         }
509                         return false;
510                 }
511                 public override XPathNavigator Current { get { return _iter.Current; }}
512                 public override int CurrentPosition { get { return _pos; }}
513         }
514         internal class ArrayListIterator : BaseIterator
515         {
516                 protected ArrayList _rgNodes;
517                 protected int _pos;
518
519                 public ArrayListIterator (BaseIterator iter, ArrayList rgNodes) : base (iter)
520                 {
521                         _rgNodes = rgNodes;
522                 }
523
524                 protected ArrayListIterator (ArrayListIterator other) : base (other)
525                 {
526                         _rgNodes = other._rgNodes;
527                         _pos = other._pos;
528                 }
529                 public override XPathNodeIterator Clone () { return new ArrayListIterator (this); }
530
531                 public override bool MoveNext ()
532                 {
533                         if (_pos >= _rgNodes.Count)
534                                 return false;
535                         _pos++;
536                         return true;
537                 }
538                 public override XPathNavigator Current { get { return (XPathNavigator) _rgNodes [_pos - 1]; }}
539                 public override int CurrentPosition { get { return _pos; }}
540         }
541
542         internal class UnionIterator : BaseIterator
543         {
544                 protected ArrayList _rgNodes;
545                 protected BaseIterator _left, _right;
546                 protected int _pos;
547
548                 public UnionIterator (BaseIterator iter, BaseIterator left, BaseIterator right) : base (iter)
549                 {
550                         _rgNodes = new ArrayList ();
551                         _left = left;
552                         _right = right;
553                 }
554
555                 protected UnionIterator (UnionIterator other) : base (other)
556                 {
557                         _rgNodes = (ArrayList) other._rgNodes.Clone ();
558                         _left = other._left;
559                         _right = other._right;
560                         _pos = other._pos;
561                 }
562                 public override XPathNodeIterator Clone () { return new UnionIterator (this); }
563
564                 public override bool MoveNext ()
565                 {
566                         if (_left.MoveNext ())
567                         {
568                                 _rgNodes.Add (_left.Current.Clone ());
569                                 _pos ++;
570                                 return true;
571                         }
572
573                         while (_right.MoveNext ())
574                         {
575                                 XPathNavigator navRight = _right.Current;
576                                 bool fFound = false;
577                                 foreach (XPathNavigator navLeft in _rgNodes)
578                                 {
579                                         if (navLeft.IsSamePosition (navRight))
580                                         {
581                                                 fFound = true;
582                                                 break;
583                                         }
584                                 }
585                                 if (!fFound)
586                                 {
587                                         _pos ++;
588                                         return true;
589                                 }
590                         }
591                         return false;
592                 }
593                 public override XPathNavigator Current
594                 {
595                         get
596                         {
597                                 if (_pos < _rgNodes.Count)
598                                         throw new XPathException ("bug in UnionOperator");      // TODO: better exception
599                                 if (_pos == _rgNodes.Count)
600                                         return _left.Current;
601                                 else
602                                         return _right.Current;
603                         }
604                 }
605                 public override int CurrentPosition { get { return _pos; }}
606         }
607 }