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