KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > xml > dtm > ref > DTMDefaultBaseIterators


1 /*
2  * Copyright 1999-2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 /*
17  * $Id: DTMDefaultBaseIterators.java,v 1.21 2004/02/16 23:06:11 minchau Exp $
18  */

19 package org.apache.xml.dtm.ref;
20
21 import org.apache.xml.dtm.*;
22
23 import javax.xml.transform.Source JavaDoc;
24
25 import org.apache.xml.utils.XMLStringFactory;
26
27 import org.apache.xml.res.XMLErrorResources;
28 import org.apache.xml.res.XMLMessages;
29
30
31 /**
32  * This class implements the traversers for DTMDefaultBase.
33  */

34 public abstract class DTMDefaultBaseIterators extends DTMDefaultBaseTraversers
35 {
36
37   /**
38    * Construct a DTMDefaultBaseTraversers object from a DOM node.
39    *
40    * @param mgr The DTMManager who owns this DTM.
41    * @param domSource the DOM source that this DTM will wrap.
42    * @param source The object that is used to specify the construction source.
43    * @param dtmIdentity The DTM identity ID for this DTM.
44    * @param whiteSpaceFilter The white space filter for this DTM, which may
45    * be null.
46    * @param xstringfactory The factory to use for creating XMLStrings.
47    * @param doIndexing true if the caller considers it worth it to use
48    * indexing schemes.
49    */

50   public DTMDefaultBaseIterators(DTMManager mgr, Source JavaDoc source,
51                                  int dtmIdentity,
52                                  DTMWSFilter whiteSpaceFilter,
53                                  XMLStringFactory xstringfactory,
54                                  boolean doIndexing)
55   {
56     super(mgr, source, dtmIdentity, whiteSpaceFilter,
57           xstringfactory, doIndexing);
58   }
59
60   /**
61    * Construct a DTMDefaultBaseTraversers object from a DOM node.
62    *
63    * @param mgr The DTMManager who owns this DTM.
64    * @param domSource the DOM source that this DTM will wrap.
65    * @param source The object that is used to specify the construction source.
66    * @param dtmIdentity The DTM identity ID for this DTM.
67    * @param whiteSpaceFilter The white space filter for this DTM, which may
68    * be null.
69    * @param xstringfactory The factory to use for creating XMLStrings.
70    * @param doIndexing true if the caller considers it worth it to use
71    * indexing schemes.
72    * @param blocksize The block size of the DTM.
73    * @param usePrevsib true if we want to build the previous sibling node array.
74    * @param newNameTable true if we want to use a new ExpandedNameTable for this DTM.
75    */

76   public DTMDefaultBaseIterators(DTMManager mgr, Source JavaDoc source,
77                                  int dtmIdentity,
78                                  DTMWSFilter whiteSpaceFilter,
79                                  XMLStringFactory xstringfactory,
80                                  boolean doIndexing,
81                                  int blocksize,
82                                  boolean usePrevsib,
83                                  boolean newNameTable)
84   {
85     super(mgr, source, dtmIdentity, whiteSpaceFilter,
86           xstringfactory, doIndexing, blocksize, usePrevsib, newNameTable);
87   }
88
89   /**
90    * Get an iterator that can navigate over an XPath Axis, predicated by
91    * the extended type ID.
92    * Returns an iterator that must be initialized
93    * with a start node (using iterator.setStartNode()).
94    *
95    * @param axis One of Axes.ANCESTORORSELF, etc.
96    * @param type An extended type ID.
97    *
98    * @return A DTMAxisIterator, or null if the given axis isn't supported.
99    */

100   public DTMAxisIterator getTypedAxisIterator(int axis, int type)
101   {
102
103     DTMAxisIterator iterator = null;
104
105     /* This causes an error when using patterns for elements that
106        do not exist in the DOM (translet types which do not correspond
107        to a DOM type are mapped to the DOM.ELEMENT type).
108     */

109
110     // if (type == NO_TYPE) {
111
// return(EMPTYITERATOR);
112
// }
113
// else if (type == ELEMENT) {
114
// iterator = new FilterIterator(getAxisIterator(axis),
115
// getElementFilter());
116
// }
117
// else
118
{
119       switch (axis)
120       {
121       case Axis.SELF :
122         iterator = new TypedSingletonIterator(type);
123         break;
124       case Axis.CHILD :
125         iterator = new TypedChildrenIterator(type);
126         break;
127       case Axis.PARENT :
128         return (new ParentIterator().setNodeType(type));
129       case Axis.ANCESTOR :
130         return (new TypedAncestorIterator(type));
131       case Axis.ANCESTORORSELF :
132         return ((new TypedAncestorIterator(type)).includeSelf());
133       case Axis.ATTRIBUTE :
134         return (new TypedAttributeIterator(type));
135       case Axis.DESCENDANT :
136         iterator = new TypedDescendantIterator(type);
137         break;
138       case Axis.DESCENDANTORSELF :
139         iterator = (new TypedDescendantIterator(type)).includeSelf();
140         break;
141       case Axis.FOLLOWING :
142         iterator = new TypedFollowingIterator(type);
143         break;
144       case Axis.PRECEDING :
145         iterator = new TypedPrecedingIterator(type);
146         break;
147       case Axis.FOLLOWINGSIBLING :
148         iterator = new TypedFollowingSiblingIterator(type);
149         break;
150       case Axis.PRECEDINGSIBLING :
151         iterator = new TypedPrecedingSiblingIterator(type);
152         break;
153       case Axis.NAMESPACE :
154         iterator = new TypedNamespaceIterator(type);
155         break;
156       case Axis.ROOT :
157         iterator = new TypedRootIterator(type);
158         break;
159       default :
160         throw new DTMException(XMLMessages.createXMLMessage(XMLErrorResources.ER_TYPED_ITERATOR_AXIS_NOT_IMPLEMENTED, new Object JavaDoc[]{Axis.names[axis]})); //"Error: typed iterator for axis "
161
//+ Axis.names[axis] + "not implemented");
162
}
163     }
164
165     return (iterator);
166   }
167
168   /**
169    * This is a shortcut to the iterators that implement the
170    * XPath axes.
171    * Returns a bare-bones iterator that must be initialized
172    * with a start node (using iterator.setStartNode()).
173    *
174    * @param axis One of Axes.ANCESTORORSELF, etc.
175    *
176    * @return A DTMAxisIterator, or null if the given axis isn't supported.
177    */

178   public DTMAxisIterator getAxisIterator(final int axis)
179   {
180
181     DTMAxisIterator iterator = null;
182
183     switch (axis)
184     {
185     case Axis.SELF :
186       iterator = new SingletonIterator();
187       break;
188     case Axis.CHILD :
189       iterator = new ChildrenIterator();
190       break;
191     case Axis.PARENT :
192       return (new ParentIterator());
193     case Axis.ANCESTOR :
194       return (new AncestorIterator());
195     case Axis.ANCESTORORSELF :
196       return ((new AncestorIterator()).includeSelf());
197     case Axis.ATTRIBUTE :
198       return (new AttributeIterator());
199     case Axis.DESCENDANT :
200       iterator = new DescendantIterator();
201       break;
202     case Axis.DESCENDANTORSELF :
203       iterator = (new DescendantIterator()).includeSelf();
204       break;
205     case Axis.FOLLOWING :
206       iterator = new FollowingIterator();
207       break;
208     case Axis.PRECEDING :
209       iterator = new PrecedingIterator();
210       break;
211     case Axis.FOLLOWINGSIBLING :
212       iterator = new FollowingSiblingIterator();
213       break;
214     case Axis.PRECEDINGSIBLING :
215       iterator = new PrecedingSiblingIterator();
216       break;
217     case Axis.NAMESPACE :
218       iterator = new NamespaceIterator();
219       break;
220     case Axis.ROOT :
221       iterator = new RootIterator();
222       break;
223     default :
224       throw new DTMException(XMLMessages.createXMLMessage(XMLErrorResources.ER_ITERATOR_AXIS_NOT_IMPLEMENTED, new Object JavaDoc[]{Axis.names[axis]})); //"Error: iterator for axis '" + Axis.names[axis]
225
//+ "' not implemented");
226
}
227
228     return (iterator);
229   }
230
231   /**
232    * Abstract superclass defining behaviors shared by all DTMDefault's
233    * internal implementations of DTMAxisIterator. Subclass this (and
234    * override, if necessary) to implement the specifics of an
235    * individual axis iterator.
236    *
237    * Currently there isn't a lot here
238    */

239   public abstract class InternalAxisIteratorBase extends DTMAxisIteratorBase
240   {
241
242     // %REVIEW% We could opt to share _nodeType and setNodeType() as
243
// well, and simply ignore them in iterators which don't use them.
244
// But Scott's worried about the overhead involved in cloning
245
// these, and wants them to have as few fields as possible. Note
246
// that we can't create a TypedInternalAxisIteratorBase because
247
// those are often based on the untyped versions and Java doesn't
248
// support multiple inheritance. <sigh/>
249

250     /**
251      * Current iteration location. Usually this is the last location
252      * returned (starting point for the next() search); for single-node
253      * iterators it may instead be initialized to point to that single node.
254      */

255     protected int _currentNode;
256
257     /**
258      * Remembers the current node for the next call to gotoMark().
259      *
260      * %REVIEW% Should this save _position too?
261      */

262     public void setMark()
263     {
264       _markedNode = _currentNode;
265     }
266
267     /**
268      * Restores the current node remembered by setMark().
269      *
270      * %REVEIW% Should this restore _position too?
271      */

272     public void gotoMark()
273     {
274       _currentNode = _markedNode;
275     }
276         
277   } // end of InternalAxisIteratorBase
278

279   /**
280    * Iterator that returns all immediate children of a given node
281    */

282   public final class ChildrenIterator extends InternalAxisIteratorBase
283   {
284
285     /**
286      * Setting start to END should 'close' the iterator,
287      * i.e. subsequent call to next() should return END.
288      *
289      * If the iterator is not restartable, this has no effect.
290      * %REVIEW% Should it return/throw something in that case,
291      * or set current node to END, to indicate request-not-honored?
292      *
293      * @param node Sets the root of the iteration.
294      *
295      * @return A DTMAxisIterator set to the start of the iteration.
296      */

297     public DTMAxisIterator setStartNode(int node)
298     {
299 //%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
300
if (node == DTMDefaultBase.ROOTNODE)
301         node = getDocument();
302       if (_isRestartable)
303       {
304         _startNode = node;
305         _currentNode = (node == DTM.NULL) ? DTM.NULL
306                                           : _firstch(makeNodeIdentity(node));
307
308         return resetPosition();
309       }
310
311       return this;
312     }
313
314     /**
315      * Get the next node in the iteration.
316      *
317      * @return The next node handle in the iteration, or END if no more
318      * are available.
319      */

320     public int next()
321     {
322       if (_currentNode != NULL) {
323         int node = _currentNode;
324         _currentNode = _nextsib(node);
325         return returnNode(makeNodeHandle(node));
326       }
327
328       return END;
329     }
330   } // end of ChildrenIterator
331

332   /**
333    * Iterator that returns the parent of a given node. Note that
334    * this delivers only a single node; if you want all the ancestors,
335    * see AncestorIterator.
336    */

337   public final class ParentIterator extends InternalAxisIteratorBase
338   {
339
340     /** The extended type ID that was requested. */
341     private int _nodeType = -1;
342
343     /**
344      * Set start to END should 'close' the iterator,
345      * i.e. subsequent call to next() should return END.
346      *
347      * @param node Sets the root of the iteration.
348      *
349      * @return A DTMAxisIterator set to the start of the iteration.
350      */

351     public DTMAxisIterator setStartNode(int node)
352     {
353 //%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
354
if (node == DTMDefaultBase.ROOTNODE)
355         node = getDocument();
356       if (_isRestartable)
357       {
358         _startNode = node;
359         _currentNode = getParent(node);
360
361         return resetPosition();
362       }
363
364       return this;
365     }
366
367     /**
368      * Set the node type of the parent that we're looking for.
369      * Note that this does _not_ mean "find the nearest ancestor of
370      * this type", but "yield the parent if it is of this type".
371      *
372      *
373      * @param type extended type ID.
374      *
375      * @return ParentIterator configured with the type filter set.
376      */

377     public DTMAxisIterator setNodeType(final int type)
378     {
379
380       _nodeType = type;
381
382       return this;
383     }
384
385     /**
386      * Get the next node in the iteration. In this case, we return
387      * only the immediate parent, _if_ it matches the requested nodeType.
388      *
389      * @return The next node handle in the iteration, or END.
390      */

391     public int next()
392     {
393       int result = _currentNode;
394
395       if (_nodeType >= DTM.NTYPES) {
396         if (_nodeType != getExpandedTypeID(_currentNode)) {
397           result = END;
398         }
399       } else if (_nodeType != NULL) {
400         if (_nodeType != getNodeType(_currentNode)) {
401           result = END;
402         }
403       }
404
405       _currentNode = END;
406
407       return returnNode(result);
408     }
409   } // end of ParentIterator
410

411   /**
412    * Iterator that returns children of a given type for a given node.
413    * The functionality chould be achieved by putting a filter on top
414    * of a basic child iterator, but a specialised iterator is used
415    * for efficiency (both speed and size of translet).
416    */

417   public final class TypedChildrenIterator extends InternalAxisIteratorBase
418   {
419
420     /** The extended type ID that was requested. */
421     private final int _nodeType;
422
423     /**
424      * Constructor TypedChildrenIterator
425      *
426      *
427      * @param nodeType The extended type ID being requested.
428      */

429     public TypedChildrenIterator(int nodeType)
430     {
431       _nodeType = nodeType;
432     }
433
434     /**
435      * Set start to END should 'close' the iterator,
436      * i.e. subsequent call to next() should return END.
437      *
438      * @param node Sets the root of the iteration.
439      *
440      * @return A DTMAxisIterator set to the start of the iteration.
441      */

442     public DTMAxisIterator setStartNode(int node)
443     {
444 //%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
445
if (node == DTMDefaultBase.ROOTNODE)
446         node = getDocument();
447       if (_isRestartable)
448       {
449         _startNode = node;
450         _currentNode = (node == DTM.NULL)
451                                    ? DTM.NULL
452                                    : _firstch(makeNodeIdentity(_startNode));
453
454         return resetPosition();
455       }
456
457       return this;
458     }
459
460     /**
461      * Get the next node in the iteration.
462      *
463      * @return The next node handle in the iteration, or END.
464      */

465     public int next()
466     {
467       int eType;
468       int node = _currentNode;
469
470       int nodeType = _nodeType;
471
472       if (nodeType >= DTM.NTYPES) {
473         while (node != DTM.NULL && _exptype(node) != nodeType) {
474           node = _nextsib(node);
475         }
476       } else {
477         while (node != DTM.NULL) {
478           eType = _exptype(node);
479           if (eType < DTM.NTYPES) {
480             if (eType == nodeType) {
481               break;
482             }
483           } else if (m_expandedNameTable.getType(eType) == nodeType) {
484             break;
485           }
486           node = _nextsib(node);
487         }
488       }
489
490       if (node == DTM.NULL) {
491         _currentNode = DTM.NULL;
492         return DTM.NULL;
493       } else {
494         _currentNode = _nextsib(node);
495         return returnNode(makeNodeHandle(node));
496       }
497
498     }
499   } // end of TypedChildrenIterator
500

501   /**
502    * Iterator that returns children within a given namespace for a
503    * given node. The functionality chould be achieved by putting a
504    * filter on top of a basic child iterator, but a specialised
505    * iterator is used for efficiency (both speed and size of translet).
506    */

507   public final class NamespaceChildrenIterator
508           extends InternalAxisIteratorBase
509   {
510
511     /** The extended type ID being requested. */
512     private final int _nsType;
513
514     /**
515      * Constructor NamespaceChildrenIterator
516      *
517      *
518      * @param type The extended type ID being requested.
519      */

520     public NamespaceChildrenIterator(final int type)
521     {
522       _nsType = type;
523     }
524
525     /**
526      * Set start to END should 'close' the iterator,
527      * i.e. subsequent call to next() should return END.
528      *
529      * @param node Sets the root of the iteration.
530      *
531      * @return A DTMAxisIterator set to the start of the iteration.
532      */

533     public DTMAxisIterator setStartNode(int node)
534     {
535 //%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
536
if (node == DTMDefaultBase.ROOTNODE)
537         node = getDocument();
538       if (_isRestartable)
539       {
540         _startNode = node;
541         _currentNode = (node == DTM.NULL) ? DTM.NULL : NOTPROCESSED;
542
543         return resetPosition();
544       }
545
546       return this;
547     }
548
549     /**
550      * Get the next node in the iteration.
551      *
552      * @return The next node handle in the iteration, or END.
553      */

554     public int next()
555     {
556       if (_currentNode != DTM.NULL) {
557         for (int node = (NOTPROCESSED == _currentNode)
558                                   ? _firstch(makeNodeIdentity(_startNode))
559                                   : _nextsib(_currentNode);
560              node != END;
561              node = _nextsib(node)) {
562           if (m_expandedNameTable.getNamespaceID(_exptype(node)) == _nsType) {
563             _currentNode = node;
564
565             return returnNode(node);
566           }
567         }
568       }
569
570       return END;
571     }
572   } // end of NamespaceChildrenIterator
573

574   /**
575    * Iterator that returns the namespace nodes as defined by the XPath data model
576    * for a given node.
577    */

578   public class NamespaceIterator
579           extends InternalAxisIteratorBase
580   {
581
582     /**
583      * Constructor NamespaceAttributeIterator
584      */

585     public NamespaceIterator()
586     {
587
588       super();
589     }
590
591     /**
592      * Set start to END should 'close' the iterator,
593      * i.e. subsequent call to next() should return END.
594      *
595      * @param node Sets the root of the iteration.
596      *
597      * @return A DTMAxisIterator set to the start of the iteration.
598      */

599     public DTMAxisIterator setStartNode(int node)
600     {
601 //%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
602
if (node == DTMDefaultBase.ROOTNODE)
603         node = getDocument();
604       if (_isRestartable)
605       {
606         _startNode = node;
607         _currentNode = getFirstNamespaceNode(node, true);
608
609         return resetPosition();
610       }
611
612       return this;
613     }
614
615     /**
616      * Get the next node in the iteration.
617      *
618      * @return The next node handle in the iteration, or END.
619      */

620     public int next()
621     {
622
623       int node = _currentNode;
624
625       if (DTM.NULL != node)
626         _currentNode = getNextNamespaceNode(_startNode, node, true);
627
628       return returnNode(node);
629     }
630   } // end of NamespaceIterator
631

632   /**
633    * Iterator that returns the namespace nodes as defined by the XPath data model
634    * for a given node, filtered by extended type ID.
635    */

636   public class TypedNamespaceIterator extends NamespaceIterator
637   {
638
639     /** The extended type ID that was requested. */
640     private final int _nodeType;
641
642     /**
643      * Constructor TypedNamespaceIterator
644      *
645      *
646      * @param nodeType The extended type ID being requested.
647      */

648     public TypedNamespaceIterator(int nodeType)
649     {
650       super();
651       _nodeType = nodeType;
652     }
653
654     /**
655      * Get the next node in the iteration.
656      *
657      * @return The next node handle in the iteration, or END.
658      */

659     public int next()
660     {
661         int node;
662
663       for (node = _currentNode;
664            node != END;
665            node = getNextNamespaceNode(_startNode, node, true)) {
666         if (getExpandedTypeID(node) == _nodeType
667             || getNodeType(node) == _nodeType
668             || getNamespaceType(node) == _nodeType) {
669           _currentNode = node;
670
671           return returnNode(node);
672         }
673       }
674
675       return (_currentNode =END);
676     }
677   } // end of TypedNamespaceIterator
678

679   /**
680    * Iterator that returns the the root node as defined by the XPath data model
681    * for a given node.
682    */

683   public class RootIterator
684           extends InternalAxisIteratorBase
685   {
686
687     /**
688      * Constructor RootIterator
689      */

690     public RootIterator()
691     {
692
693       super();
694     }
695
696     /**
697      * Set start to END should 'close' the iterator,
698      * i.e. subsequent call to next() should return END.
699      *
700      * @param node Sets the root of the iteration.
701      *
702      * @return A DTMAxisIterator set to the start of the iteration.
703      */

704     public DTMAxisIterator setStartNode(int node)
705     {
706
707       if (_isRestartable)
708       {
709         _startNode = getDocumentRoot(node);
710         _currentNode = NULL;
711
712         return resetPosition();
713       }
714
715       return this;
716     }
717
718     /**
719      * Get the next node in the iteration.
720      *
721      * @return The next node handle in the iteration, or END.
722      */

723     public int next()
724     {
725       if(_startNode == _currentNode)
726         return NULL;
727
728       _currentNode = _startNode;
729
730       return returnNode(_startNode);
731     }
732   } // end of RootIterator
733

734   /**
735    * Iterator that returns the namespace nodes as defined by the XPath data model
736    * for a given node, filtered by extended type ID.
737    */

738   public class TypedRootIterator extends RootIterator
739   {
740
741     /** The extended type ID that was requested. */
742     private final int _nodeType;
743
744     /**
745      * Constructor TypedRootIterator
746      *
747      * @param nodeType The extended type ID being requested.
748      */

749     public TypedRootIterator(int nodeType)
750     {
751       super();
752       _nodeType = nodeType;
753     }
754
755     /**
756      * Get the next node in the iteration.
757      *
758      * @return The next node handle in the iteration, or END.
759      */

760     public int next()
761     {
762         if(_startNode == _currentNode)
763         return NULL;
764
765       int nodeType = _nodeType;
766       int node = _startNode;
767       int expType = getExpandedTypeID(node);
768
769       _currentNode = node;
770
771       if (nodeType >= DTM.NTYPES) {
772         if (nodeType == expType) {
773           return returnNode(node);
774         }
775       } else {
776         if (expType < DTM.NTYPES) {
777           if (expType == nodeType) {
778             return returnNode(node);
779           }
780         } else {
781           if (m_expandedNameTable.getType(expType) == nodeType) {
782             return returnNode(node);
783           }
784         }
785       }
786
787       return END;
788     }
789   } // end of TypedRootIterator
790

791   /**
792    * Iterator that returns attributes within a given namespace for a node.
793    */

794   public final class NamespaceAttributeIterator
795           extends InternalAxisIteratorBase
796   {
797
798     /** The extended type ID being requested. */
799     private final int _nsType;
800
801     /**
802      * Constructor NamespaceAttributeIterator
803      *
804      *
805      * @param nsType The extended type ID being requested.
806      */

807     public NamespaceAttributeIterator(int nsType)
808     {
809
810       super();
811
812       _nsType = nsType;
813     }
814
815     /**
816      * Set start to END should 'close' the iterator,
817      * i.e. subsequent call to next() should return END.
818      *
819      * @param node Sets the root of the iteration.
820      *
821      * @return A DTMAxisIterator set to the start of the iteration.
822      */

823     public DTMAxisIterator setStartNode(int node)
824     {
825 //%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
826
if (node == DTMDefaultBase.ROOTNODE)
827         node = getDocument();
828       if (_isRestartable)
829       {
830         _startNode = node;
831         _currentNode = getFirstNamespaceNode(node, false);
832
833         return resetPosition();
834       }
835
836       return this;
837     }
838
839     /**
840      * Get the next node in the iteration.
841      *
842      * @return The next node handle in the iteration, or END.
843      */

844     public int next()
845     {
846
847       int node = _currentNode;
848
849       if (DTM.NULL != node)
850         _currentNode = getNextNamespaceNode(_startNode, node, false);
851
852       return returnNode(node);
853     }
854   } // end of NamespaceAttributeIterator
855

856   /**
857    * Iterator that returns all siblings of a given node.
858    */

859   public class FollowingSiblingIterator extends InternalAxisIteratorBase
860   {
861
862     /**
863      * Set start to END should 'close' the iterator,
864      * i.e. subsequent call to next() should return END.
865      *
866      * @param node Sets the root of the iteration.
867      *
868      * @return A DTMAxisIterator set to the start of the iteration.
869      */

870     public DTMAxisIterator setStartNode(int node)
871     {
872 //%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
873
if (node == DTMDefaultBase.ROOTNODE)
874         node = getDocument();
875       if (_isRestartable)
876       {
877         _startNode = node;
878         _currentNode = makeNodeIdentity(node);
879
880         return resetPosition();
881       }
882
883       return this;
884     }
885
886     /**
887      * Get the next node in the iteration.
888      *
889      * @return The next node handle in the iteration, or END.
890      */

891     public int next()
892     {
893       _currentNode = (_currentNode == DTM.NULL) ? DTM.NULL
894                                                 : _nextsib(_currentNode);
895       return returnNode(makeNodeHandle(_currentNode));
896     }
897   } // end of FollowingSiblingIterator
898

899   /**
900    * Iterator that returns all following siblings of a given node.
901    */

902   public final class TypedFollowingSiblingIterator
903           extends FollowingSiblingIterator
904   {
905
906     /** The extended type ID that was requested. */
907     private final int _nodeType;
908
909     /**
910      * Constructor TypedFollowingSiblingIterator
911      *
912      *
913      * @param type The extended type ID being requested.
914      */

915     public TypedFollowingSiblingIterator(int type)
916     {
917       _nodeType = type;
918     }
919
920     /**
921      * Get the next node in the iteration.
922      *
923      * @return The next node handle in the iteration, or END.
924      */

925     public int next()
926     {
927       if (_currentNode == DTM.NULL) {
928         return DTM.NULL;
929       }
930
931       int node = _currentNode;
932       int eType;
933       int nodeType = _nodeType;
934
935       if (nodeType >= DTM.NTYPES) {
936         do {
937           node = _nextsib(node);
938         } while (node != DTM.NULL && _exptype(node) != nodeType);
939       } else {
940         while ((node = _nextsib(node)) != DTM.NULL) {
941           eType = _exptype(node);
942           if (eType < DTM.NTYPES) {
943             if (eType == nodeType) {
944               break;
945             }
946           } else if (m_expandedNameTable.getType(eType) == nodeType) {
947             break;
948           }
949         }
950       }
951
952       _currentNode = node;
953
954       return (_currentNode == DTM.NULL)
955                       ? DTM.NULL
956                       : returnNode(makeNodeHandle(_currentNode));
957     }
958   } // end of TypedFollowingSiblingIterator
959

960   /**
961    * Iterator that returns attribute nodes (of what nodes?)
962    */

963   public final class AttributeIterator extends InternalAxisIteratorBase
964   {
965
966     // assumes caller will pass element nodes
967

968     /**
969      * Set start to END should 'close' the iterator,
970      * i.e. subsequent call to next() should return END.
971      *
972      * @param node Sets the root of the iteration.
973      *
974      * @return A DTMAxisIterator set to the start of the iteration.
975      */

976     public DTMAxisIterator setStartNode(int node)
977     {
978 //%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
979
if (node == DTMDefaultBase.ROOTNODE)
980         node = getDocument();
981       if (_isRestartable)
982       {
983         _startNode = node;
984         _currentNode = getFirstAttributeIdentity(makeNodeIdentity(node));
985
986         return resetPosition();
987       }
988
989       return this;
990     }
991
992     /**
993      * Get the next node in the iteration.
994      *
995      * @return The next node handle in the iteration, or END.
996      */

997     public int next()
998     {
999
1000      final int node = _currentNode;
1001
1002      if (node != NULL) {
1003        _currentNode = getNextAttributeIdentity(node);
1004        return returnNode(makeNodeHandle(node));
1005      }
1006
1007      return NULL;
1008    }
1009  } // end of AttributeIterator
1010

1011  /**
1012   * Iterator that returns attribute nodes of a given type
1013   */

1014  public final class TypedAttributeIterator extends InternalAxisIteratorBase
1015  {
1016
1017    /** The extended type ID that was requested. */
1018    private final int _nodeType;
1019
1020    /**
1021     * Constructor TypedAttributeIterator
1022     *
1023     *
1024     * @param nodeType The extended type ID that is requested.
1025     */

1026    public TypedAttributeIterator(int nodeType)
1027    {
1028      _nodeType = nodeType;
1029    }
1030
1031    // assumes caller will pass element nodes
1032

1033    /**
1034     * Set start to END should 'close' the iterator,
1035     * i.e. subsequent call to next() should return END.
1036     *
1037     * @param node Sets the root of the iteration.
1038     *
1039     * @return A DTMAxisIterator set to the start of the iteration.
1040     */

1041    public DTMAxisIterator setStartNode(int node)
1042    {
1043      if (_isRestartable)
1044      {
1045        _startNode = node;
1046
1047        _currentNode = getTypedAttribute(node, _nodeType);
1048
1049        return resetPosition();
1050      }
1051
1052      return this;
1053    }
1054
1055    /**
1056     * Get the next node in the iteration.
1057     *
1058     * @return The next node handle in the iteration, or END.
1059     */

1060    public int next()
1061    {
1062
1063      final int node = _currentNode;
1064
1065      // singleton iterator, since there can only be one attribute of
1066
// a given type.
1067
_currentNode = NULL;
1068
1069      return returnNode(node);
1070    }
1071  } // end of TypedAttributeIterator
1072

1073  /**
1074   * Iterator that returns preceding siblings of a given node
1075   */

1076  public class PrecedingSiblingIterator extends InternalAxisIteratorBase
1077  {
1078
1079    /**
1080     * The node identity of _startNode for this iterator
1081     */

1082    protected int _startNodeID;
1083
1084    /**
1085     * True if this iterator has a reversed axis.
1086     *
1087     * @return true.
1088     */

1089    public boolean isReverse()
1090    {
1091      return true;
1092    }
1093
1094    /**
1095     * Set start to END should 'close' the iterator,
1096     * i.e. subsequent call to next() should return END.
1097     *
1098     * @param node Sets the root of the iteration.
1099     *
1100     * @return A DTMAxisIterator set to the start of the iteration.
1101     */

1102    public DTMAxisIterator setStartNode(int node)
1103    {
1104//%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
1105
if (node == DTMDefaultBase.ROOTNODE)
1106        node = getDocument();
1107      if (_isRestartable)
1108      {
1109        _startNode = node;
1110        node = _startNodeID = makeNodeIdentity(node);
1111
1112        if(node == NULL)
1113        {
1114          _currentNode = node;
1115          return resetPosition();
1116        }
1117
1118        int type = m_expandedNameTable.getType(_exptype(node));
1119        if(ExpandedNameTable.ATTRIBUTE == type
1120           || ExpandedNameTable.NAMESPACE == type )
1121        {
1122          _currentNode = node;
1123        }
1124        else
1125        {
1126          // Be careful to handle the Document node properly
1127
_currentNode = _parent(node);
1128          if(NULL!=_currentNode)
1129            _currentNode = _firstch(_currentNode);
1130          else
1131            _currentNode = node;
1132        }
1133
1134        return resetPosition();
1135      }
1136
1137      return this;
1138    }
1139
1140    /**
1141     * Get the next node in the iteration.
1142     *
1143     * @return The next node handle in the iteration, or END.
1144     */

1145    public int next()
1146    {
1147
1148      if (_currentNode == _startNodeID || _currentNode == DTM.NULL)
1149      {
1150        return NULL;
1151      }
1152      else
1153      {
1154        final int node = _currentNode;
1155        _currentNode = _nextsib(node);
1156
1157        return returnNode(makeNodeHandle(node));
1158      }
1159    }
1160  } // end of PrecedingSiblingIterator
1161

1162  /**
1163   * Iterator that returns preceding siblings of a given type for
1164   * a given node
1165   */

1166  public final class TypedPrecedingSiblingIterator
1167          extends PrecedingSiblingIterator
1168  {
1169
1170    /** The extended type ID that was requested. */
1171    private final int _nodeType;
1172
1173    /**
1174     * Constructor TypedPrecedingSiblingIterator
1175     *
1176     *
1177     * @param type The extended type ID being requested.
1178     */

1179    public TypedPrecedingSiblingIterator(int type)
1180    {
1181      _nodeType = type;
1182    }
1183
1184    /**
1185     * Get the next node in the iteration.
1186     *
1187     * @return The next node handle in the iteration, or END.
1188     */

1189    public int next()
1190    {
1191      int node = _currentNode;
1192      int expType;
1193
1194      int nodeType = _nodeType;
1195      int startID = _startNodeID;
1196
1197      if (nodeType >= DTM.NTYPES) {
1198        while (node != NULL && node != startID && _exptype(node) != nodeType) {
1199          node = _nextsib(node);
1200        }
1201      } else {
1202        while (node != NULL && node != startID) {
1203          expType = _exptype(node);
1204          if (expType < DTM.NTYPES) {
1205            if (expType == nodeType) {
1206              break;
1207            }
1208          } else {
1209            if (m_expandedNameTable.getType(expType) == nodeType) {
1210              break;
1211            }
1212          }
1213          node = _nextsib(node);
1214        }
1215      }
1216
1217      if (node == DTM.NULL || node == _startNodeID) {
1218        _currentNode = NULL;
1219        return NULL;
1220      } else {
1221        _currentNode = _nextsib(node);
1222        return returnNode(makeNodeHandle(node));
1223      }
1224    }
1225  } // end of TypedPrecedingSiblingIterator
1226

1227  /**
1228   * Iterator that returns preceding nodes of a given node.
1229   * This includes the node set {root+1, start-1}, but excludes
1230   * all ancestors, attributes, and namespace nodes.
1231   */

1232  public class PrecedingIterator extends InternalAxisIteratorBase
1233  {
1234
1235    /** The max ancestors, but it can grow... */
1236    private final int _maxAncestors = 8;
1237
1238    /**
1239     * The stack of start node + ancestors up to the root of the tree,
1240     * which we must avoid.
1241     */

1242    protected int[] _stack = new int[_maxAncestors];
1243
1244    /** (not sure yet... -sb) */
1245    protected int _sp, _oldsp;
1246
1247    protected int _markedsp, _markedNode, _markedDescendant;
1248
1249    /* _currentNode precedes candidates. This is the identity, not the handle! */
1250
1251    /**
1252     * True if this iterator has a reversed axis.
1253     *
1254     * @return true since this iterator is a reversed axis.
1255     */

1256    public boolean isReverse()
1257    {
1258      return true;
1259    }
1260
1261    /**
1262     * Returns a deep copy of this iterator. The cloned iterator is not reset.
1263     *
1264     * @return a deep copy of this iterator.
1265     */

1266    public DTMAxisIterator cloneIterator()
1267    {
1268      _isRestartable = false;
1269
1270      try
1271      {
1272        final PrecedingIterator clone = (PrecedingIterator) super.clone();
1273        final int[] stackCopy = new int[_stack.length];
1274        System.arraycopy(_stack, 0, stackCopy, 0, _stack.length);
1275
1276        clone._stack = stackCopy;
1277
1278        // return clone.reset();
1279
return clone;
1280      }
1281      catch (CloneNotSupportedException JavaDoc e)
1282      {
1283        throw new DTMException(XMLMessages.createXMLMessage(XMLErrorResources.ER_ITERATOR_CLONE_NOT_SUPPORTED, null)); //"Iterator clone not supported.");
1284
}
1285    }
1286
1287    /**
1288     * Set start to END should 'close' the iterator,
1289     * i.e. subsequent call to next() should return END.
1290     *
1291     * @param node Sets the root of the iteration.
1292     *
1293     * @return A DTMAxisIterator set to the start of the iteration.
1294     */

1295    public DTMAxisIterator setStartNode(int node)
1296    {
1297//%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
1298
if (node == DTMDefaultBase.ROOTNODE)
1299        node = getDocument();
1300      if (_isRestartable)
1301      {
1302        node = makeNodeIdentity(node);
1303
1304        // iterator is not a clone
1305
int parent, index;
1306
1307       if (_type(node) == DTM.ATTRIBUTE_NODE)
1308        node = _parent(node);
1309
1310        _startNode = node;
1311        _stack[index = 0] = node;
1312        
1313       
1314
1315        parent=node;
1316        while ((parent = _parent(parent)) != NULL)
1317        {
1318            if (++index == _stack.length)
1319            {
1320                final int[] stack = new int[index + 4];
1321                System.arraycopy(_stack, 0, stack, 0, index);
1322                _stack = stack;
1323            }
1324            _stack[index] = parent;
1325        }
1326        if(index>0)
1327            --index; // Pop actual root node (if not start) back off the stack
1328

1329        _currentNode=_stack[index]; // Last parent before root node
1330

1331        _oldsp = _sp = index;
1332
1333        return resetPosition();
1334      }
1335
1336      return this;
1337    }
1338
1339    /**
1340     * Get the next node in the iteration.
1341     *
1342     * @return The next node handle in the iteration, or END.
1343     */

1344    public int next()
1345    {
1346        // Bugzilla 8324: We were forgetting to skip Attrs and NS nodes.
1347
// Also recoded the loop controls for clarity and to flatten out
1348
// the tail-recursion.
1349
for(++_currentNode;
1350            _sp>=0;
1351            ++_currentNode)
1352        {
1353            if(_currentNode < _stack[_sp])
1354            {
1355                if(_type(_currentNode) != ATTRIBUTE_NODE &&
1356                    _type(_currentNode) != NAMESPACE_NODE)
1357                    return returnNode(makeNodeHandle(_currentNode));
1358            }
1359            else
1360                --_sp;
1361        }
1362        return NULL;
1363    }
1364
1365    // redefine DTMAxisIteratorBase's reset
1366

1367    /**
1368     * Resets the iterator to the last start node.
1369     *
1370     * @return A DTMAxisIterator, which may or may not be the same as this
1371     * iterator.
1372     */

1373    public DTMAxisIterator reset()
1374    {
1375
1376      _sp = _oldsp;
1377
1378      return resetPosition();
1379    }
1380
1381    public void setMark() {
1382        _markedsp = _sp;
1383        _markedNode = _currentNode;
1384        _markedDescendant = _stack[0];
1385    }
1386
1387    public void gotoMark() {
1388        _sp = _markedsp;
1389        _currentNode = _markedNode;
1390    }
1391  } // end of PrecedingIterator
1392

1393  /**
1394   * Iterator that returns preceding nodes of agiven type for a
1395   * given node. This includes the node set {root+1, start-1}, but
1396   * excludes all ancestors.
1397   */

1398  public final class TypedPrecedingIterator extends PrecedingIterator
1399  {
1400
1401    /** The extended type ID that was requested. */
1402    private final int _nodeType;
1403
1404    /**
1405     * Constructor TypedPrecedingIterator
1406     *
1407     *
1408     * @param type The extended type ID being requested.
1409     */

1410    public TypedPrecedingIterator(int type)
1411    {
1412      _nodeType = type;
1413    }
1414
1415    /**
1416     * Get the next node in the iteration.
1417     *
1418     * @return The next node handle in the iteration, or END.
1419     */

1420    public int next()
1421    {
1422      int node = _currentNode;
1423      int nodeType = _nodeType;
1424
1425      if (nodeType >= DTM.NTYPES) {
1426        while (true) {
1427          node = node + 1;
1428
1429          if (_sp < 0) {
1430            node = NULL;
1431            break;
1432          } else if (node >= _stack[_sp]) {
1433            if (--_sp < 0) {
1434              node = NULL;
1435              break;
1436            }
1437          } else if (_exptype(node) == nodeType) {
1438            break;
1439          }
1440        }
1441      } else {
1442        int expType;
1443
1444        while (true) {
1445          node = node + 1;
1446
1447          if (_sp < 0) {
1448            node = NULL;
1449            break;
1450          } else if (node >= _stack[_sp]) {
1451            if (--_sp < 0) {
1452              node = NULL;
1453              break;
1454            }
1455          } else {
1456            expType = _exptype(node);
1457            if (expType < DTM.NTYPES) {
1458              if (expType == nodeType) {
1459                break;
1460              }
1461            } else {
1462              if (m_expandedNameTable.getType(expType) == nodeType) {
1463                break;
1464              }
1465            }
1466          }
1467        }
1468      }
1469
1470      _currentNode = node;
1471             
1472      return (node == NULL) ? NULL : returnNode(makeNodeHandle(node));
1473    }
1474  } // end of TypedPrecedingIterator
1475

1476  /**
1477   * Iterator that returns following nodes of for a given node.
1478   */

1479  public class FollowingIterator extends InternalAxisIteratorBase
1480  {
1481    DTMAxisTraverser m_traverser; // easier for now
1482

1483    public FollowingIterator()
1484    {
1485      m_traverser = getAxisTraverser(Axis.FOLLOWING);
1486    }
1487
1488    /**
1489     * Set start to END should 'close' the iterator,
1490     * i.e. subsequent call to next() should return END.
1491     *
1492     * @param node Sets the root of the iteration.
1493     *
1494     * @return A DTMAxisIterator set to the start of the iteration.
1495     */

1496    public DTMAxisIterator setStartNode(int node)
1497    {
1498//%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
1499
if (node == DTMDefaultBase.ROOTNODE)
1500        node = getDocument();
1501      if (_isRestartable)
1502      {
1503        _startNode = node;
1504
1505        // ?? -sb
1506
// find rightmost descendant (or self)
1507
// int current;
1508
// while ((node = getLastChild(current = node)) != NULL){}
1509
// _currentNode = current;
1510
_currentNode = m_traverser.first(node);
1511
1512        // _currentNode precedes possible following(node) nodes
1513
return resetPosition();
1514      }
1515
1516      return this;
1517    }
1518
1519    /**
1520     * Get the next node in the iteration.
1521     *
1522     * @return The next node handle in the iteration, or END.
1523     */

1524    public int next()
1525    {
1526
1527      int node = _currentNode;
1528
1529      _currentNode = m_traverser.next(_startNode, _currentNode);
1530
1531      return returnNode(node);
1532    }
1533  } // end of FollowingIterator
1534

1535  /**
1536   * Iterator that returns following nodes of a given type for a given node.
1537   */

1538  public final class TypedFollowingIterator extends FollowingIterator
1539  {
1540
1541    /** The extended type ID that was requested. */
1542    private final int _nodeType;
1543
1544    /**
1545     * Constructor TypedFollowingIterator
1546     *
1547     *
1548     * @param type The extended type ID being requested.
1549     */

1550    public TypedFollowingIterator(int type)
1551    {
1552      _nodeType = type;
1553    }
1554
1555    /**
1556     * Get the next node in the iteration.
1557     *
1558     * @return The next node handle in the iteration, or END.
1559     */

1560    public int next()
1561    {
1562
1563      int node;
1564
1565      do{
1566       node = _currentNode;
1567
1568      _currentNode = m_traverser.next(_startNode, _currentNode);
1569
1570      }
1571      while (node != DTM.NULL
1572             && (getExpandedTypeID(node) != _nodeType && getNodeType(node) != _nodeType));
1573
1574      return (node == DTM.NULL ? DTM.NULL :returnNode(node));
1575    }
1576  } // end of TypedFollowingIterator
1577

1578  /**
1579   * Iterator that returns the ancestors of a given node in document
1580   * order. (NOTE! This was changed from the XSLTC code!)
1581   */

1582  public class AncestorIterator extends InternalAxisIteratorBase
1583  {
1584    org.apache.xml.utils.NodeVector m_ancestors =
1585         new org.apache.xml.utils.NodeVector();
1586         
1587    int m_ancestorsPos;
1588
1589    int m_markedPos;
1590    
1591    /** The real start node for this axes, since _startNode will be adjusted. */
1592    int m_realStartNode;
1593    
1594    /**
1595     * Get start to END should 'close' the iterator,
1596     * i.e. subsequent call to next() should return END.
1597     *
1598     * @return The root node of the iteration.
1599     */

1600    public int getStartNode()
1601    {
1602      return m_realStartNode;
1603    }
1604
1605    /**
1606     * True if this iterator has a reversed axis.
1607     *
1608     * @return true since this iterator is a reversed axis.
1609     */

1610    public final boolean isReverse()
1611    {
1612      return true;
1613    }
1614
1615    /**
1616     * Returns a deep copy of this iterator. The cloned iterator is not reset.
1617     *
1618     * @return a deep copy of this iterator.
1619     */

1620    public DTMAxisIterator cloneIterator()
1621    {
1622      _isRestartable = false; // must set to false for any clone
1623

1624      try
1625      {
1626        final AncestorIterator clone = (AncestorIterator) super.clone();
1627
1628        clone._startNode = _startNode;
1629
1630        // return clone.reset();
1631
return clone;
1632      }
1633      catch (CloneNotSupportedException JavaDoc e)
1634      {
1635        throw new DTMException(XMLMessages.createXMLMessage(XMLErrorResources.ER_ITERATOR_CLONE_NOT_SUPPORTED, null)); //"Iterator clone not supported.");
1636
}
1637    }
1638
1639    /**
1640     * Set start to END should 'close' the iterator,
1641     * i.e. subsequent call to next() should return END.
1642     *
1643     * @param node Sets the root of the iteration.
1644     *
1645     * @return A DTMAxisIterator set to the start of the iteration.
1646     */

1647    public DTMAxisIterator setStartNode(int node)
1648    {
1649//%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
1650
if (node == DTMDefaultBase.ROOTNODE)
1651        node = getDocument();
1652      m_realStartNode = node;
1653
1654      if (_isRestartable)
1655      {
1656        int nodeID = makeNodeIdentity(node);
1657
1658        if (!_includeSelf && node != DTM.NULL) {
1659          nodeID = _parent(nodeID);
1660          node = makeNodeHandle(nodeID);
1661        }
1662
1663        _startNode = node;
1664
1665        while (nodeID != END) {
1666          m_ancestors.addElement(node);
1667          nodeID = _parent(nodeID);
1668          node = makeNodeHandle(nodeID);
1669        }
1670        m_ancestorsPos = m_ancestors.size()-1;
1671
1672        _currentNode = (m_ancestorsPos>=0)
1673                               ? m_ancestors.elementAt(m_ancestorsPos)
1674                               : DTM.NULL;
1675
1676        return resetPosition();
1677      }
1678
1679      return this;
1680    }
1681
1682    /**
1683     * Resets the iterator to the last start node.
1684     *
1685     * @return A DTMAxisIterator, which may or may not be the same as this
1686     * iterator.
1687     */

1688    public DTMAxisIterator reset()
1689    {
1690
1691      m_ancestorsPos = m_ancestors.size()-1;
1692
1693      _currentNode = (m_ancestorsPos>=0) ? m_ancestors.elementAt(m_ancestorsPos)
1694                                         : DTM.NULL;
1695
1696      return resetPosition();
1697    }
1698
1699    /**
1700     * Get the next node in the iteration.
1701     *
1702     * @return The next node handle in the iteration, or END.
1703     */

1704    public int next()
1705    {
1706
1707      int next = _currentNode;
1708      
1709      int pos = --m_ancestorsPos;
1710
1711      _currentNode = (pos >= 0) ? m_ancestors.elementAt(m_ancestorsPos)
1712                                : DTM.NULL;
1713      
1714      return returnNode(next);
1715    }
1716
1717    public void setMark() {
1718        m_markedPos = m_ancestorsPos;
1719    }
1720
1721    public void gotoMark() {
1722        m_ancestorsPos = m_markedPos;
1723        _currentNode = m_ancestorsPos>=0 ? m_ancestors.elementAt(m_ancestorsPos)
1724                                         : DTM.NULL;
1725    }
1726  } // end of AncestorIterator
1727

1728  /**
1729   * Typed iterator that returns the ancestors of a given node.
1730   */

1731  public final class TypedAncestorIterator extends AncestorIterator
1732  {
1733
1734    /** The extended type ID that was requested. */
1735    private final int _nodeType;
1736
1737    /**
1738     * Constructor TypedAncestorIterator
1739     *
1740     *
1741     * @param type The extended type ID being requested.
1742     */

1743    public TypedAncestorIterator(int type)
1744    {
1745      _nodeType = type;
1746    }
1747
1748    /**
1749     * Set start to END should 'close' the iterator,
1750     * i.e. subsequent call to next() should return END.
1751     *
1752     * @param node Sets the root of the iteration.
1753     *
1754     * @return A DTMAxisIterator set to the start of the iteration.
1755     */

1756    public DTMAxisIterator setStartNode(int node)
1757    {
1758//%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
1759
if (node == DTMDefaultBase.ROOTNODE)
1760        node = getDocument();
1761      m_realStartNode = node;
1762
1763      if (_isRestartable)
1764      {
1765        int nodeID = makeNodeIdentity(node);
1766        int nodeType = _nodeType;
1767
1768        if (!_includeSelf && node != DTM.NULL) {
1769          nodeID = _parent(nodeID);
1770        }
1771
1772        _startNode = node;
1773
1774        if (nodeType >= DTM.NTYPES) {
1775          while (nodeID != END) {
1776            int eType = _exptype(nodeID);
1777
1778            if (eType == nodeType) {
1779              m_ancestors.addElement(makeNodeHandle(nodeID));
1780            }
1781            nodeID = _parent(nodeID);
1782          }
1783        } else {
1784          while (nodeID != END) {
1785            int eType = _exptype(nodeID);
1786
1787            if ((eType >= DTM.NTYPES
1788                    && m_expandedNameTable.getType(eType) == nodeType)
1789                || (eType < DTM.NTYPES && eType == nodeType)) {
1790              m_ancestors.addElement(makeNodeHandle(nodeID));
1791            }
1792            nodeID = _parent(nodeID);
1793          }
1794        }
1795        m_ancestorsPos = m_ancestors.size()-1;
1796
1797        _currentNode = (m_ancestorsPos>=0)
1798                               ? m_ancestors.elementAt(m_ancestorsPos)
1799                               : DTM.NULL;
1800
1801        return resetPosition();
1802      }
1803
1804      return this;
1805    }
1806  } // end of TypedAncestorIterator
1807

1808  /**
1809   * Iterator that returns the descendants of a given node.
1810   */

1811  public class DescendantIterator extends InternalAxisIteratorBase
1812  {
1813
1814    /**
1815     * Set start to END should 'close' the iterator,
1816     * i.e. subsequent call to next() should return END.
1817     *
1818     * @param node Sets the root of the iteration.
1819     *
1820     * @return A DTMAxisIterator set to the start of the iteration.
1821     */

1822    public DTMAxisIterator setStartNode(int node)
1823    {
1824//%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
1825
if (node == DTMDefaultBase.ROOTNODE)
1826        node = getDocument();
1827      if (_isRestartable)
1828      {
1829        node = makeNodeIdentity(node);
1830        _startNode = node;
1831
1832        if (_includeSelf)
1833          node--;
1834
1835        _currentNode = node;
1836
1837        return resetPosition();
1838      }
1839
1840      return this;
1841    }
1842
1843    /**
1844     * Tell if this node identity is a descendant. Assumes that
1845     * the node info for the element has already been obtained.
1846     *
1847     * This one-sided test works only if the parent has been
1848     * previously tested and is known to be a descendent. It fails if
1849     * the parent is the _startNode's next sibling, or indeed any node
1850     * that follows _startNode in document order. That may suffice
1851     * for this iterator, but it's not really an isDescendent() test.
1852     * %REVIEW% rename?
1853     *
1854     * @param identity The index number of the node in question.
1855     * @return true if the index is a descendant of _startNode.
1856     */

1857    protected boolean isDescendant(int identity)
1858    {
1859      return (_parent(identity) >= _startNode) || (_startNode == identity);
1860    }
1861
1862    /**
1863     * Get the next node in the iteration.
1864     *
1865     * @return The next node handle in the iteration, or END.
1866     */

1867    public int next()
1868    {
1869      if (_startNode == NULL) {
1870        return NULL;
1871      }
1872
1873      if (_includeSelf && (_currentNode + 1) == _startNode)
1874          return returnNode(makeNodeHandle(++_currentNode)); // | m_dtmIdent);
1875

1876      int node = _currentNode;
1877      int type;
1878
1879      do {
1880        node++;
1881        type = _type(node);
1882
1883        if (NULL == type ||!isDescendant(node)) {
1884          _currentNode = NULL;
1885          return END;
1886        }
1887      } while(ATTRIBUTE_NODE == type || TEXT_NODE == type
1888                 || NAMESPACE_NODE == type);
1889
1890      _currentNode = node;
1891      return returnNode(makeNodeHandle(node)); // make handle.
1892
}
1893  
1894    /**
1895     * Reset.
1896     *
1897     */

1898  public DTMAxisIterator reset()
1899  {
1900
1901    final boolean temp = _isRestartable;
1902
1903    _isRestartable = true;
1904
1905    setStartNode(makeNodeHandle(_startNode));
1906
1907    _isRestartable = temp;
1908
1909    return this;
1910  }
1911    
1912  } // end of DescendantIterator
1913

1914  /**
1915   * Typed iterator that returns the descendants of a given node.
1916   */

1917  public final class TypedDescendantIterator extends DescendantIterator
1918  {
1919
1920    /** The extended type ID that was requested. */
1921    private final int _nodeType;
1922
1923    /**
1924     * Constructor TypedDescendantIterator
1925     *
1926     *
1927     * @param nodeType Extended type ID being requested.
1928     */

1929    public TypedDescendantIterator(int nodeType)
1930    {
1931      _nodeType = nodeType;
1932    }
1933
1934    /**
1935     * Get the next node in the iteration.
1936     *
1937     * @return The next node handle in the iteration, or END.
1938     */

1939    public int next()
1940    {
1941      int node;
1942      int type;
1943
1944      if (_startNode == NULL) {
1945        return NULL;
1946      }
1947
1948      node = _currentNode;
1949
1950      do
1951      {
1952        node++;
1953        type = _type(node);
1954
1955        if (NULL == type ||!isDescendant(node)) {
1956          _currentNode = NULL;
1957          return END;
1958        }
1959      }
1960      while (type != _nodeType && _exptype(node) != _nodeType);
1961
1962      _currentNode = node;
1963      return returnNode(makeNodeHandle(node));
1964    }
1965  } // end of TypedDescendantIterator
1966

1967  /**
1968   * Iterator that returns the descendants of a given node.
1969   * I'm not exactly clear about this one... -sb
1970   */

1971  public class NthDescendantIterator extends DescendantIterator
1972  {
1973
1974    /** The current nth position. */
1975    int _pos;
1976
1977    /**
1978     * Constructor NthDescendantIterator
1979     *
1980     *
1981     * @param pos The nth position being requested.
1982     */

1983    public NthDescendantIterator(int pos)
1984    {
1985      _pos = pos;
1986    }
1987
1988    /**
1989     * Get the next node in the iteration.
1990     *
1991     * @return The next node handle in the iteration, or END.
1992     */

1993    public int next()
1994    {
1995
1996      // I'm not exactly clear yet what this is doing... -sb
1997
int node;
1998
1999      while ((node = super.next()) != END)
2000      {
2001        node = makeNodeIdentity(node);
2002
2003        int parent = _parent(node);
2004        int child = _firstch(parent);
2005        int pos = 0;
2006
2007        do
2008        {
2009          int type = _type(child);
2010
2011          if (ELEMENT_NODE == type)
2012            pos++;
2013        }
2014        while ((pos < _pos) && (child = _nextsib(child)) != END);
2015
2016        if (node == child)
2017          return node;
2018      }
2019
2020      return (END);
2021    }
2022  } // end of NthDescendantIterator
2023

2024  /**
2025   * Class SingletonIterator.
2026   */

2027  public class SingletonIterator extends InternalAxisIteratorBase
2028  {
2029
2030    /** (not sure yet what this is. -sb) (sc & sb remove final to compile in JDK 1.1.8) */
2031    private boolean _isConstant;
2032
2033    /**
2034     * Constructor SingletonIterator
2035     *
2036     */

2037    public SingletonIterator()
2038    {
2039      this(Integer.MIN_VALUE, false);
2040    }
2041
2042    /**
2043     * Constructor SingletonIterator
2044     *
2045     *
2046     * @param node The node handle to return.
2047     */

2048    public SingletonIterator(int node)
2049    {
2050      this(node, false);
2051    }
2052
2053    /**
2054     * Constructor SingletonIterator
2055     *
2056     *
2057     * @param node the node handle to return.
2058     * @param constant (Not sure what this is yet. -sb)
2059     */

2060    public SingletonIterator(int node, boolean constant)
2061    {
2062      _currentNode = _startNode = node;
2063      _isConstant = constant;
2064    }
2065
2066    /**
2067     * Set start to END should 'close' the iterator,
2068     * i.e. subsequent call to next() should return END.
2069     *
2070     * @param node Sets the root of the iteration.
2071     *
2072     * @return A DTMAxisIterator set to the start of the iteration.
2073     */

2074    public DTMAxisIterator setStartNode(int node)
2075    {
2076//%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
2077
if (node == DTMDefaultBase.ROOTNODE)
2078        node = getDocument();
2079      if (_isConstant)
2080      {
2081        _currentNode = _startNode;
2082
2083        return resetPosition();
2084      }
2085      else if (_isRestartable)
2086      {
2087        if (_currentNode == Integer.MIN_VALUE)
2088        {
2089          _currentNode = _startNode = node;
2090        }
2091
2092        return resetPosition();
2093      }
2094
2095      return this;
2096    }
2097
2098    /**
2099     * Resets the iterator to the last start node.
2100     *
2101     * @return A DTMAxisIterator, which may or may not be the same as this
2102     * iterator.
2103     */

2104    public DTMAxisIterator reset()
2105    {
2106
2107      if (_isConstant)
2108      {
2109        _currentNode = _startNode;
2110
2111        return resetPosition();
2112      }
2113      else
2114      {
2115        final boolean temp = _isRestartable;
2116
2117        _isRestartable = true;
2118
2119        setStartNode(_startNode);
2120
2121        _isRestartable = temp;
2122      }
2123
2124      return this;
2125    }
2126
2127    /**
2128     * Get the next node in the iteration.
2129     *
2130     * @return The next node handle in the iteration, or END.
2131     */

2132    public int next()
2133    {
2134
2135      final int result = _currentNode;
2136
2137      _currentNode = END;
2138
2139      return returnNode(result);
2140    }
2141  } // end of SingletonIterator
2142

2143  /**
2144   * Iterator that returns a given node only if it is of a given type.
2145   */

2146  public final class TypedSingletonIterator extends SingletonIterator
2147  {
2148
2149    /** The extended type ID that was requested. */
2150    private final int _nodeType;
2151
2152    /**
2153     * Constructor TypedSingletonIterator
2154     *
2155     *
2156     * @param nodeType The extended type ID being requested.
2157     */

2158    public TypedSingletonIterator(int nodeType)
2159    {
2160      _nodeType = nodeType;
2161    }
2162
2163    /**
2164     * Get the next node in the iteration.
2165     *
2166     * @return The next node handle in the iteration, or END.
2167     */

2168    public int next()
2169    {
2170
2171      //final int result = super.next();
2172
final int result = _currentNode;
2173      int nodeType = _nodeType;
2174
2175      _currentNode = END;
2176
2177      if (nodeType >= DTM.NTYPES) {
2178        if (getExpandedTypeID(result) == nodeType) {
2179          return returnNode(result);
2180        }
2181      } else {
2182        if (getNodeType(result) == nodeType) {
2183          return returnNode(result);
2184        }
2185      }
2186
2187      return NULL;
2188    }
2189  } // end of TypedSingletonIterator
2190
}
2191
Popular Tags