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 */
21package org.apache.xml.dtm.ref;
22
23import org.apache.xml.dtm.*;
24
25import javax.xml.transform.Source;
26
27import org.apache.xml.utils.XMLStringFactory;
28
29import org.apache.xml.res.XMLErrorResources;
30import org.apache.xml.res.XMLMessages;
31
32/**
33 * This class implements the traversers for DTMDefaultBase.
34 */
35public 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   */
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   */
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   */
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   */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
1378    public DTMAxisIterator reset()
1379    {
1380
1381      _sp = _oldsp;
1382
1383      return resetPosition();
1384    }
1385
1386    public void setMark() {
1387        _markedsp = _sp;
1388        _markedNode = _currentNode;
1389        _markedDescendant = _stack[0];
1390    }
1391
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     */
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     */
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
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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
1722    public void setMark() {
1723        m_markedPos = m_ancestorsPos;
1724    }
1725
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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