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