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