Home | History | Annotate | Download | only in ref
      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    */
     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