2002-09-03 Gonzalo Paniagua Javier <gonzalo@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 //
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 XsltContext _context;
21
22                 internal BaseIterator (BaseIterator other)
23                 {
24                         _context = other._context;
25                 }
26                 internal BaseIterator (XsltContext context)
27                 {
28                         _context = context;
29                 }
30
31                 public XsltContext Context { get { return _context; } }
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, XsltContext context) : base (context)
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, XsltContext context) : base (nav, context) {}
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 ParentIterator : SimpleIterator
128         {
129                 public ParentIterator (BaseIterator iter) : base (iter) {}
130                 protected ParentIterator (SimpleIterator other) : base (other) {}
131                 public override XPathNodeIterator Clone () { return new ParentIterator (this); }
132                 public override bool MoveNext ()
133                 {
134                         if (_pos == 0 && _nav.MoveToParent ())
135                         {
136                                 _pos = 1;
137                                 return true;
138                         }
139                         return false;
140                 }
141         }
142
143         internal class ChildIterator : SimpleIterator
144         {
145                 public ChildIterator (BaseIterator iter) : base (iter) {}
146                 protected ChildIterator (SimpleIterator other) : base (other) {}
147                 public override XPathNodeIterator Clone () { return new ChildIterator (this); }
148                 public override bool MoveNext ()
149                 {
150                         bool fSuccess = (_pos == 0) ? _nav.MoveToFirstChild () : _nav.MoveToNext ();
151                         if (fSuccess)
152                                 _pos ++;
153                         return fSuccess;
154                 }
155         }
156
157         internal class FollowingSiblingIterator : SimpleIterator
158         {
159                 public FollowingSiblingIterator (BaseIterator iter) : base (iter) {}
160                 protected FollowingSiblingIterator (SimpleIterator other) : base (other) {}
161                 public override XPathNodeIterator Clone () { return new FollowingSiblingIterator (this); }
162                 public override bool MoveNext ()
163                 {
164                         if (_nav.MoveToNext ())
165                         {
166                                 _pos ++;
167                                 return true;
168                         }
169                         return false;
170                 }
171         }
172
173         internal class PrecedingSiblingIterator : SimpleIterator
174         {
175                 public PrecedingSiblingIterator (BaseIterator iter) : base (iter) {}
176                 protected PrecedingSiblingIterator (SimpleIterator other) : base (other) {}
177                 public override XPathNodeIterator Clone () { return new PrecedingSiblingIterator (this); }
178                 public override bool MoveNext ()
179                 {
180                         if (_nav.MoveToPrevious ())
181                         {
182                                 _pos ++;
183                                 return true;
184                         }
185                         return false;
186                 }
187         }
188
189         internal class AncestorIterator : SimpleIterator
190         {
191                 public AncestorIterator (BaseIterator iter) : base (iter) {}
192                 protected AncestorIterator (SimpleIterator other) : base (other) {}
193                 public override XPathNodeIterator Clone () { return new AncestorIterator (this); }
194                 public override bool MoveNext ()
195                 {
196                         if (_nav.MoveToParent ())
197                         {
198                                 _pos ++;
199                                 return true;
200                         }
201                         return false;
202                 }
203         }
204
205         internal class AncestorOrSelfIterator : MergedIterator
206         {
207                 public AncestorOrSelfIterator (BaseIterator iter) : base (iter)
208                 {
209                         Add (new SelfIterator (iter));
210                         Add (new AncestorIterator (iter));
211                 }
212                 protected AncestorOrSelfIterator (MergedIterator other) : base (other) {}
213                 public override XPathNodeIterator Clone () { return new AncestorOrSelfIterator (this); }
214         }
215
216         internal class DescendantIterator : SimpleIterator
217         {
218                 protected int _depth;
219                 public DescendantIterator (BaseIterator iter) : base (iter) {}
220                 protected DescendantIterator (SimpleIterator other) : base (other) {}
221                 public override XPathNodeIterator Clone () { return new DescendantIterator (this); }
222                 [MonoTODO]
223                 public override bool MoveNext ()
224                 {
225                         if (_nav.MoveToFirstChild ())
226                         {
227                                 _depth ++;
228                                 _pos ++;
229                                 return true;
230                         }
231                         while (_depth != 0)
232                         {
233                                 if (_nav.MoveToNext ())
234                                 {
235                                         _pos ++;
236                                         return true;
237                                 }
238                                 if (!_nav.MoveToParent ())      // should NEVER fail!
239                                         throw new Exception ("unexpected depth");       // TODO: better message
240                                 _depth --;
241                         }
242                         return false;
243                 }
244         }
245
246         internal class DescendantOrSelfIterator : MergedIterator
247         {
248                 public DescendantOrSelfIterator (BaseIterator iter) : base (iter)
249                 {
250                         Add (new SelfIterator (iter));
251                         Add (new DescendantIterator (iter));
252                 }
253                 protected DescendantOrSelfIterator (MergedIterator other) : base (other) {}
254                 public override XPathNodeIterator Clone () { return new DescendantOrSelfIterator (this); }
255         }
256
257         internal class FollowingIterator : SimpleIterator
258         {
259                 public FollowingIterator (BaseIterator iter) : base (iter) {}
260                 protected FollowingIterator (SimpleIterator other) : base (other) {}
261                 public override XPathNodeIterator Clone () { return new FollowingIterator (this); }
262                 public override bool MoveNext ()
263                 {
264                         if (_pos == 0)
265                         {
266                                 if (_nav.MoveToNext ())
267                                 {
268                                         _pos ++;
269                                         return true;
270                                 }
271                         }
272                         else
273                         {
274                                 if (_nav.MoveToFirstChild ())
275                                 {
276                                         _pos ++;
277                                         return true;
278                                 }
279                                 do
280                                 {
281                                         if (_nav.MoveToNext ())
282                                         {
283                                                 _pos ++;
284                                                 return true;
285                                         }
286                                 }
287                                 while (_nav.MoveToParent ());
288                         }
289                         return false;
290                 }
291         }
292
293         internal class PrecedingIterator : SimpleIterator
294         {
295                 public PrecedingIterator (BaseIterator iter) : base (iter) {}
296                 protected PrecedingIterator (SimpleIterator other) : base (other) {}
297                 public override XPathNodeIterator Clone () { return new PrecedingIterator (this); }
298                 public override bool MoveNext ()
299                 {
300                         if (_pos == 0)
301                         {
302                                 if (_nav.MoveToPrevious ())
303                                 {
304                                         _pos ++;
305                                         return true;
306                                 }
307                         }
308                         else
309                         {
310                                 if (_nav.MoveToFirstChild ())
311                                 {
312                                         while (_nav.MoveToNext ())
313                                                 ;
314                                         _pos ++;
315                                         return true;
316                                 }
317                                 do
318                                 {
319                                         if (_nav.MoveToPrevious ())
320                                         {
321                                                 _pos ++;
322                                                 return true;
323                                         }
324                                 }
325                                 while (_nav.MoveToParent ());
326                         }
327                         return false;
328                 }
329         }
330
331         internal class NamespaceIterator : SimpleIterator
332         {
333                 public NamespaceIterator (BaseIterator iter) : base (iter) {}
334                 protected NamespaceIterator (SimpleIterator other) : base (other) {}
335                 public override XPathNodeIterator Clone () { return new NamespaceIterator (this); }
336                 public override bool MoveNext ()
337                 {
338                         if (_pos == 0)
339                         {
340                                 if (_nav.MoveToFirstNamespace ())
341                                 {
342                                         _pos ++;
343                                         return true;
344                                 }
345                         }
346                         else if (_nav.MoveToNextNamespace ())
347                         {
348                                 _pos ++;
349                                 return true;
350                         }
351                         return false;
352                 }
353         }
354
355         internal class AttributeIterator : SimpleIterator
356         {
357                 public AttributeIterator (BaseIterator iter) : base (iter) {}
358                 protected AttributeIterator (SimpleIterator other) : base (other) {}
359                 public override XPathNodeIterator Clone () { return new AttributeIterator (this); }
360                 public override bool MoveNext ()
361                 {
362                         if (_pos == 0)
363                         {
364                                 if (_nav.MoveToFirstAttribute ())
365                                 {
366                                         _pos += 1;
367                                         return true;
368                                 }
369                         }
370                         else if (_nav.MoveToNextAttribute ())
371                         {
372                                 _pos ++;
373                                 return true;
374                         }
375                         return false;                   
376                 }
377         }
378
379         internal class AxisIterator : BaseIterator
380         {
381                 protected BaseIterator _iter;
382                 protected NodeTest _test;
383                 protected int _pos;
384
385                 public AxisIterator (BaseIterator iter, NodeTest test) : base (iter)
386                 {
387                         _iter = iter;
388                         _test = test;
389                 }
390
391                 protected AxisIterator (AxisIterator other) : base (other)
392                 {
393                         _iter = (BaseIterator) other._iter.Clone ();
394                         _test = other._test;
395                         _pos = other._pos;
396                 }
397                 public override XPathNodeIterator Clone () { return new AxisIterator (this); }
398
399                 public override bool MoveNext ()
400                 {
401                         while (_iter.MoveNext ())
402                         {
403                                 if (_test.Match (Context, Current))
404                                 {
405                                         _pos ++;
406                                         return true;
407                                 }
408                         }
409                         return false;
410                 }
411                 public override XPathNavigator Current { get { return _iter.Current; }}
412                 public override int CurrentPosition { get { return _pos; }}
413         }
414
415         internal class SlashIterator : BaseIterator
416         {
417                 protected BaseIterator _iterLeft;
418                 protected BaseIterator _iterRight;
419                 protected Expression _expr;
420                 protected int _pos;
421
422                 public SlashIterator (BaseIterator iter, Expression expr) : base (iter)
423                 {
424                         _iterLeft = iter;
425                         _expr = expr;
426                 }
427
428                 protected SlashIterator (SlashIterator other) : base (other)
429                 {
430                         _iterLeft = (BaseIterator) other._iterLeft.Clone ();
431                         _iterRight = (BaseIterator) other._iterRight.Clone ();
432                         _expr = other._expr;
433                         _pos = other._pos;
434                 }
435                 public override XPathNodeIterator Clone () { return new SlashIterator (this); }
436
437                 public override bool MoveNext ()
438                 {
439                         while (_iterRight == null || !_iterRight.MoveNext ())
440                         {
441                                 if (!_iterLeft.MoveNext ())
442                                         return false;
443                                 _iterRight = _expr.EvaluateNodeSet (_iterLeft);
444                         }
445                         _pos ++;
446                         return true;
447                 }
448                 public override XPathNavigator Current { get { return _iterRight.Current; }}
449                 public override int CurrentPosition { get { return _pos; }}
450         }
451         internal class PredicateIterator : BaseIterator
452         {
453                 protected BaseIterator _iter;
454                 protected Expression [] _preds;
455                 protected int _pos;
456
457                 public PredicateIterator (BaseIterator iter, Expression [] preds) : base (iter)
458                 {
459                         _iter = iter;
460                         _preds = preds;
461                 }
462
463                 protected PredicateIterator (PredicateIterator other) : base (other)
464                 {
465                         _iter = (BaseIterator) other._iter.Clone ();
466                         _preds = other._preds;
467                         _pos = other._pos;
468                 }
469                 public override XPathNodeIterator Clone () { return new PredicateIterator (this); }
470
471                 public override bool MoveNext ()
472                 {
473                         while (_iter.MoveNext ())
474                         {
475                                 bool fTrue = true;
476                                 foreach (Expression pred in _preds)
477                                 {
478                                         object result = pred.Evaluate ((BaseIterator) _iter.Clone ());
479                                         if (result is double)
480                                         {
481                                                 if ((double) result != _iter.CurrentPosition)
482                                                 {
483                                                         fTrue = false;
484                                                         break;
485                                                 }
486                                         }
487                                         else if (!XPathFunctions.ToBoolean (result))
488                                         {
489                                                 fTrue = false;
490                                                 break;
491                                         }
492                                 }
493                                 if (fTrue)
494                                         return true;
495                         }
496                         return false;
497                 }
498                 public override XPathNavigator Current { get { return _iter.Current; }}
499                 public override int CurrentPosition { get { return _pos; }}
500         }
501         internal class ArrayListIterator : BaseIterator
502         {
503                 protected ArrayList _rgNodes;
504                 protected int _pos;
505
506                 public ArrayListIterator (BaseIterator iter, ArrayList rgNodes) : base (iter)
507                 {
508                         _rgNodes = rgNodes;
509                 }
510
511                 protected ArrayListIterator (ArrayListIterator other) : base (other)
512                 {
513                         _rgNodes = other._rgNodes;
514                         _pos = other._pos;
515                 }
516                 public override XPathNodeIterator Clone () { return new ArrayListIterator (this); }
517
518                 public override bool MoveNext ()
519                 {
520                         if (_pos >= _rgNodes.Count)
521                                 return false;
522                         _pos++;
523                         return true;
524                 }
525                 public override XPathNavigator Current { get { return (XPathNavigator) _rgNodes [_pos - 1]; }}
526                 public override int CurrentPosition { get { return _pos; }}
527         }
528
529         internal class UnionIterator : BaseIterator
530         {
531                 protected ArrayList _rgNodes;
532                 protected BaseIterator _left, _right;
533                 protected int _pos;
534
535                 public UnionIterator (BaseIterator iter, BaseIterator left, BaseIterator right) : base (iter)
536                 {
537                         _rgNodes = new ArrayList ();
538                         _left = left;
539                         _right = right;
540                 }
541
542                 protected UnionIterator (UnionIterator other) : base (other)
543                 {
544                         _rgNodes = (ArrayList) other._rgNodes.Clone ();
545                         _left = other._left;
546                         _right = other._right;
547                         _pos = other._pos;
548                 }
549                 public override XPathNodeIterator Clone () { return new UnionIterator (this); }
550
551                 public override bool MoveNext ()
552                 {
553                         if (_left.MoveNext ())
554                         {
555                                 _rgNodes.Add (_left.Current.Clone ());
556                                 _pos ++;
557                                 return true;
558                         }
559
560                         while (_right.MoveNext ())
561                         {
562                                 XPathNavigator navRight = _right.Current;
563                                 bool fFound = false;
564                                 foreach (XPathNavigator navLeft in _rgNodes)
565                                 {
566                                         if (navLeft.IsSamePosition (navRight))
567                                         {
568                                                 fFound = true;
569                                                 break;
570                                         }
571                                 }
572                                 if (!fFound)
573                                 {
574                                         _pos ++;
575                                         return true;
576                                 }
577                         }
578                         return false;
579                 }
580                 public override XPathNavigator Current
581                 {
582                         get
583                         {
584                                 if (_pos < _rgNodes.Count)
585                                         throw new Exception ("bug in UnionOperator");   // TODO: better exception
586                                 if (_pos == _rgNodes.Count)
587                                         return _left.Current;
588                                 else
589                                         return _right.Current;
590                         }
591                 }
592                 public override int CurrentPosition { get { return _pos; }}
593         }
594 }