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