View Javadoc
1   /*
2    * reserved comment block
3    * DO NOT REMOVE OR ALTER!
4    */
5   /*
6    * Copyright 1999-2004 The Apache Software Foundation.
7    *
8    * Licensed under the Apache License, Version 2.0 (the "License");
9    * you may not use this file except in compliance with the License.
10   * You may obtain a copy of the License at
11   *
12   *     http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing, software
15   * distributed under the License is distributed on an "AS IS" BASIS,
16   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17   * See the License for the specific language governing permissions and
18   * limitations under the License.
19   */
20  /*
21   * $Id: DTMDefaultBaseIterators.java,v 1.2.4.1 2005/09/15 08:15:00 suresh_emailid Exp $
22   */
23  package com.sun.org.apache.xml.internal.dtm.ref;
24  
25  import com.sun.org.apache.xml.internal.dtm.*;
26  
27  import javax.xml.transform.Source;
28  
29  import com.sun.org.apache.xml.internal.utils.XMLStringFactory;
30  
31  import com.sun.org.apache.xml.internal.res.XMLErrorResources;
32  import com.sun.org.apache.xml.internal.res.XMLMessages;
33  import com.sun.org.apache.xalan.internal.xsltc.dom.NodeCounter;
34  
35  /**
36   * This class implements the traversers for DTMDefaultBase.
37   */
38  public abstract class DTMDefaultBaseIterators extends DTMDefaultBaseTraversers
39  {
40  
41    /**
42     * Construct a DTMDefaultBaseTraversers object from a DOM node.
43     *
44     * @param mgr The DTMManager who owns this DTM.
45     * @param source The object that is used to specify the construction source.
46     * @param dtmIdentity The DTM identity ID for this DTM.
47     * @param whiteSpaceFilter The white space filter for this DTM, which may
48     *                         be null.
49     * @param xstringfactory The factory to use for creating XMLStrings.
50     * @param doIndexing true if the caller considers it worth it to use
51     *                   indexing schemes.
52     */
53    public DTMDefaultBaseIterators(DTMManager mgr, Source source,
54                                   int dtmIdentity,
55                                   DTMWSFilter whiteSpaceFilter,
56                                   XMLStringFactory xstringfactory,
57                                   boolean doIndexing)
58    {
59      super(mgr, source, dtmIdentity, whiteSpaceFilter,
60            xstringfactory, doIndexing);
61    }
62  
63    /**
64     * Construct a DTMDefaultBaseTraversers object from a DOM node.
65     *
66     * @param mgr The DTMManager who owns this DTM.
67     * @param source The object that is used to specify the construction source.
68     * @param dtmIdentity The DTM identity ID for this DTM.
69     * @param whiteSpaceFilter The white space filter for this DTM, which may
70     *                         be null.
71     * @param xstringfactory The factory to use for creating XMLStrings.
72     * @param doIndexing true if the caller considers it worth it to use
73     *                   indexing schemes.
74     * @param blocksize The block size of the DTM.
75     * @param usePrevsib true if we want to build the previous sibling node array.
76     * @param newNameTable true if we want to use a new ExpandedNameTable for this DTM.
77     */
78    public DTMDefaultBaseIterators(DTMManager mgr, Source source,
79                                   int dtmIdentity,
80                                   DTMWSFilter whiteSpaceFilter,
81                                   XMLStringFactory xstringfactory,
82                                   boolean doIndexing,
83                                   int blocksize,
84                                   boolean usePrevsib,
85                                   boolean newNameTable)
86    {
87      super(mgr, source, dtmIdentity, whiteSpaceFilter,
88            xstringfactory, doIndexing, blocksize, usePrevsib, newNameTable);
89    }
90  
91    /**
92     * Get an iterator that can navigate over an XPath Axis, predicated by
93     * the extended type ID.
94     * Returns an iterator that must be initialized
95     * with a start node (using iterator.setStartNode()).
96     *
97     * @param axis One of Axes.ANCESTORORSELF, etc.
98     * @param type An extended type ID.
99     *
100    * @return A DTMAxisIterator, or null if the given axis isn't supported.
101    */
102   public DTMAxisIterator getTypedAxisIterator(int axis, int type)
103   {
104 
105     DTMAxisIterator iterator = null;
106 
107     /* This causes an error when using patterns for elements that
108        do not exist in the DOM (translet types which do not correspond
109        to a DOM type are mapped to the DOM.ELEMENT type).
110     */
111 
112     //        if (type == NO_TYPE) {
113     //            return(EMPTYITERATOR);
114     //        }
115     //        else if (type == ELEMENT) {
116     //            iterator = new FilterIterator(getAxisIterator(axis),
117     //                                          getElementFilter());
118     //        }
119     //        else
120     {
121       switch (axis)
122       {
123       case Axis.SELF :
124         iterator = new TypedSingletonIterator(type);
125         break;
126       case Axis.CHILD :
127         iterator = new TypedChildrenIterator(type);
128         break;
129       case Axis.PARENT :
130         return (new ParentIterator().setNodeType(type));
131       case Axis.ANCESTOR :
132         return (new TypedAncestorIterator(type));
133       case Axis.ANCESTORORSELF :
134         return ((new TypedAncestorIterator(type)).includeSelf());
135       case Axis.ATTRIBUTE :
136         return (new TypedAttributeIterator(type));
137       case Axis.DESCENDANT :
138         iterator = new TypedDescendantIterator(type);
139         break;
140       case Axis.DESCENDANTORSELF :
141         iterator = (new TypedDescendantIterator(type)).includeSelf();
142         break;
143       case Axis.FOLLOWING :
144         iterator = new TypedFollowingIterator(type);
145         break;
146       case Axis.PRECEDING :
147         iterator = new TypedPrecedingIterator(type);
148         break;
149       case Axis.FOLLOWINGSIBLING :
150         iterator = new TypedFollowingSiblingIterator(type);
151         break;
152       case Axis.PRECEDINGSIBLING :
153         iterator = new TypedPrecedingSiblingIterator(type);
154         break;
155       case Axis.NAMESPACE :
156         iterator = new TypedNamespaceIterator(type);
157         break;
158       case Axis.ROOT :
159         iterator = new TypedRootIterator(type);
160         break;
161       default :
162         throw new DTMException(XMLMessages.createXMLMessage(
163             XMLErrorResources.ER_TYPED_ITERATOR_AXIS_NOT_IMPLEMENTED,
164             new Object[]{Axis.getNames(axis)}));
165             //"Error: typed iterator for axis "
166                                //+ Axis.names[axis] + "not implemented");
167       }
168     }
169 
170     return (iterator);
171   }
172 
173   /**
174    * This is a shortcut to the iterators that implement the
175    * XPath axes.
176    * Returns a bare-bones iterator that must be initialized
177    * with a start node (using iterator.setStartNode()).
178    *
179    * @param axis One of Axes.ANCESTORORSELF, etc.
180    *
181    * @return A DTMAxisIterator, or null if the given axis isn't supported.
182    */
183   public DTMAxisIterator getAxisIterator(final int axis)
184   {
185 
186     DTMAxisIterator iterator = null;
187 
188     switch (axis)
189     {
190     case Axis.SELF :
191       iterator = new SingletonIterator();
192       break;
193     case Axis.CHILD :
194       iterator = new ChildrenIterator();
195       break;
196     case Axis.PARENT :
197       return (new ParentIterator());
198     case Axis.ANCESTOR :
199       return (new AncestorIterator());
200     case Axis.ANCESTORORSELF :
201       return ((new AncestorIterator()).includeSelf());
202     case Axis.ATTRIBUTE :
203       return (new AttributeIterator());
204     case Axis.DESCENDANT :
205       iterator = new DescendantIterator();
206       break;
207     case Axis.DESCENDANTORSELF :
208       iterator = (new DescendantIterator()).includeSelf();
209       break;
210     case Axis.FOLLOWING :
211       iterator = new FollowingIterator();
212       break;
213     case Axis.PRECEDING :
214       iterator = new PrecedingIterator();
215       break;
216     case Axis.FOLLOWINGSIBLING :
217       iterator = new FollowingSiblingIterator();
218       break;
219     case Axis.PRECEDINGSIBLING :
220       iterator = new PrecedingSiblingIterator();
221       break;
222     case Axis.NAMESPACE :
223       iterator = new NamespaceIterator();
224       break;
225     case Axis.ROOT :
226       iterator = new RootIterator();
227       break;
228     default :
229       throw new DTMException(XMLMessages.createXMLMessage(
230         XMLErrorResources.ER_ITERATOR_AXIS_NOT_IMPLEMENTED,
231         new Object[]{Axis.getNames(axis)}));
232         //"Error: iterator for axis '" + Axis.names[axis]
233                              //+ "' not implemented");
234     }
235 
236     return (iterator);
237   }
238 
239   /**
240    * Abstract superclass defining behaviors shared by all DTMDefault's
241    * internal implementations of DTMAxisIterator. Subclass this (and
242    * override, if necessary) to implement the specifics of an
243    * individual axis iterator.
244    *
245    * Currently there isn't a lot here
246    */
247   public abstract class InternalAxisIteratorBase extends DTMAxisIteratorBase
248   {
249 
250     // %REVIEW% We could opt to share _nodeType and setNodeType() as
251     // well, and simply ignore them in iterators which don't use them.
252     // But Scott's worried about the overhead involved in cloning
253     // these, and wants them to have as few fields as possible. Note
254     // that we can't create a TypedInternalAxisIteratorBase because
255     // those are often based on the untyped versions and Java doesn't
256     // support multiple inheritance. <sigh/>
257 
258     /**
259      * Current iteration location. Usually this is the last location
260      * returned (starting point for the next() search); for single-node
261      * iterators it may instead be initialized to point to that single node.
262      */
263     protected int _currentNode;
264 
265     /**
266      * Remembers the current node for the next call to gotoMark().
267      *
268      * %REVIEW% Should this save _position too?
269      */
270     public void setMark()
271     {
272       _markedNode = _currentNode;
273     }
274 
275     /**
276      * Restores the current node remembered by setMark().
277      *
278      * %REVEIW% Should this restore _position too?
279      */
280     public void gotoMark()
281     {
282       _currentNode = _markedNode;
283     }
284 
285   }  // end of InternalAxisIteratorBase
286 
287   /**
288    * Iterator that returns all immediate children of a given node
289    */
290   public final class ChildrenIterator extends InternalAxisIteratorBase
291   {
292 
293     /**
294      * Setting start to END should 'close' the iterator,
295      * i.e. subsequent call to next() should return END.
296      *
297      * If the iterator is not restartable, this has no effect.
298      * %REVIEW% Should it return/throw something in that case,
299      * or set current node to END, to indicate request-not-honored?
300      *
301      * @param node Sets the root of the iteration.
302      *
303      * @return A DTMAxisIterator set to the start of the iteration.
304      */
305     public DTMAxisIterator setStartNode(int node)
306     {
307 //%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
308       if (node == DTMDefaultBase.ROOTNODE)
309         node = getDocument();
310       if (_isRestartable)
311       {
312         _startNode = node;
313         _currentNode = (node == DTM.NULL) ? DTM.NULL
314                                           : _firstch(makeNodeIdentity(node));
315 
316         return resetPosition();
317       }
318 
319       return this;
320     }
321 
322     /**
323      * Get the next node in the iteration.
324      *
325      * @return The next node handle in the iteration, or END if no more
326      * are available.
327      */
328     public int next()
329     {
330       if (_currentNode != NULL) {
331         int node = _currentNode;
332         _currentNode = _nextsib(node);
333         return returnNode(makeNodeHandle(node));
334       }
335 
336       return END;
337     }
338   }  // end of ChildrenIterator
339 
340   /**
341    * Iterator that returns the parent of a given node. Note that
342    * this delivers only a single node; if you want all the ancestors,
343    * see AncestorIterator.
344    */
345   public final class ParentIterator extends InternalAxisIteratorBase
346   {
347 
348     /** The extended type ID that was requested. */
349     private int _nodeType = -1;
350 
351     /**
352      * Set start to END should 'close' the iterator,
353      * i.e. subsequent call to next() should return END.
354      *
355      * @param node Sets the root of the iteration.
356      *
357      * @return A DTMAxisIterator set to the start of the iteration.
358      */
359     public DTMAxisIterator setStartNode(int node)
360     {
361 //%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
362       if (node == DTMDefaultBase.ROOTNODE)
363         node = getDocument();
364       if (_isRestartable)
365       {
366         _startNode = node;
367         _currentNode = getParent(node);
368 
369         return resetPosition();
370       }
371 
372       return this;
373     }
374 
375     /**
376      * Set the node type of the parent that we're looking for.
377      * Note that this does _not_ mean "find the nearest ancestor of
378      * this type", but "yield the parent if it is of this type".
379      *
380      *
381      * @param type extended type ID.
382      *
383      * @return ParentIterator configured with the type filter set.
384      */
385     public DTMAxisIterator setNodeType(final int type)
386     {
387 
388       _nodeType = type;
389 
390       return this;
391     }
392 
393     /**
394      * Get the next node in the iteration. In this case, we return
395      * only the immediate parent, _if_ it matches the requested nodeType.
396      *
397      * @return The next node handle in the iteration, or END.
398      */
399     public int next()
400     {
401       int result = _currentNode;
402 
403       if (_nodeType >= DTM.NTYPES) {
404         if (_nodeType != getExpandedTypeID(_currentNode)) {
405           result = END;
406         }
407       } else if (_nodeType != NULL) {
408         if (_nodeType != getNodeType(_currentNode)) {
409           result = END;
410         }
411       }
412 
413       _currentNode = END;
414 
415       return returnNode(result);
416     }
417   }  // end of ParentIterator
418 
419   /**
420    * Iterator that returns children of a given type for a given node.
421    * The functionality chould be achieved by putting a filter on top
422    * of a basic child iterator, but a specialised iterator is used
423    * for efficiency (both speed and size of translet).
424    */
425   public final class TypedChildrenIterator extends InternalAxisIteratorBase
426   {
427 
428     /** The extended type ID that was requested. */
429     private final int _nodeType;
430 
431     /**
432      * Constructor TypedChildrenIterator
433      *
434      *
435      * @param nodeType The extended type ID being requested.
436      */
437     public TypedChildrenIterator(int nodeType)
438     {
439       _nodeType = nodeType;
440     }
441 
442     /**
443      * Set start to END should 'close' the iterator,
444      * i.e. subsequent call to next() should return END.
445      *
446      * @param node Sets the root of the iteration.
447      *
448      * @return A DTMAxisIterator set to the start of the iteration.
449      */
450     public DTMAxisIterator setStartNode(int node)
451     {
452 //%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
453       if (node == DTMDefaultBase.ROOTNODE)
454         node = getDocument();
455       if (_isRestartable)
456       {
457         _startNode = node;
458         _currentNode = (node == DTM.NULL)
459                                    ? DTM.NULL
460                                    : _firstch(makeNodeIdentity(_startNode));
461 
462         return resetPosition();
463       }
464 
465       return this;
466     }
467 
468     /**
469      * Get the next node in the iteration.
470      *
471      * @return The next node handle in the iteration, or END.
472      */
473     public int next()
474     {
475       int eType;
476       int node = _currentNode;
477 
478       int nodeType = _nodeType;
479 
480       if (nodeType >= DTM.NTYPES) {
481         while (node != DTM.NULL && _exptype(node) != nodeType) {
482           node = _nextsib(node);
483         }
484       } else {
485         while (node != DTM.NULL) {
486           eType = _exptype(node);
487           if (eType < DTM.NTYPES) {
488             if (eType == nodeType) {
489               break;
490             }
491           } else if (m_expandedNameTable.getType(eType) == nodeType) {
492             break;
493           }
494           node = _nextsib(node);
495         }
496       }
497 
498       if (node == DTM.NULL) {
499         _currentNode = DTM.NULL;
500         return DTM.NULL;
501       } else {
502         _currentNode = _nextsib(node);
503         return returnNode(makeNodeHandle(node));
504       }
505 
506     }
507   }  // end of TypedChildrenIterator
508 
509   /**
510    * Iterator that returns children within a given namespace for a
511    * given node. The functionality chould be achieved by putting a
512    * filter on top of a basic child iterator, but a specialised
513    * iterator is used for efficiency (both speed and size of translet).
514    */
515   public final class NamespaceChildrenIterator
516           extends InternalAxisIteratorBase
517   {
518 
519     /** The extended type ID being requested. */
520     private final int _nsType;
521 
522     /**
523      * Constructor NamespaceChildrenIterator
524      *
525      *
526      * @param type The extended type ID being requested.
527      */
528     public NamespaceChildrenIterator(final int type)
529     {
530       _nsType = type;
531     }
532 
533     /**
534      * Set start to END should 'close' the iterator,
535      * i.e. subsequent call to next() should return END.
536      *
537      * @param node Sets the root of the iteration.
538      *
539      * @return A DTMAxisIterator set to the start of the iteration.
540      */
541     public DTMAxisIterator setStartNode(int node)
542     {
543 //%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
544       if (node == DTMDefaultBase.ROOTNODE)
545         node = getDocument();
546       if (_isRestartable)
547       {
548         _startNode = node;
549         _currentNode = (node == DTM.NULL) ? DTM.NULL : NOTPROCESSED;
550 
551         return resetPosition();
552       }
553 
554       return this;
555     }
556 
557     /**
558      * Get the next node in the iteration.
559      *
560      * @return The next node handle in the iteration, or END.
561      */
562     public int next()
563     {
564       if (_currentNode != DTM.NULL) {
565         for (int node = (NOTPROCESSED == _currentNode)
566                                   ? _firstch(makeNodeIdentity(_startNode))
567                                   : _nextsib(_currentNode);
568              node != END;
569              node = _nextsib(node)) {
570           if (m_expandedNameTable.getNamespaceID(_exptype(node)) == _nsType) {
571             _currentNode = node;
572 
573             return returnNode(node);
574           }
575         }
576       }
577 
578       return END;
579     }
580   }  // end of NamespaceChildrenIterator
581 
582   /**
583    * Iterator that returns the namespace nodes as defined by the XPath data model
584    * for a given node.
585    */
586   public class NamespaceIterator
587           extends InternalAxisIteratorBase
588   {
589 
590     /**
591      * Constructor NamespaceAttributeIterator
592      */
593     public NamespaceIterator()
594     {
595 
596       super();
597     }
598 
599     /**
600      * Set start to END should 'close' the iterator,
601      * i.e. subsequent call to next() should return END.
602      *
603      * @param node Sets the root of the iteration.
604      *
605      * @return A DTMAxisIterator set to the start of the iteration.
606      */
607     public DTMAxisIterator setStartNode(int node)
608     {
609 //%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
610       if (node == DTMDefaultBase.ROOTNODE)
611         node = getDocument();
612       if (_isRestartable)
613       {
614         _startNode = node;
615         _currentNode = getFirstNamespaceNode(node, true);
616 
617         return resetPosition();
618       }
619 
620       return this;
621     }
622 
623     /**
624      * Get the next node in the iteration.
625      *
626      * @return The next node handle in the iteration, or END.
627      */
628     public int next()
629     {
630 
631       int node = _currentNode;
632 
633       if (DTM.NULL != node)
634         _currentNode = getNextNamespaceNode(_startNode, node, true);
635 
636       return returnNode(node);
637     }
638   }  // end of NamespaceIterator
639 
640   /**
641    * Iterator that returns the namespace nodes as defined by the XPath data model
642    * for a given node, filtered by extended type ID.
643    */
644   public class TypedNamespaceIterator extends NamespaceIterator
645   {
646 
647     /** The extended type ID that was requested. */
648     private final int _nodeType;
649 
650     /**
651      * Constructor TypedNamespaceIterator
652      *
653      *
654      * @param nodeType The extended type ID being requested.
655      */
656     public TypedNamespaceIterator(int nodeType)
657     {
658       super();
659       _nodeType = nodeType;
660     }
661 
662     /**
663      * Get the next node in the iteration.
664      *
665      * @return The next node handle in the iteration, or END.
666      */
667     public int next()
668     {
669         int node;
670 
671       for (node = _currentNode;
672            node != END;
673            node = getNextNamespaceNode(_startNode, node, true)) {
674         if (getExpandedTypeID(node) == _nodeType
675             || getNodeType(node) == _nodeType
676             || getNamespaceType(node) == _nodeType) {
677           _currentNode = node;
678 
679           return returnNode(node);
680         }
681       }
682 
683       return (_currentNode =END);
684     }
685   }  // end of TypedNamespaceIterator
686 
687   /**
688    * Iterator that returns the the root node as defined by the XPath data model
689    * for a given node.
690    */
691   public class RootIterator
692           extends InternalAxisIteratorBase
693   {
694 
695     /**
696      * Constructor RootIterator
697      */
698     public RootIterator()
699     {
700 
701       super();
702     }
703 
704     /**
705      * Set start to END should 'close' the iterator,
706      * i.e. subsequent call to next() should return END.
707      *
708      * @param node Sets the root of the iteration.
709      *
710      * @return A DTMAxisIterator set to the start of the iteration.
711      */
712     public DTMAxisIterator setStartNode(int node)
713     {
714 
715       if (_isRestartable)
716       {
717         _startNode = getDocumentRoot(node);
718         _currentNode = NULL;
719 
720         return resetPosition();
721       }
722 
723       return this;
724     }
725 
726     /**
727      * Get the next node in the iteration.
728      *
729      * @return The next node handle in the iteration, or END.
730      */
731     public int next()
732     {
733       if(_startNode == _currentNode)
734         return NULL;
735 
736       _currentNode = _startNode;
737 
738       return returnNode(_startNode);
739     }
740   }  // end of RootIterator
741 
742   /**
743    * Iterator that returns the namespace nodes as defined by the XPath data model
744    * for a given node, filtered by extended type ID.
745    */
746   public class TypedRootIterator extends RootIterator
747   {
748 
749     /** The extended type ID that was requested. */
750     private final int _nodeType;
751 
752     /**
753      * Constructor TypedRootIterator
754      *
755      * @param nodeType The extended type ID being requested.
756      */
757     public TypedRootIterator(int nodeType)
758     {
759       super();
760       _nodeType = nodeType;
761     }
762 
763     /**
764      * Get the next node in the iteration.
765      *
766      * @return The next node handle in the iteration, or END.
767      */
768     public int next()
769     {
770         if(_startNode == _currentNode)
771         return NULL;
772 
773       int nodeType = _nodeType;
774       int node = _startNode;
775       int expType = getExpandedTypeID(node);
776 
777       _currentNode = node;
778 
779       if (nodeType >= DTM.NTYPES) {
780         if (nodeType == expType) {
781           return returnNode(node);
782         }
783       } else {
784         if (expType < DTM.NTYPES) {
785           if (expType == nodeType) {
786             return returnNode(node);
787           }
788         } else {
789           if (m_expandedNameTable.getType(expType) == nodeType) {
790             return returnNode(node);
791           }
792         }
793       }
794 
795       return END;
796     }
797   }  // end of TypedRootIterator
798 
799   /**
800    * Iterator that returns attributes within a given namespace for a node.
801    */
802   public final class NamespaceAttributeIterator
803           extends InternalAxisIteratorBase
804   {
805 
806     /** The extended type ID being requested. */
807     private final int _nsType;
808 
809     /**
810      * Constructor NamespaceAttributeIterator
811      *
812      *
813      * @param nsType The extended type ID being requested.
814      */
815     public NamespaceAttributeIterator(int nsType)
816     {
817 
818       super();
819 
820       _nsType = nsType;
821     }
822 
823     /**
824      * Set start to END should 'close' the iterator,
825      * i.e. subsequent call to next() should return END.
826      *
827      * @param node Sets the root of the iteration.
828      *
829      * @return A DTMAxisIterator set to the start of the iteration.
830      */
831     public DTMAxisIterator setStartNode(int node)
832     {
833 //%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
834       if (node == DTMDefaultBase.ROOTNODE)
835         node = getDocument();
836       if (_isRestartable)
837       {
838         _startNode = node;
839         _currentNode = getFirstNamespaceNode(node, false);
840 
841         return resetPosition();
842       }
843 
844       return this;
845     }
846 
847     /**
848      * Get the next node in the iteration.
849      *
850      * @return The next node handle in the iteration, or END.
851      */
852     public int next()
853     {
854 
855       int node = _currentNode;
856 
857       if (DTM.NULL != node)
858         _currentNode = getNextNamespaceNode(_startNode, node, false);
859 
860       return returnNode(node);
861     }
862   }  // end of NamespaceAttributeIterator
863 
864   /**
865    * Iterator that returns all siblings of a given node.
866    */
867   public class FollowingSiblingIterator extends InternalAxisIteratorBase
868   {
869 
870     /**
871      * Set start to END should 'close' the iterator,
872      * i.e. subsequent call to next() should return END.
873      *
874      * @param node Sets the root of the iteration.
875      *
876      * @return A DTMAxisIterator set to the start of the iteration.
877      */
878     public DTMAxisIterator setStartNode(int node)
879     {
880 //%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
881       if (node == DTMDefaultBase.ROOTNODE)
882         node = getDocument();
883       if (_isRestartable)
884       {
885         _startNode = node;
886         _currentNode = makeNodeIdentity(node);
887 
888         return resetPosition();
889       }
890 
891       return this;
892     }
893 
894     /**
895      * Get the next node in the iteration.
896      *
897      * @return The next node handle in the iteration, or END.
898      */
899     public int next()
900     {
901       _currentNode = (_currentNode == DTM.NULL) ? DTM.NULL
902                                                 : _nextsib(_currentNode);
903       return returnNode(makeNodeHandle(_currentNode));
904     }
905   }  // end of FollowingSiblingIterator
906 
907   /**
908    * Iterator that returns all following siblings of a given node.
909    */
910   public final class TypedFollowingSiblingIterator
911           extends FollowingSiblingIterator
912   {
913 
914     /** The extended type ID that was requested. */
915     private final int _nodeType;
916 
917     /**
918      * Constructor TypedFollowingSiblingIterator
919      *
920      *
921      * @param type The extended type ID being requested.
922      */
923     public TypedFollowingSiblingIterator(int type)
924     {
925       _nodeType = type;
926     }
927 
928     /**
929      * Get the next node in the iteration.
930      *
931      * @return The next node handle in the iteration, or END.
932      */
933     public int next()
934     {
935       if (_currentNode == DTM.NULL) {
936         return DTM.NULL;
937       }
938 
939       int node = _currentNode;
940       int eType;
941       int nodeType = _nodeType;
942 
943       if (nodeType >= DTM.NTYPES) {
944         do {
945           node = _nextsib(node);
946         } while (node != DTM.NULL && _exptype(node) != nodeType);
947       } else {
948         while ((node = _nextsib(node)) != DTM.NULL) {
949           eType = _exptype(node);
950           if (eType < DTM.NTYPES) {
951             if (eType == nodeType) {
952               break;
953             }
954           } else if (m_expandedNameTable.getType(eType) == nodeType) {
955             break;
956           }
957         }
958       }
959 
960       _currentNode = node;
961 
962       return (_currentNode == DTM.NULL)
963                       ? DTM.NULL
964                       : returnNode(makeNodeHandle(_currentNode));
965     }
966   }  // end of TypedFollowingSiblingIterator
967 
968   /**
969    * Iterator that returns attribute nodes (of what nodes?)
970    */
971   public final class AttributeIterator extends InternalAxisIteratorBase
972   {
973 
974     // assumes caller will pass element nodes
975 
976     /**
977      * Set start to END should 'close' the iterator,
978      * i.e. subsequent call to next() should return END.
979      *
980      * @param node Sets the root of the iteration.
981      *
982      * @return A DTMAxisIterator set to the start of the iteration.
983      */
984     public DTMAxisIterator setStartNode(int node)
985     {
986 //%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
987       if (node == DTMDefaultBase.ROOTNODE)
988         node = getDocument();
989       if (_isRestartable)
990       {
991         _startNode = node;
992         _currentNode = getFirstAttributeIdentity(makeNodeIdentity(node));
993 
994         return resetPosition();
995       }
996 
997       return this;
998     }
999 
1000     /**
1001      * Get the next node in the iteration.
1002      *
1003      * @return The next node handle in the iteration, or END.
1004      */
1005     public int next()
1006     {
1007 
1008       final int node = _currentNode;
1009 
1010       if (node != NULL) {
1011         _currentNode = getNextAttributeIdentity(node);
1012         return returnNode(makeNodeHandle(node));
1013       }
1014 
1015       return NULL;
1016     }
1017   }  // end of AttributeIterator
1018 
1019   /**
1020    * Iterator that returns attribute nodes of a given type
1021    */
1022   public final class TypedAttributeIterator extends InternalAxisIteratorBase
1023   {
1024 
1025     /** The extended type ID that was requested. */
1026     private final int _nodeType;
1027 
1028     /**
1029      * Constructor TypedAttributeIterator
1030      *
1031      *
1032      * @param nodeType The extended type ID that is requested.
1033      */
1034     public TypedAttributeIterator(int nodeType)
1035     {
1036       _nodeType = nodeType;
1037     }
1038 
1039     // assumes caller will pass element nodes
1040 
1041     /**
1042      * Set start to END should 'close' the iterator,
1043      * i.e. subsequent call to next() should return END.
1044      *
1045      * @param node Sets the root of the iteration.
1046      *
1047      * @return A DTMAxisIterator set to the start of the iteration.
1048      */
1049     public DTMAxisIterator setStartNode(int node)
1050     {
1051       if (_isRestartable)
1052       {
1053         _startNode = node;
1054 
1055         _currentNode = getTypedAttribute(node, _nodeType);
1056 
1057         return resetPosition();
1058       }
1059 
1060       return this;
1061     }
1062 
1063     /**
1064      * Get the next node in the iteration.
1065      *
1066      * @return The next node handle in the iteration, or END.
1067      */
1068     public int next()
1069     {
1070 
1071       final int node = _currentNode;
1072 
1073       // singleton iterator, since there can only be one attribute of
1074       // a given type.
1075       _currentNode = NULL;
1076 
1077       return returnNode(node);
1078     }
1079   }  // end of TypedAttributeIterator
1080 
1081   /**
1082    * Iterator that returns preceding siblings of a given node
1083    */
1084   public class PrecedingSiblingIterator extends InternalAxisIteratorBase
1085   {
1086 
1087     /**
1088      * The node identity of _startNode for this iterator
1089      */
1090     protected int _startNodeID;
1091 
1092     /**
1093      * True if this iterator has a reversed axis.
1094      *
1095      * @return true.
1096      */
1097     public boolean isReverse()
1098     {
1099       return true;
1100     }
1101 
1102     /**
1103      * Set start to END should 'close' the iterator,
1104      * i.e. subsequent call to next() should return END.
1105      *
1106      * @param node Sets the root of the iteration.
1107      *
1108      * @return A DTMAxisIterator set to the start of the iteration.
1109      */
1110     public DTMAxisIterator setStartNode(int node)
1111     {
1112 //%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
1113       if (node == DTMDefaultBase.ROOTNODE)
1114         node = getDocument();
1115       if (_isRestartable)
1116       {
1117         _startNode = node;
1118         node = _startNodeID = makeNodeIdentity(node);
1119 
1120         if(node == NULL)
1121         {
1122           _currentNode = node;
1123           return resetPosition();
1124         }
1125 
1126         int type = m_expandedNameTable.getType(_exptype(node));
1127         if(ExpandedNameTable.ATTRIBUTE == type
1128            || ExpandedNameTable.NAMESPACE == type )
1129         {
1130           _currentNode = node;
1131         }
1132         else
1133         {
1134           // Be careful to handle the Document node properly
1135           _currentNode = _parent(node);
1136           if(NULL!=_currentNode)
1137             _currentNode = _firstch(_currentNode);
1138           else
1139             _currentNode = node;
1140         }
1141 
1142         return resetPosition();
1143       }
1144 
1145       return this;
1146     }
1147 
1148     /**
1149      * Get the next node in the iteration.
1150      *
1151      * @return The next node handle in the iteration, or END.
1152      */
1153     public int next()
1154     {
1155 
1156       if (_currentNode == _startNodeID || _currentNode == DTM.NULL)
1157       {
1158         return NULL;
1159       }
1160       else
1161       {
1162         final int node = _currentNode;
1163         _currentNode = _nextsib(node);
1164 
1165         return returnNode(makeNodeHandle(node));
1166       }
1167     }
1168   }  // end of PrecedingSiblingIterator
1169 
1170   /**
1171    * Iterator that returns preceding siblings of a given type for
1172    * a given node
1173    */
1174   public final class TypedPrecedingSiblingIterator
1175           extends PrecedingSiblingIterator
1176   {
1177 
1178     /** The extended type ID that was requested. */
1179     private final int _nodeType;
1180 
1181     /**
1182      * Constructor TypedPrecedingSiblingIterator
1183      *
1184      *
1185      * @param type The extended type ID being requested.
1186      */
1187     public TypedPrecedingSiblingIterator(int type)
1188     {
1189       _nodeType = type;
1190     }
1191 
1192     /**
1193      * Get the next node in the iteration.
1194      *
1195      * @return The next node handle in the iteration, or END.
1196      */
1197     public int next()
1198     {
1199       int node = _currentNode;
1200       int expType;
1201 
1202       int nodeType = _nodeType;
1203       int startID = _startNodeID;
1204 
1205       if (nodeType >= DTM.NTYPES) {
1206         while (node != NULL && node != startID && _exptype(node) != nodeType) {
1207           node = _nextsib(node);
1208         }
1209       } else {
1210         while (node != NULL && node != startID) {
1211           expType = _exptype(node);
1212           if (expType < DTM.NTYPES) {
1213             if (expType == nodeType) {
1214               break;
1215             }
1216           } else {
1217             if (m_expandedNameTable.getType(expType) == nodeType) {
1218               break;
1219             }
1220           }
1221           node = _nextsib(node);
1222         }
1223       }
1224 
1225       if (node == DTM.NULL || node == _startNodeID) {
1226         _currentNode = NULL;
1227         return NULL;
1228       } else {
1229         _currentNode = _nextsib(node);
1230         return returnNode(makeNodeHandle(node));
1231       }
1232     }
1233   }  // end of TypedPrecedingSiblingIterator
1234 
1235   /**
1236    * Iterator that returns preceding nodes of a given node.
1237    * This includes the node set {root+1, start-1}, but excludes
1238    * all ancestors, attributes, and namespace nodes.
1239    */
1240   public class PrecedingIterator extends InternalAxisIteratorBase
1241   {
1242 
1243     /** The max ancestors, but it can grow... */
1244     private final int _maxAncestors = 8;
1245 
1246     /**
1247      * The stack of start node + ancestors up to the root of the tree,
1248      *  which we must avoid.
1249      */
1250     protected int[] _stack = new int[_maxAncestors];
1251 
1252     /** (not sure yet... -sb) */
1253     protected int _sp, _oldsp;
1254 
1255     protected int _markedsp, _markedNode, _markedDescendant;
1256 
1257     /* _currentNode precedes candidates.  This is the identity, not the handle! */
1258 
1259     /**
1260      * True if this iterator has a reversed axis.
1261      *
1262      * @return true since this iterator is a reversed axis.
1263      */
1264     public boolean isReverse()
1265     {
1266       return true;
1267     }
1268 
1269     /**
1270      * Returns a deep copy of this iterator.   The cloned iterator is not reset.
1271      *
1272      * @return a deep copy of this iterator.
1273      */
1274     public DTMAxisIterator cloneIterator()
1275     {
1276       _isRestartable = false;
1277 
1278       try
1279       {
1280         final PrecedingIterator clone = (PrecedingIterator) super.clone();
1281         final int[] stackCopy = new int[_stack.length];
1282         System.arraycopy(_stack, 0, stackCopy, 0, _stack.length);
1283 
1284         clone._stack = stackCopy;
1285 
1286         // return clone.reset();
1287         return clone;
1288       }
1289       catch (CloneNotSupportedException e)
1290       {
1291         throw new DTMException(XMLMessages.createXMLMessage(XMLErrorResources.ER_ITERATOR_CLONE_NOT_SUPPORTED, null)); //"Iterator clone not supported.");
1292       }
1293     }
1294 
1295     /**
1296      * Set start to END should 'close' the iterator,
1297      * i.e. subsequent call to next() should return END.
1298      *
1299      * @param node Sets the root of the iteration.
1300      *
1301      * @return A DTMAxisIterator set to the start of the iteration.
1302      */
1303     public DTMAxisIterator setStartNode(int node)
1304     {
1305 //%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
1306       if (node == DTMDefaultBase.ROOTNODE)
1307         node = getDocument();
1308       if (_isRestartable)
1309       {
1310         node = makeNodeIdentity(node);
1311 
1312         // iterator is not a clone
1313         int parent, index;
1314 
1315        if (_type(node) == DTM.ATTRIBUTE_NODE)
1316         node = _parent(node);
1317 
1318         _startNode = node;
1319         _stack[index = 0] = node;
1320 
1321 
1322 
1323                 parent=node;
1324                 while ((parent = _parent(parent)) != NULL)
1325                 {
1326                         if (++index == _stack.length)
1327                         {
1328                                 final int[] stack = new int[index + 4];
1329                                 System.arraycopy(_stack, 0, stack, 0, index);
1330                                 _stack = stack;
1331                         }
1332                         _stack[index] = parent;
1333         }
1334         if(index>0)
1335                 --index; // Pop actual root node (if not start) back off the stack
1336 
1337         _currentNode=_stack[index]; // Last parent before root node
1338 
1339         _oldsp = _sp = index;
1340 
1341         return resetPosition();
1342       }
1343 
1344       return this;
1345     }
1346 
1347     /**
1348      * Get the next node in the iteration.
1349      *
1350      * @return The next node handle in the iteration, or END.
1351      */
1352     public int next()
1353     {
1354         // Bugzilla 8324: We were forgetting to skip Attrs and NS nodes.
1355         // Also recoded the loop controls for clarity and to flatten out
1356         // the tail-recursion.
1357                 for(++_currentNode;
1358                         _sp>=0;
1359                         ++_currentNode)
1360                 {
1361                         if(_currentNode < _stack[_sp])
1362                         {
1363                                 if(_type(_currentNode) != ATTRIBUTE_NODE &&
1364                                         _type(_currentNode) != NAMESPACE_NODE)
1365                                         return returnNode(makeNodeHandle(_currentNode));
1366                         }
1367                         else
1368                                 --_sp;
1369                 }
1370                 return NULL;
1371     }
1372 
1373     // redefine DTMAxisIteratorBase's reset
1374 
1375     /**
1376      * Resets the iterator to the last start node.
1377      *
1378      * @return A DTMAxisIterator, which may or may not be the same as this
1379      *         iterator.
1380      */
1381     public DTMAxisIterator reset()
1382     {
1383 
1384       _sp = _oldsp;
1385 
1386       return resetPosition();
1387     }
1388 
1389     public void setMark() {
1390         _markedsp = _sp;
1391         _markedNode = _currentNode;
1392         _markedDescendant = _stack[0];
1393     }
1394 
1395     public void gotoMark() {
1396         _sp = _markedsp;
1397         _currentNode = _markedNode;
1398     }
1399   }  // end of PrecedingIterator
1400 
1401   /**
1402    * Iterator that returns preceding nodes of agiven type for a
1403    * given node. This includes the node set {root+1, start-1}, but
1404    * excludes all ancestors.
1405    */
1406   public final class TypedPrecedingIterator extends PrecedingIterator
1407   {
1408 
1409     /** The extended type ID that was requested. */
1410     private final int _nodeType;
1411 
1412     /**
1413      * Constructor TypedPrecedingIterator
1414      *
1415      *
1416      * @param type The extended type ID being requested.
1417      */
1418     public TypedPrecedingIterator(int type)
1419     {
1420       _nodeType = type;
1421     }
1422 
1423     /**
1424      * Get the next node in the iteration.
1425      *
1426      * @return The next node handle in the iteration, or END.
1427      */
1428     public int next()
1429     {
1430       int node = _currentNode;
1431       int nodeType = _nodeType;
1432 
1433       if (nodeType >= DTM.NTYPES) {
1434         while (true) {
1435           node = node + 1;
1436 
1437           if (_sp < 0) {
1438             node = NULL;
1439             break;
1440           } else if (node >= _stack[_sp]) {
1441             if (--_sp < 0) {
1442               node = NULL;
1443               break;
1444             }
1445           } else if (_exptype(node) == nodeType) {
1446             break;
1447           }
1448         }
1449       } else {
1450         int expType;
1451 
1452         while (true) {
1453           node = node + 1;
1454 
1455           if (_sp < 0) {
1456             node = NULL;
1457             break;
1458           } else if (node >= _stack[_sp]) {
1459             if (--_sp < 0) {
1460               node = NULL;
1461               break;
1462             }
1463           } else {
1464             expType = _exptype(node);
1465             if (expType < DTM.NTYPES) {
1466               if (expType == nodeType) {
1467                 break;
1468               }
1469             } else {
1470               if (m_expandedNameTable.getType(expType) == nodeType) {
1471                 break;
1472               }
1473             }
1474           }
1475         }
1476       }
1477 
1478       _currentNode = node;
1479 
1480       return (node == NULL) ? NULL : returnNode(makeNodeHandle(node));
1481     }
1482   }  // end of TypedPrecedingIterator
1483 
1484   /**
1485    * Iterator that returns following nodes of for a given node.
1486    */
1487   public class FollowingIterator extends InternalAxisIteratorBase
1488   {
1489     DTMAxisTraverser m_traverser; // easier for now
1490 
1491     public FollowingIterator()
1492     {
1493       m_traverser = getAxisTraverser(Axis.FOLLOWING);
1494     }
1495 
1496     /**
1497      * Set start to END should 'close' the iterator,
1498      * i.e. subsequent call to next() should return END.
1499      *
1500      * @param node Sets the root of the iteration.
1501      *
1502      * @return A DTMAxisIterator set to the start of the iteration.
1503      */
1504     public DTMAxisIterator setStartNode(int node)
1505     {
1506 //%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
1507       if (node == DTMDefaultBase.ROOTNODE)
1508         node = getDocument();
1509       if (_isRestartable)
1510       {
1511         _startNode = node;
1512 
1513         // ?? -sb
1514         // find rightmost descendant (or self)
1515         // int current;
1516         // while ((node = getLastChild(current = node)) != NULL){}
1517         // _currentNode = current;
1518         _currentNode = m_traverser.first(node);
1519 
1520         // _currentNode precedes possible following(node) nodes
1521         return resetPosition();
1522       }
1523 
1524       return this;
1525     }
1526 
1527     /**
1528      * Get the next node in the iteration.
1529      *
1530      * @return The next node handle in the iteration, or END.
1531      */
1532     public int next()
1533     {
1534 
1535       int node = _currentNode;
1536 
1537       _currentNode = m_traverser.next(_startNode, _currentNode);
1538 
1539       return returnNode(node);
1540     }
1541   }  // end of FollowingIterator
1542 
1543   /**
1544    * Iterator that returns following nodes of a given type for a given node.
1545    */
1546   public final class TypedFollowingIterator extends FollowingIterator
1547   {
1548 
1549     /** The extended type ID that was requested. */
1550     private final int _nodeType;
1551 
1552     /**
1553      * Constructor TypedFollowingIterator
1554      *
1555      *
1556      * @param type The extended type ID being requested.
1557      */
1558     public TypedFollowingIterator(int type)
1559     {
1560       _nodeType = type;
1561     }
1562 
1563     /**
1564      * Get the next node in the iteration.
1565      *
1566      * @return The next node handle in the iteration, or END.
1567      */
1568     public int next()
1569     {
1570 
1571       int node;
1572 
1573       do{
1574        node = _currentNode;
1575 
1576       _currentNode = m_traverser.next(_startNode, _currentNode);
1577 
1578       }
1579       while (node != DTM.NULL
1580              && (getExpandedTypeID(node) != _nodeType && getNodeType(node) != _nodeType));
1581 
1582       return (node == DTM.NULL ? DTM.NULL :returnNode(node));
1583     }
1584   }  // end of TypedFollowingIterator
1585 
1586   /**
1587    * Iterator that returns the ancestors of a given node in document
1588    * order.  (NOTE!  This was changed from the XSLTC code!)
1589    */
1590   public class AncestorIterator extends InternalAxisIteratorBase
1591   {
1592     com.sun.org.apache.xml.internal.utils.NodeVector m_ancestors =
1593          new com.sun.org.apache.xml.internal.utils.NodeVector();
1594 
1595     int m_ancestorsPos;
1596 
1597     int m_markedPos;
1598 
1599     /** The real start node for this axes, since _startNode will be adjusted. */
1600     int m_realStartNode;
1601 
1602     /**
1603      * Get start to END should 'close' the iterator,
1604      * i.e. subsequent call to next() should return END.
1605      *
1606      * @return The root node of the iteration.
1607      */
1608     public int getStartNode()
1609     {
1610       return m_realStartNode;
1611     }
1612 
1613     /**
1614      * True if this iterator has a reversed axis.
1615      *
1616      * @return true since this iterator is a reversed axis.
1617      */
1618     public final boolean isReverse()
1619     {
1620       return true;
1621     }
1622 
1623     /**
1624      * Returns a deep copy of this iterator.  The cloned iterator is not reset.
1625      *
1626      * @return a deep copy of this iterator.
1627      */
1628     public DTMAxisIterator cloneIterator()
1629     {
1630       _isRestartable = false;  // must set to false for any clone
1631 
1632       try
1633       {
1634         final AncestorIterator clone = (AncestorIterator) super.clone();
1635 
1636         clone._startNode = _startNode;
1637 
1638         // return clone.reset();
1639         return clone;
1640       }
1641       catch (CloneNotSupportedException e)
1642       {
1643         throw new DTMException(XMLMessages.createXMLMessage(XMLErrorResources.ER_ITERATOR_CLONE_NOT_SUPPORTED, null)); //"Iterator clone not supported.");
1644       }
1645     }
1646 
1647     /**
1648      * Set start to END should 'close' the iterator,
1649      * i.e. subsequent call to next() should return END.
1650      *
1651      * @param node Sets the root of the iteration.
1652      *
1653      * @return A DTMAxisIterator set to the start of the iteration.
1654      */
1655     public DTMAxisIterator setStartNode(int node)
1656     {
1657 //%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
1658       if (node == DTMDefaultBase.ROOTNODE)
1659         node = getDocument();
1660       m_realStartNode = node;
1661 
1662       if (_isRestartable)
1663       {
1664         int nodeID = makeNodeIdentity(node);
1665 
1666         if (!_includeSelf && node != DTM.NULL) {
1667           nodeID = _parent(nodeID);
1668           node = makeNodeHandle(nodeID);
1669         }
1670 
1671         _startNode = node;
1672 
1673         while (nodeID != END) {
1674           m_ancestors.addElement(node);
1675           nodeID = _parent(nodeID);
1676           node = makeNodeHandle(nodeID);
1677         }
1678         m_ancestorsPos = m_ancestors.size()-1;
1679 
1680         _currentNode = (m_ancestorsPos>=0)
1681                                ? m_ancestors.elementAt(m_ancestorsPos)
1682                                : DTM.NULL;
1683 
1684         return resetPosition();
1685       }
1686 
1687       return this;
1688     }
1689 
1690     /**
1691      * Resets the iterator to the last start node.
1692      *
1693      * @return A DTMAxisIterator, which may or may not be the same as this
1694      *         iterator.
1695      */
1696     public DTMAxisIterator reset()
1697     {
1698 
1699       m_ancestorsPos = m_ancestors.size()-1;
1700 
1701       _currentNode = (m_ancestorsPos>=0) ? m_ancestors.elementAt(m_ancestorsPos)
1702                                          : DTM.NULL;
1703 
1704       return resetPosition();
1705     }
1706 
1707     /**
1708      * Get the next node in the iteration.
1709      *
1710      * @return The next node handle in the iteration, or END.
1711      */
1712     public int next()
1713     {
1714 
1715       int next = _currentNode;
1716 
1717       int pos = --m_ancestorsPos;
1718 
1719       _currentNode = (pos >= 0) ? m_ancestors.elementAt(m_ancestorsPos)
1720                                 : DTM.NULL;
1721 
1722       return returnNode(next);
1723     }
1724 
1725     public void setMark() {
1726         m_markedPos = m_ancestorsPos;
1727     }
1728 
1729     public void gotoMark() {
1730         m_ancestorsPos = m_markedPos;
1731         _currentNode = m_ancestorsPos>=0 ? m_ancestors.elementAt(m_ancestorsPos)
1732                                          : DTM.NULL;
1733     }
1734   }  // end of AncestorIterator
1735 
1736   /**
1737    * Typed iterator that returns the ancestors of a given node.
1738    */
1739   public final class TypedAncestorIterator extends AncestorIterator
1740   {
1741 
1742     /** The extended type ID that was requested. */
1743     private final int _nodeType;
1744 
1745     /**
1746      * Constructor TypedAncestorIterator
1747      *
1748      *
1749      * @param type The extended type ID being requested.
1750      */
1751     public TypedAncestorIterator(int type)
1752     {
1753       _nodeType = type;
1754     }
1755 
1756     /**
1757      * Set start to END should 'close' the iterator,
1758      * i.e. subsequent call to next() should return END.
1759      *
1760      * @param node Sets the root of the iteration.
1761      *
1762      * @return A DTMAxisIterator set to the start of the iteration.
1763      */
1764     public DTMAxisIterator setStartNode(int node)
1765     {
1766 //%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
1767       if (node == DTMDefaultBase.ROOTNODE)
1768         node = getDocument();
1769       m_realStartNode = node;
1770 
1771       if (_isRestartable)
1772       {
1773         int nodeID = makeNodeIdentity(node);
1774         int nodeType = _nodeType;
1775 
1776         if (!_includeSelf && node != DTM.NULL) {
1777           nodeID = _parent(nodeID);
1778         }
1779 
1780         _startNode = node;
1781 
1782         if (nodeType >= DTM.NTYPES) {
1783           while (nodeID != END) {
1784             int eType = _exptype(nodeID);
1785 
1786             if (eType == nodeType) {
1787               m_ancestors.addElement(makeNodeHandle(nodeID));
1788             }
1789             nodeID = _parent(nodeID);
1790           }
1791         } else {
1792           while (nodeID != END) {
1793             int eType = _exptype(nodeID);
1794 
1795             if ((eType >= DTM.NTYPES
1796                     && m_expandedNameTable.getType(eType) == nodeType)
1797                 || (eType < DTM.NTYPES && eType == nodeType)) {
1798               m_ancestors.addElement(makeNodeHandle(nodeID));
1799             }
1800             nodeID = _parent(nodeID);
1801           }
1802         }
1803         m_ancestorsPos = m_ancestors.size()-1;
1804 
1805         _currentNode = (m_ancestorsPos>=0)
1806                                ? m_ancestors.elementAt(m_ancestorsPos)
1807                                : DTM.NULL;
1808 
1809         return resetPosition();
1810       }
1811 
1812       return this;
1813     }
1814   }  // end of TypedAncestorIterator
1815 
1816   /**
1817    * Iterator that returns the descendants of a given node.
1818    */
1819   public class DescendantIterator extends InternalAxisIteratorBase
1820   {
1821 
1822     /**
1823      * Set start to END should 'close' the iterator,
1824      * i.e. subsequent call to next() should return END.
1825      *
1826      * @param node Sets the root of the iteration.
1827      *
1828      * @return A DTMAxisIterator set to the start of the iteration.
1829      */
1830     public DTMAxisIterator setStartNode(int node)
1831     {
1832 //%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
1833       if (node == DTMDefaultBase.ROOTNODE)
1834         node = getDocument();
1835       if (_isRestartable)
1836       {
1837         node = makeNodeIdentity(node);
1838         _startNode = node;
1839 
1840         if (_includeSelf)
1841           node--;
1842 
1843         _currentNode = node;
1844 
1845         return resetPosition();
1846       }
1847 
1848       return this;
1849     }
1850 
1851     /**
1852      * Tell if this node identity is a descendant.  Assumes that
1853      * the node info for the element has already been obtained.
1854      *
1855      * This one-sided test works only if the parent has been
1856      * previously tested and is known to be a descendent. It fails if
1857      * the parent is the _startNode's next sibling, or indeed any node
1858      * that follows _startNode in document order.  That may suffice
1859      * for this iterator, but it's not really an isDescendent() test.
1860      * %REVIEW% rename?
1861      *
1862      * @param identity The index number of the node in question.
1863      * @return true if the index is a descendant of _startNode.
1864      */
1865     protected boolean isDescendant(int identity)
1866     {
1867       return (_parent(identity) >= _startNode) || (_startNode == identity);
1868     }
1869 
1870     /**
1871      * Get the next node in the iteration.
1872      *
1873      * @return The next node handle in the iteration, or END.
1874      */
1875     public int next()
1876     {
1877       if (_startNode == NULL) {
1878         return NULL;
1879       }
1880 
1881       if (_includeSelf && (_currentNode + 1) == _startNode)
1882           return returnNode(makeNodeHandle(++_currentNode)); // | m_dtmIdent);
1883 
1884       int node = _currentNode;
1885       int type;
1886 
1887       do {
1888         node++;
1889         type = _type(node);
1890 
1891         if (NULL == type ||!isDescendant(node)) {
1892           _currentNode = NULL;
1893           return END;
1894         }
1895       } while(ATTRIBUTE_NODE == type || TEXT_NODE == type
1896                  || NAMESPACE_NODE == type);
1897 
1898       _currentNode = node;
1899       return returnNode(makeNodeHandle(node));  // make handle.
1900     }
1901 
1902     /**
1903      * Reset.
1904      *
1905      */
1906   public DTMAxisIterator reset()
1907   {
1908 
1909     final boolean temp = _isRestartable;
1910 
1911     _isRestartable = true;
1912 
1913     setStartNode(makeNodeHandle(_startNode));
1914 
1915     _isRestartable = temp;
1916 
1917     return this;
1918   }
1919 
1920   }  // end of DescendantIterator
1921 
1922   /**
1923    * Typed iterator that returns the descendants of a given node.
1924    */
1925   public final class TypedDescendantIterator extends DescendantIterator
1926   {
1927 
1928     /** The extended type ID that was requested. */
1929     private final int _nodeType;
1930 
1931     /**
1932      * Constructor TypedDescendantIterator
1933      *
1934      *
1935      * @param nodeType Extended type ID being requested.
1936      */
1937     public TypedDescendantIterator(int nodeType)
1938     {
1939       _nodeType = nodeType;
1940     }
1941 
1942     /**
1943      * Get the next node in the iteration.
1944      *
1945      * @return The next node handle in the iteration, or END.
1946      */
1947     public int next()
1948     {
1949       int node;
1950       int type;
1951 
1952       if (_startNode == NULL) {
1953         return NULL;
1954       }
1955 
1956       node = _currentNode;
1957 
1958       do
1959       {
1960         node++;
1961         type = _type(node);
1962 
1963         if (NULL == type ||!isDescendant(node)) {
1964           _currentNode = NULL;
1965           return END;
1966         }
1967       }
1968       while (type != _nodeType && _exptype(node) != _nodeType);
1969 
1970       _currentNode = node;
1971       return returnNode(makeNodeHandle(node));
1972     }
1973   }  // end of TypedDescendantIterator
1974 
1975   /**
1976    * Iterator that returns the descendants of a given node.
1977    * I'm not exactly clear about this one... -sb
1978    */
1979   public class NthDescendantIterator extends DescendantIterator
1980   {
1981 
1982     /** The current nth position. */
1983     int _pos;
1984 
1985     /**
1986      * Constructor NthDescendantIterator
1987      *
1988      *
1989      * @param pos The nth position being requested.
1990      */
1991     public NthDescendantIterator(int pos)
1992     {
1993       _pos = pos;
1994     }
1995 
1996     /**
1997      * Get the next node in the iteration.
1998      *
1999      * @return The next node handle in the iteration, or END.
2000      */
2001     public int next()
2002     {
2003 
2004       // I'm not exactly clear yet what this is doing... -sb
2005       int node;
2006 
2007       while ((node = super.next()) != END)
2008       {
2009         node = makeNodeIdentity(node);
2010 
2011         int parent = _parent(node);
2012         int child = _firstch(parent);
2013         int pos = 0;
2014 
2015         do
2016         {
2017           int type = _type(child);
2018 
2019           if (ELEMENT_NODE == type)
2020             pos++;
2021         }
2022         while ((pos < _pos) && (child = _nextsib(child)) != END);
2023 
2024         if (node == child)
2025           return node;
2026       }
2027 
2028       return (END);
2029     }
2030   }  // end of NthDescendantIterator
2031 
2032   /**
2033    * Class SingletonIterator.
2034    */
2035   public class SingletonIterator extends InternalAxisIteratorBase
2036   {
2037 
2038     /** (not sure yet what this is.  -sb)  (sc & sb remove final to compile in JDK 1.1.8) */
2039     private boolean _isConstant;
2040 
2041     /**
2042      * Constructor SingletonIterator
2043      *
2044      */
2045     public SingletonIterator()
2046     {
2047       this(Integer.MIN_VALUE, false);
2048     }
2049 
2050     /**
2051      * Constructor SingletonIterator
2052      *
2053      *
2054      * @param node The node handle to return.
2055      */
2056     public SingletonIterator(int node)
2057     {
2058       this(node, false);
2059     }
2060 
2061     /**
2062      * Constructor SingletonIterator
2063      *
2064      *
2065      * @param node the node handle to return.
2066      * @param constant (Not sure what this is yet.  -sb)
2067      */
2068     public SingletonIterator(int node, boolean constant)
2069     {
2070       _currentNode = _startNode = node;
2071       _isConstant = constant;
2072     }
2073 
2074     /**
2075      * Set start to END should 'close' the iterator,
2076      * i.e. subsequent call to next() should return END.
2077      *
2078      * @param node Sets the root of the iteration.
2079      *
2080      * @return A DTMAxisIterator set to the start of the iteration.
2081      */
2082     public DTMAxisIterator setStartNode(int node)
2083     {
2084 //%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
2085       if (node == DTMDefaultBase.ROOTNODE)
2086         node = getDocument();
2087       if (_isConstant)
2088       {
2089         _currentNode = _startNode;
2090 
2091         return resetPosition();
2092       }
2093       else if (_isRestartable)
2094       {
2095           _currentNode = _startNode = node;
2096 
2097         return resetPosition();
2098       }
2099 
2100       return this;
2101     }
2102 
2103     /**
2104      * Resets the iterator to the last start node.
2105      *
2106      * @return A DTMAxisIterator, which may or may not be the same as this
2107      *         iterator.
2108      */
2109     public DTMAxisIterator reset()
2110     {
2111 
2112       if (_isConstant)
2113       {
2114         _currentNode = _startNode;
2115 
2116         return resetPosition();
2117       }
2118       else
2119       {
2120         final boolean temp = _isRestartable;
2121 
2122         _isRestartable = true;
2123 
2124         setStartNode(_startNode);
2125 
2126         _isRestartable = temp;
2127       }
2128 
2129       return this;
2130     }
2131 
2132     /**
2133      * Get the next node in the iteration.
2134      *
2135      * @return The next node handle in the iteration, or END.
2136      */
2137     public int next()
2138     {
2139 
2140       final int result = _currentNode;
2141 
2142       _currentNode = END;
2143 
2144       return returnNode(result);
2145     }
2146   }  // end of SingletonIterator
2147 
2148   /**
2149    * Iterator that returns a given node only if it is of a given type.
2150    */
2151   public final class TypedSingletonIterator extends SingletonIterator
2152   {
2153 
2154     /** The extended type ID that was requested. */
2155     private final int _nodeType;
2156 
2157     /**
2158      * Constructor TypedSingletonIterator
2159      *
2160      *
2161      * @param nodeType The extended type ID being requested.
2162      */
2163     public TypedSingletonIterator(int nodeType)
2164     {
2165       _nodeType = nodeType;
2166     }
2167 
2168     /**
2169      * Get the next node in the iteration.
2170      *
2171      * @return The next node handle in the iteration, or END.
2172      */
2173     public int next()
2174     {
2175 
2176       //final int result = super.next();
2177       final int result = _currentNode;
2178       int nodeType = _nodeType;
2179 
2180       _currentNode = END;
2181 
2182       if (nodeType >= DTM.NTYPES) {
2183         if (getExpandedTypeID(result) == nodeType) {
2184           return returnNode(result);
2185         }
2186       } else {
2187         if (getNodeType(result) == nodeType) {
2188           return returnNode(result);
2189         }
2190       }
2191 
2192       return NULL;
2193     }
2194   }  // end of TypedSingletonIterator
2195 }