• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements. See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership. The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the  "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 /*
19  * $Id: DTMDefaultBaseTraversers.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  * PLEASE NOTE that the public interface for all traversers should be
36  * in terms of DTM Node Handles... but they may use the internal node
37  * identity indices within their logic, for efficiency's sake. Be very
38  * careful to avoid confusing these when maintaining this code.
39  * */
40 public abstract class DTMDefaultBaseTraversers extends DTMDefaultBase
41 {
42 
43   /**
44    * Construct a DTMDefaultBaseTraversers object from a DOM node.
45    *
46    * @param mgr The DTMManager who owns this DTM.
47    * @param source The object that is used to specify the construction source.
48    * @param dtmIdentity The DTM identity ID for this DTM.
49    * @param whiteSpaceFilter The white space filter for this DTM, which may
50    *                         be null.
51    * @param xstringfactory The factory to use for creating XMLStrings.
52    * @param doIndexing true if the caller considers it worth it to use
53    *                   indexing schemes.
54    */
DTMDefaultBaseTraversers(DTMManager mgr, Source source, int dtmIdentity, DTMWSFilter whiteSpaceFilter, XMLStringFactory xstringfactory, boolean doIndexing)55   public DTMDefaultBaseTraversers(DTMManager mgr, Source source,
56                                   int dtmIdentity,
57                                   DTMWSFilter whiteSpaceFilter,
58                                   XMLStringFactory xstringfactory,
59                                   boolean doIndexing)
60   {
61     super(mgr, source, dtmIdentity, whiteSpaceFilter, xstringfactory,
62           doIndexing);
63   }
64 
65   /**
66    * Construct a DTMDefaultBaseTraversers object from a DOM node.
67    *
68    * @param mgr The DTMManager who owns this DTM.
69    * @param source The object that is used to specify the construction source.
70    * @param dtmIdentity The DTM identity ID for this DTM.
71    * @param whiteSpaceFilter The white space filter for this DTM, which may
72    *                         be null.
73    * @param xstringfactory The factory to use for creating XMLStrings.
74    * @param doIndexing true if the caller considers it worth it to use
75    *                   indexing schemes.
76    * @param blocksize The block size of the DTM.
77    * @param usePrevsib true if we want to build the previous sibling node array.
78    * @param newNameTable true if we want to use a new ExpandedNameTable for this DTM.
79    */
DTMDefaultBaseTraversers(DTMManager mgr, Source source, int dtmIdentity, DTMWSFilter whiteSpaceFilter, XMLStringFactory xstringfactory, boolean doIndexing, int blocksize, boolean usePrevsib, boolean newNameTable)80   public DTMDefaultBaseTraversers(DTMManager mgr, Source source,
81                                   int dtmIdentity,
82                                   DTMWSFilter whiteSpaceFilter,
83                                   XMLStringFactory xstringfactory,
84                                   boolean doIndexing,
85                                   int blocksize,
86                                   boolean usePrevsib,
87                                   boolean newNameTable)
88   {
89     super(mgr, source, dtmIdentity, whiteSpaceFilter, xstringfactory,
90           doIndexing, blocksize, usePrevsib, newNameTable);
91   }
92 
93   /**
94    * This returns a stateless "traverser", that can navigate
95    * over an XPath axis, though perhaps not in document order.
96    *
97    * @param axis One of Axes.ANCESTORORSELF, etc.
98    *
99    * @return A DTMAxisTraverser, or null if the given axis isn't supported.
100    */
getAxisTraverser(final int axis)101   public DTMAxisTraverser getAxisTraverser(final int axis)
102   {
103 
104     DTMAxisTraverser traverser;
105 
106     if (null == m_traversers)  // Cache of stateless traversers for this DTM
107     {
108       m_traversers = new DTMAxisTraverser[Axis.getNamesLength()];
109       traverser = null;
110     }
111     else
112     {
113       traverser = m_traversers[axis];  // Share/reuse existing traverser
114 
115       if (traverser != null)
116         return traverser;
117     }
118 
119     switch (axis)  // Generate new traverser
120     {
121     case Axis.ANCESTOR :
122       traverser = new AncestorTraverser();
123       break;
124     case Axis.ANCESTORORSELF :
125       traverser = new AncestorOrSelfTraverser();
126       break;
127     case Axis.ATTRIBUTE :
128       traverser = new AttributeTraverser();
129       break;
130     case Axis.CHILD :
131       traverser = new ChildTraverser();
132       break;
133     case Axis.DESCENDANT :
134       traverser = new DescendantTraverser();
135       break;
136     case Axis.DESCENDANTORSELF :
137       traverser = new DescendantOrSelfTraverser();
138       break;
139     case Axis.FOLLOWING :
140       traverser = new FollowingTraverser();
141       break;
142     case Axis.FOLLOWINGSIBLING :
143       traverser = new FollowingSiblingTraverser();
144       break;
145     case Axis.NAMESPACE :
146       traverser = new NamespaceTraverser();
147       break;
148     case Axis.NAMESPACEDECLS :
149       traverser = new NamespaceDeclsTraverser();
150       break;
151     case Axis.PARENT :
152       traverser = new ParentTraverser();
153       break;
154     case Axis.PRECEDING :
155       traverser = new PrecedingTraverser();
156       break;
157     case Axis.PRECEDINGSIBLING :
158       traverser = new PrecedingSiblingTraverser();
159       break;
160     case Axis.SELF :
161       traverser = new SelfTraverser();
162       break;
163     case Axis.ALL :
164       traverser = new AllFromRootTraverser();
165       break;
166     case Axis.ALLFROMNODE :
167       traverser = new AllFromNodeTraverser();
168       break;
169     case Axis.PRECEDINGANDANCESTOR :
170       traverser = new PrecedingAndAncestorTraverser();
171       break;
172     case Axis.DESCENDANTSFROMROOT :
173       traverser = new DescendantFromRootTraverser();
174       break;
175     case Axis.DESCENDANTSORSELFFROMROOT :
176       traverser = new DescendantOrSelfFromRootTraverser();
177       break;
178     case Axis.ROOT :
179       traverser = new RootTraverser();
180       break;
181     case Axis.FILTEREDLIST :
182       return null; // Don't want to throw an exception for this one.
183     default :
184       throw new DTMException(XMLMessages.createXMLMessage(XMLErrorResources.ER_UNKNOWN_AXIS_TYPE, new Object[]{Integer.toString(axis)})); //"Unknown axis traversal type: "+axis);
185     }
186 
187     if (null == traverser)
188       throw new DTMException(XMLMessages.createXMLMessage(XMLErrorResources.ER_AXIS_TRAVERSER_NOT_SUPPORTED, new Object[]{Axis.getNames(axis)}));
189       // "Axis traverser not supported: "
190       //                       + Axis.names[axis]);
191 
192     m_traversers[axis] = traverser;
193 
194     return traverser;
195   }
196 
197   /**
198    * Implements traversal of the Ancestor access, in reverse document order.
199    */
200   private class AncestorTraverser extends DTMAxisTraverser
201   {
202 
203     /**
204      * Traverse to the next node after the current node.
205      *
206      * @param context The context node if this iteration.
207      * @param current The current node of the iteration.
208      *
209      * @return the next node in the iteration, or DTM.NULL.
210      */
next(int context, int current)211     public int next(int context, int current)
212     {
213 			return getParent(current);
214     }
215 
216     /**
217      * Traverse to the next node after the current node that is matched
218      * by the expanded type ID.
219      *
220      * @param context The context node of this iteration.
221      * @param current The current node of the iteration.
222      * @param expandedTypeID The expanded type ID that must match.
223      *
224      * @return the next node in the iteration, or DTM.NULL.
225      */
next(int context, int current, int expandedTypeID)226     public int next(int context, int current, int expandedTypeID)
227     {
228 			// Process using identities
229       current = makeNodeIdentity(current);
230 
231       while (DTM.NULL != (current = m_parent.elementAt(current)))
232       {
233         if (m_exptype.elementAt(current) == expandedTypeID)
234           return makeNodeHandle(current);
235       }
236 
237       return NULL;
238     }
239   }
240 
241   /**
242    * Implements traversal of the Ancestor access, in reverse document order.
243    */
244   private class AncestorOrSelfTraverser extends AncestorTraverser
245   {
246 
247     /**
248      * By the nature of the stateless traversal, the context node can not be
249      * returned or the iteration will go into an infinate loop.  To see if
250      * the self node should be processed, use this function.
251      *
252      * @param context The context node of this traversal.
253      *
254      * @return the first node in the traversal.
255      */
first(int context)256     public int first(int context)
257     {
258       return context;
259     }
260 
261     /**
262      * By the nature of the stateless traversal, the context node can not be
263      * returned or the iteration will go into an infinate loop.  To see if
264      * the self node should be processed, use this function.  If the context
265      * node does not match the expanded type ID, this function will return
266      * false.
267      *
268      * @param context The context node of this traversal.
269      * @param expandedTypeID The expanded type ID that must match.
270      *
271      * @return the first node in the traversal.
272      */
first(int context, int expandedTypeID)273     public int first(int context, int expandedTypeID)
274     {
275 			return (getExpandedTypeID(context) == expandedTypeID)
276              ? context : next(context, context, expandedTypeID);
277     }
278   }
279 
280   /**
281    * Implements traversal of the Attribute access
282    */
283   private class AttributeTraverser extends DTMAxisTraverser
284   {
285 
286     /**
287      * Traverse to the next node after the current node.
288      *
289      * @param context The context node of this iteration.
290      * @param current The current node of the iteration.
291      *
292      * @return the next node in the iteration, or DTM.NULL.
293      */
next(int context, int current)294     public int next(int context, int current)
295     {
296       return (context == current)
297              ? getFirstAttribute(context) : getNextAttribute(current);
298     }
299 
300     /**
301      * Traverse to the next node after the current node that is matched
302      * by the expanded type ID.
303      *
304      * @param context The context node of this iteration.
305      * @param current The current node of the iteration.
306      * @param expandedTypeID The expanded type ID that must match.
307      *
308      * @return the next node in the iteration, or DTM.NULL.
309      */
next(int context, int current, int expandedTypeID)310     public int next(int context, int current, int expandedTypeID)
311     {
312 
313       current = (context == current)
314                 ? getFirstAttribute(context) : getNextAttribute(current);
315 
316       do
317       {
318         if (getExpandedTypeID(current) == expandedTypeID)
319           return current;
320       }
321       while (DTM.NULL != (current = getNextAttribute(current)));
322 
323       return NULL;
324     }
325   }
326 
327   /**
328    * Implements traversal of the Ancestor access, in reverse document order.
329    */
330   private class ChildTraverser extends DTMAxisTraverser
331   {
332 
333     /**
334      * Get the next indexed node that matches the expanded type ID.  Before
335      * calling this function, one should first call
336      * {@link #isIndexed(int) isIndexed} to make sure that the index can
337      * contain nodes that match the given expanded type ID.
338      *
339      * @param axisRoot The root identity of the axis.
340      * @param nextPotential The node found must match or occur after this node.
341      * @param expandedTypeID The expanded type ID for the request.
342      *
343      * @return The node ID or NULL if not found.
344      */
getNextIndexed(int axisRoot, int nextPotential, int expandedTypeID)345     protected int getNextIndexed(int axisRoot, int nextPotential,
346                                  int expandedTypeID)
347     {
348 
349       int nsIndex = m_expandedNameTable.getNamespaceID(expandedTypeID);
350       int lnIndex = m_expandedNameTable.getLocalNameID(expandedTypeID);
351 
352       for (; ; )
353       {
354         int nextID = findElementFromIndex(nsIndex, lnIndex, nextPotential);
355 
356         if (NOTPROCESSED != nextID)
357         {
358           int parentID = m_parent.elementAt(nextID);
359 
360           // Is it a child?
361           if(parentID == axisRoot)
362             return nextID;
363 
364           // If the parent occured before the subtree root, then
365           // we know it is past the child axis.
366           if(parentID < axisRoot)
367               return NULL;
368 
369           // Otherwise, it could be a descendant below the subtree root
370           // children, or it could be after the subtree root.  So we have
371           // to climb up until the parent is less than the subtree root, in
372           // which case we return NULL, or until it is equal to the subtree
373           // root, in which case we continue to look.
374           do
375           {
376             parentID = m_parent.elementAt(parentID);
377             if(parentID < axisRoot)
378               return NULL;
379           }
380             while(parentID > axisRoot);
381 
382           // System.out.println("Found node via index: "+first);
383           nextPotential = nextID+1;
384           continue;
385         }
386 
387         nextNode();
388 
389         if(!(m_nextsib.elementAt(axisRoot) == NOTPROCESSED))
390           break;
391       }
392 
393       return DTM.NULL;
394     }
395 
396     /**
397      * By the nature of the stateless traversal, the context node can not be
398      * returned or the iteration will go into an infinate loop.  So to traverse
399      * an axis, the first function must be used to get the first node.
400      *
401      * <p>This method needs to be overloaded only by those axis that process
402      * the self node. <\p>
403      *
404      * @param context The context node of this traversal. This is the point
405      * that the traversal starts from.
406      * @return the first node in the traversal.
407      */
first(int context)408     public int first(int context)
409     {
410       return getFirstChild(context);
411     }
412 
413     /**
414      * By the nature of the stateless traversal, the context node can not be
415      * returned or the iteration will go into an infinate loop.  So to traverse
416      * an axis, the first function must be used to get the first node.
417      *
418      * <p>This method needs to be overloaded only by those axis that process
419      * the self node. <\p>
420      *
421      * @param context The context node of this traversal. This is the point
422      * of origin for the traversal -- its "root node" or starting point.
423      * @param expandedTypeID The expanded type ID that must match.
424      *
425      * @return the first node in the traversal.
426      */
first(int context, int expandedTypeID)427     public int first(int context, int expandedTypeID)
428     {
429       if(true)
430       {
431         int identity = makeNodeIdentity(context);
432 
433         int firstMatch = getNextIndexed(identity, _firstch(identity),
434                                  expandedTypeID);
435 
436         return makeNodeHandle(firstMatch);
437       }
438       else
439       {
440 				// %REVIEW% Dead code. Eliminate?
441         for (int current = _firstch(makeNodeIdentity(context));
442              DTM.NULL != current;
443              current = _nextsib(current))
444         {
445           if (m_exptype.elementAt(current) == expandedTypeID)
446               return makeNodeHandle(current);
447         }
448         return NULL;
449       }
450     }
451 
452     /**
453      * Traverse to the next node after the current node.
454      *
455      * @param context The context node of this iteration.
456      * @param current The current node of the iteration.
457      *
458      * @return the next node in the iteration, or DTM.NULL.
459      */
next(int context, int current)460     public int next(int context, int current)
461     {
462       return getNextSibling(current);
463     }
464 
465     /**
466      * Traverse to the next node after the current node that is matched
467      * by the expanded type ID.
468      *
469      * @param context The context node of this iteration.
470      * @param current The current node of the iteration.
471      * @param expandedTypeID The expanded type ID that must match.
472      *
473      * @return the next node in the iteration, or DTM.NULL.
474      */
next(int context, int current, int expandedTypeID)475     public int next(int context, int current, int expandedTypeID)
476     {
477 			// Process in Identifier space
478       for (current = _nextsib(makeNodeIdentity(current));
479            DTM.NULL != current;
480            current = _nextsib(current))
481       {
482         if (m_exptype.elementAt(current) == expandedTypeID)
483             return makeNodeHandle(current);
484       }
485 
486       return NULL;
487     }
488   }
489 
490   /**
491    * Super class for derived classes that want a convenient way to access
492    * the indexing mechanism.
493    */
494   private abstract class IndexedDTMAxisTraverser extends DTMAxisTraverser
495   {
496 
497     /**
498      * Tell if the indexing is on and the given expanded type ID matches
499      * what is in the indexes.  Derived classes should call this before
500      * calling {@link #getNextIndexed(int, int, int) getNextIndexed} method.
501      *
502      * @param expandedTypeID The expanded type ID being requested.
503      *
504      * @return true if it is OK to call the
505      *         {@link #getNextIndexed(int, int, int) getNextIndexed} method.
506      */
isIndexed(int expandedTypeID)507     protected final boolean isIndexed(int expandedTypeID)
508     {
509       return (m_indexing
510               && ExpandedNameTable.ELEMENT
511                  == m_expandedNameTable.getType(expandedTypeID));
512     }
513 
514     /**
515      * Tell if a node is outside the axis being traversed.  This method must be
516      * implemented by derived classes, and must be robust enough to handle any
517      * node that occurs after the axis root.
518      *
519      * @param axisRoot The root identity of the axis.
520      * @param identity The node in question.
521      *
522      * @return true if the given node falls outside the axis being traversed.
523      */
isAfterAxis(int axisRoot, int identity)524     protected abstract boolean isAfterAxis(int axisRoot, int identity);
525 
526     /**
527      * Tell if the axis has been fully processed to tell if a the wait for
528      * an arriving node should terminate.  This method must be implemented
529      * be a derived class.
530      *
531      * @param axisRoot The root identity of the axis.
532      *
533      * @return true if the axis has been fully processed.
534      */
axisHasBeenProcessed(int axisRoot)535     protected abstract boolean axisHasBeenProcessed(int axisRoot);
536 
537     /**
538      * Get the next indexed node that matches the expanded type ID.  Before
539      * calling this function, one should first call
540      * {@link #isIndexed(int) isIndexed} to make sure that the index can
541      * contain nodes that match the given expanded type ID.
542      *
543      * @param axisRoot The root identity of the axis.
544      * @param nextPotential The node found must match or occur after this node.
545      * @param expandedTypeID The expanded type ID for the request.
546      *
547      * @return The node ID or NULL if not found.
548      */
getNextIndexed(int axisRoot, int nextPotential, int expandedTypeID)549     protected int getNextIndexed(int axisRoot, int nextPotential,
550                                  int expandedTypeID)
551     {
552 
553       int nsIndex = m_expandedNameTable.getNamespaceID(expandedTypeID);
554       int lnIndex = m_expandedNameTable.getLocalNameID(expandedTypeID);
555 
556       while(true)
557       {
558         int next = findElementFromIndex(nsIndex, lnIndex, nextPotential);
559 
560         if (NOTPROCESSED != next)
561         {
562           if (isAfterAxis(axisRoot, next))
563             return NULL;
564 
565           // System.out.println("Found node via index: "+first);
566           return next;
567         }
568         else if(axisHasBeenProcessed(axisRoot))
569           break;
570 
571         nextNode();
572       }
573 
574       return DTM.NULL;
575     }
576   }
577 
578   /**
579    * Implements traversal of the Ancestor access, in reverse document order.
580    */
581   private class DescendantTraverser extends IndexedDTMAxisTraverser
582   {
583     /**
584      * Get the first potential identity that can be returned.  This should
585      * be overridded by classes that need to return the self node.
586      *
587      * @param identity The node identity of the root context of the traversal.
588      *
589      * @return The first potential node that can be in the traversal.
590      */
getFirstPotential(int identity)591     protected int getFirstPotential(int identity)
592     {
593       return identity + 1;
594     }
595 
596     /**
597      * Tell if the axis has been fully processed to tell if a the wait for
598      * an arriving node should terminate.
599      *
600      * @param axisRoot The root identity of the axis.
601      *
602      * @return true if the axis has been fully processed.
603      */
axisHasBeenProcessed(int axisRoot)604     protected boolean axisHasBeenProcessed(int axisRoot)
605     {
606       return !(m_nextsib.elementAt(axisRoot) == NOTPROCESSED);
607     }
608 
609     /**
610      * Get the subtree root identity from the handle that was passed in by
611      * the caller.  Derived classes may override this to change the root
612      * context of the traversal.
613      *
614      * @param handle handle to the root context.
615      * @return identity of the root of the subtree.
616      */
getSubtreeRoot(int handle)617     protected int getSubtreeRoot(int handle)
618     {
619       return makeNodeIdentity(handle);
620     }
621 
622     /**
623      * Tell if this node identity is a descendant.  Assumes that
624      * the node info for the element has already been obtained.
625      *
626      * %REVIEW% This is really parentFollowsRootInDocumentOrder ...
627      * which fails if the parent starts after the root ends.
628      * May be sufficient for this class's logic, but misleadingly named!
629      *
630      * @param subtreeRootIdentity The root context of the subtree in question.
631      * @param identity The index number of the node in question.
632      * @return true if the index is a descendant of _startNode.
633      */
isDescendant(int subtreeRootIdentity, int identity)634     protected boolean isDescendant(int subtreeRootIdentity, int identity)
635     {
636       return _parent(identity) >= subtreeRootIdentity;
637     }
638 
639     /**
640      * Tell if a node is outside the axis being traversed.  This method must be
641      * implemented by derived classes, and must be robust enough to handle any
642      * node that occurs after the axis root.
643      *
644      * @param axisRoot The root identity of the axis.
645      * @param identity The node in question.
646      *
647      * @return true if the given node falls outside the axis being traversed.
648      */
isAfterAxis(int axisRoot, int identity)649     protected boolean isAfterAxis(int axisRoot, int identity)
650     {
651       // %REVIEW% Is there *any* cheaper way to do this?
652 			// Yes. In ID space, compare to axisRoot's successor
653 			// (next-sib or ancestor's-next-sib). Probably shallower search.
654       do
655       {
656         if(identity == axisRoot)
657           return false;
658         identity = m_parent.elementAt(identity);
659       }
660         while(identity >= axisRoot);
661 
662       return true;
663     }
664 
665     /**
666      * By the nature of the stateless traversal, the context node can not be
667      * returned or the iteration will go into an infinate loop.  So to traverse
668      * an axis, the first function must be used to get the first node.
669      *
670      * <p>This method needs to be overloaded only by those axis that process
671      * the self node. <\p>
672      *
673      * @param context The context node of this traversal. This is the point
674      * of origin for the traversal -- its "root node" or starting point.
675      * @param expandedTypeID The expanded type ID that must match.
676      *
677      * @return the first node in the traversal.
678      */
first(int context, int expandedTypeID)679     public int first(int context, int expandedTypeID)
680     {
681 
682       if (isIndexed(expandedTypeID))
683       {
684         int identity = getSubtreeRoot(context);
685         int firstPotential = getFirstPotential(identity);
686 
687         return makeNodeHandle(getNextIndexed(identity, firstPotential, expandedTypeID));
688       }
689 
690       return next(context, context, expandedTypeID);
691     }
692 
693     /**
694      * Traverse to the next node after the current node.
695      *
696      * @param context The context node of this iteration.
697      * @param current The current node of the iteration.
698      *
699      * @return the next node in the iteration, or DTM.NULL.
700      */
next(int context, int current)701     public int next(int context, int current)
702     {
703 
704       int subtreeRootIdent = getSubtreeRoot(context);
705 
706       for (current = makeNodeIdentity(current) + 1; ; current++)
707       {
708         int type = _type(current);  // may call nextNode()
709 
710         if (!isDescendant(subtreeRootIdent, current))
711           return NULL;
712 
713         if (ATTRIBUTE_NODE == type || NAMESPACE_NODE == type)
714           continue;
715 
716         return makeNodeHandle(current);  // make handle.
717       }
718     }
719 
720     /**
721      * Traverse to the next node after the current node that is matched
722      * by the expanded type ID.
723      *
724      * @param context The context node of this iteration.
725      * @param current The current node of the iteration.
726      * @param expandedTypeID The expanded type ID that must match.
727      *
728      * @return the next node in the iteration, or DTM.NULL.
729      */
next(int context, int current, int expandedTypeID)730     public int next(int context, int current, int expandedTypeID)
731     {
732 
733       int subtreeRootIdent = getSubtreeRoot(context);
734 
735       current = makeNodeIdentity(current) + 1;
736 
737       if (isIndexed(expandedTypeID))
738       {
739         return makeNodeHandle(getNextIndexed(subtreeRootIdent, current, expandedTypeID));
740       }
741 
742       for (; ; current++)
743       {
744         int exptype = _exptype(current);  // may call nextNode()
745 
746         if (!isDescendant(subtreeRootIdent, current))
747           return NULL;
748 
749         if (exptype != expandedTypeID)
750           continue;
751 
752         return makeNodeHandle(current);  // make handle.
753       }
754     }
755   }
756 
757   /**
758    * Implements traversal of the Ancestor access, in reverse document order.
759    */
760   private class DescendantOrSelfTraverser extends DescendantTraverser
761   {
762 
763     /**
764      * Get the first potential identity that can be returned, which is the
765      * axis context, in this case.
766      *
767      * @param identity The node identity of the root context of the traversal.
768      *
769      * @return The axis context.
770      */
getFirstPotential(int identity)771     protected int getFirstPotential(int identity)
772     {
773       return identity;
774     }
775 
776     /**
777      * By the nature of the stateless traversal, the context node can not be
778      * returned or the iteration will go into an infinate loop.  To see if
779      * the self node should be processed, use this function.
780      *
781      * @param context The context node of this traversal.
782      *
783      * @return the first node in the traversal.
784      */
first(int context)785     public int first(int context)
786     {
787       return context;
788     }
789   }
790 
791   /**
792    * Implements traversal of the entire subtree, including the root node.
793    */
794   private class AllFromNodeTraverser extends DescendantOrSelfTraverser
795   {
796 
797     /**
798      * Traverse to the next node after the current node.
799      *
800      * @param context The context node of this iteration.
801      * @param current The current node of the iteration.
802      *
803      * @return the next node in the iteration, or DTM.NULL.
804      */
next(int context, int current)805     public int next(int context, int current)
806     {
807 
808       int subtreeRootIdent = makeNodeIdentity(context);
809 
810       for (current = makeNodeIdentity(current) + 1; ; current++)
811       {
812         // Trickological code: _exptype() has the side-effect of
813         // running nextNode until the specified node has been loaded,
814         // and thus can be used to ensure that incremental construction of
815         // the DTM has gotten this far. Using it just for that side-effect
816         // is quite a kluge...
817         _exptype(current);  // make sure it's here.
818 
819         if (!isDescendant(subtreeRootIdent, current))
820           return NULL;
821 
822         return makeNodeHandle(current);  // make handle.
823       }
824     }
825   }
826 
827   /**
828    * Implements traversal of the following access, in document order.
829    */
830   private class FollowingTraverser extends DescendantTraverser
831   {
832 
833     /**
834      * Get the first of the following.
835      *
836      * @param context The context node of this traversal. This is the point
837      * that the traversal starts from.
838      * @return the first node in the traversal.
839      */
first(int context)840     public int first(int context)
841     {
842 			// Compute in ID space
843 			context=makeNodeIdentity(context);
844 
845       int first;
846       int type = _type(context);
847 
848       if ((DTM.ATTRIBUTE_NODE == type) || (DTM.NAMESPACE_NODE == type))
849       {
850         context = _parent(context);
851         first = _firstch(context);
852 
853         if (NULL != first)
854           return makeNodeHandle(first);
855       }
856 
857       do
858       {
859         first = _nextsib(context);
860 
861         if (NULL == first)
862           context = _parent(context);
863       }
864       while (NULL == first && NULL != context);
865 
866       return makeNodeHandle(first);
867     }
868 
869     /**
870      * Get the first of the following.
871      *
872      * @param context The context node of this traversal. This is the point
873      * of origin for the traversal -- its "root node" or starting point.
874      * @param expandedTypeID The expanded type ID that must match.
875      *
876      * @return the first node in the traversal.
877      */
first(int context, int expandedTypeID)878     public int first(int context, int expandedTypeID)
879     {
880 			// %REVIEW% This looks like it might want shift into identity space
881 			// to avoid repeated conversion in the individual functions
882       int first;
883       int type = getNodeType(context);
884 
885       if ((DTM.ATTRIBUTE_NODE == type) || (DTM.NAMESPACE_NODE == type))
886       {
887         context = getParent(context);
888         first = getFirstChild(context);
889 
890         if (NULL != first)
891         {
892           if (getExpandedTypeID(first) == expandedTypeID)
893             return first;
894           else
895             return next(context, first, expandedTypeID);
896         }
897       }
898 
899       do
900       {
901         first = getNextSibling(context);
902 
903         if (NULL == first)
904           context = getParent(context);
905         else
906         {
907           if (getExpandedTypeID(first) == expandedTypeID)
908             return first;
909           else
910             return next(context, first, expandedTypeID);
911         }
912       }
913       while (NULL == first && NULL != context);
914 
915       return first;
916     }
917 
918     /**
919      * Traverse to the next node after the current node.
920      *
921      * @param context The context node of this iteration.
922      * @param current The current node of the iteration.
923      *
924      * @return the next node in the iteration, or DTM.NULL.
925      */
next(int context, int current)926     public int next(int context, int current)
927     {
928 			// Compute in identity space
929 			current=makeNodeIdentity(current);
930 
931       while (true)
932       {
933         current++; // Only works on IDs, not handles.
934 
935 				// %REVIEW% Are we using handles or indexes?
936         int type = _type(current);  // may call nextNode()
937 
938         if (NULL == type)
939           return NULL;
940 
941         if (ATTRIBUTE_NODE == type || NAMESPACE_NODE == type)
942           continue;
943 
944         return makeNodeHandle(current);  // make handle.
945       }
946     }
947 
948     /**
949      * Traverse to the next node after the current node that is matched
950      * by the expanded type ID.
951      *
952      * @param context The context node of this iteration.
953      * @param current The current node of the iteration.
954      * @param expandedTypeID The expanded type ID that must match.
955      *
956      * @return the next node in the iteration, or DTM.NULL.
957      */
next(int context, int current, int expandedTypeID)958     public int next(int context, int current, int expandedTypeID)
959     {
960 			// Compute in ID space
961 			current=makeNodeIdentity(current);
962 
963       while (true)
964       {
965         current++;
966 
967         int etype = _exptype(current);  // may call nextNode()
968 
969         if (NULL == etype)
970           return NULL;
971 
972         if (etype != expandedTypeID)
973           continue;
974 
975         return makeNodeHandle(current);  // make handle.
976       }
977     }
978   }
979 
980   /**
981    * Implements traversal of the Ancestor access, in reverse document order.
982    */
983   private class FollowingSiblingTraverser extends DTMAxisTraverser
984   {
985 
986     /**
987      * Traverse to the next node after the current node.
988      *
989      * @param context The context node of this iteration.
990      * @param current The current node of the iteration.
991      *
992      * @return the next node in the iteration, or DTM.NULL.
993      */
next(int context, int current)994     public int next(int context, int current)
995     {
996       return getNextSibling(current);
997     }
998 
999     /**
1000      * Traverse to the next node after the current node that is matched
1001      * by the expanded type ID.
1002      *
1003      * @param context The context node of this iteration.
1004      * @param current The current node of the iteration.
1005      * @param expandedTypeID The expanded type ID that must match.
1006      *
1007      * @return the next node in the iteration, or DTM.NULL.
1008      */
next(int context, int current, int expandedTypeID)1009     public int next(int context, int current, int expandedTypeID)
1010     {
1011 
1012       while (DTM.NULL != (current = getNextSibling(current)))
1013       {
1014         if (getExpandedTypeID(current) == expandedTypeID)
1015           return current;
1016       }
1017 
1018       return NULL;
1019     }
1020   }
1021 
1022   /**
1023    * Implements traversal of the Ancestor access, in reverse document order.
1024    */
1025   private class NamespaceDeclsTraverser extends DTMAxisTraverser
1026   {
1027 
1028     /**
1029      * Traverse to the next node after the current node.
1030      *
1031      * @param context The context node of this iteration.
1032      * @param current The current node of the iteration.
1033      *
1034      * @return the next node in the iteration, or DTM.NULL.
1035      */
next(int context, int current)1036     public int next(int context, int current)
1037     {
1038 
1039       return (context == current)
1040              ? getFirstNamespaceNode(context, false)
1041              : getNextNamespaceNode(context, current, false);
1042     }
1043 
1044     /**
1045      * Traverse to the next node after the current node that is matched
1046      * by the expanded type ID.
1047      *
1048      * @param context The context node of this iteration.
1049      * @param current The current node of the iteration.
1050      * @param expandedTypeID The expanded type ID that must match.
1051      *
1052      * @return the next node in the iteration, or DTM.NULL.
1053      */
next(int context, int current, int expandedTypeID)1054     public int next(int context, int current, int expandedTypeID)
1055     {
1056 
1057       current = (context == current)
1058                 ? getFirstNamespaceNode(context, false)
1059                 : getNextNamespaceNode(context, current, false);
1060 
1061       do
1062       {
1063         if (getExpandedTypeID(current) == expandedTypeID)
1064           return current;
1065       }
1066       while (DTM.NULL
1067              != (current = getNextNamespaceNode(context, current, false)));
1068 
1069       return NULL;
1070     }
1071   }
1072 
1073   /**
1074    * Implements traversal of the Ancestor access, in reverse document order.
1075    */
1076   private class NamespaceTraverser extends DTMAxisTraverser
1077   {
1078 
1079     /**
1080      * Traverse to the next node after the current node.
1081      *
1082      * @param context The context node of this iteration.
1083      * @param current The current node of the iteration.
1084      *
1085      * @return the next node in the iteration, or DTM.NULL.
1086      */
next(int context, int current)1087     public int next(int context, int current)
1088     {
1089 
1090       return (context == current)
1091              ? getFirstNamespaceNode(context, true)
1092              : getNextNamespaceNode(context, current, true);
1093     }
1094 
1095     /**
1096      * Traverse to the next node after the current node that is matched
1097      * by the expanded type ID.
1098      *
1099      * @param context The context node of this iteration.
1100      * @param current The current node of the iteration.
1101      * @param expandedTypeID The expanded type ID that must match.
1102      *
1103      * @return the next node in the iteration, or DTM.NULL.
1104      */
next(int context, int current, int expandedTypeID)1105     public int next(int context, int current, int expandedTypeID)
1106     {
1107 
1108       current = (context == current)
1109                 ? getFirstNamespaceNode(context, true)
1110                 : getNextNamespaceNode(context, current, true);
1111 
1112       do
1113       {
1114         if (getExpandedTypeID(current) == expandedTypeID)
1115           return current;
1116       }
1117       while (DTM.NULL
1118              != (current = getNextNamespaceNode(context, current, true)));
1119 
1120       return NULL;
1121     }
1122   }
1123 
1124   /**
1125    * Implements traversal of the Ancestor access, in reverse document order.
1126    */
1127   private class ParentTraverser extends DTMAxisTraverser
1128   {
1129     /**
1130      * By the nature of the stateless traversal, the context node can not be
1131      * returned or the iteration will go into an infinate loop.  So to traverse
1132      * an axis, the first function must be used to get the first node.
1133      *
1134      * <p>This method needs to be overloaded only by those axis that process
1135      * the self node. <\p>
1136      *
1137      * @param context The context node of this traversal. This is the point
1138      * that the traversal starts from.
1139      * @return the first node in the traversal.
1140      */
first(int context)1141     public int first(int context)
1142     {
1143       return getParent(context);
1144     }
1145 
1146     /**
1147      * By the nature of the stateless traversal, the context node can not be
1148      * returned or the iteration will go into an infinate loop.  So to traverse
1149      * an axis, the first function must be used to get the first node.
1150      *
1151      * <p>This method needs to be overloaded only by those axis that process
1152      * the self node. <\p>
1153      *
1154      * @param context The context node of this traversal. This is the point
1155      * of origin for the traversal -- its "root node" or starting point.
1156      * @param expandedTypeID The expanded type ID that must match.
1157      *
1158      * @return the first node in the traversal.
1159      */
first(int current, int expandedTypeID)1160     public int first(int current, int expandedTypeID)
1161     {
1162 			// Compute in ID space
1163       current = makeNodeIdentity(current);
1164 
1165       while (NULL != (current = m_parent.elementAt(current)))
1166       {
1167         if (m_exptype.elementAt(current) == expandedTypeID)
1168           return makeNodeHandle(current);
1169       }
1170 
1171       return NULL;
1172     }
1173 
1174 
1175     /**
1176      * Traverse to the next node after the current node.
1177      *
1178      * @param context The context node of this iteration.
1179      * @param current The current node of the iteration.
1180      *
1181      * @return the next node in the iteration, or DTM.NULL.
1182      */
next(int context, int current)1183     public int next(int context, int current)
1184     {
1185 
1186       return NULL;
1187     }
1188 
1189 
1190 
1191     /**
1192      * Traverse to the next node after the current node that is matched
1193      * by the expanded type ID.
1194      *
1195      * @param context The context node of this iteration.
1196      * @param current The current node of the iteration.
1197      * @param expandedTypeID The expanded type ID that must match.
1198      *
1199      * @return the next node in the iteration, or DTM.NULL.
1200      */
next(int context, int current, int expandedTypeID)1201     public int next(int context, int current, int expandedTypeID)
1202     {
1203 
1204       return NULL;
1205     }
1206   }
1207 
1208   /**
1209    * Implements traversal of the Ancestor access, in reverse document order.
1210    */
1211   private class PrecedingTraverser extends DTMAxisTraverser
1212   {
1213 
1214     /**
1215      * Tell if the current identity is an ancestor of the context identity.
1216      * This is an expensive operation, made worse by the stateless traversal.
1217      * But the preceding axis is used fairly infrequently.
1218      *
1219      * @param contextIdent The context node of the axis traversal.
1220      * @param currentIdent The node in question.
1221      * @return true if the currentIdent node is an ancestor of contextIdent.
1222      */
isAncestor(int contextIdent, int currentIdent)1223     protected boolean isAncestor(int contextIdent, int currentIdent)
1224     {
1225 			// %REVIEW% See comments in IsAfterAxis; using the "successor" of
1226 			// contextIdent is probably more efficient.
1227       for (contextIdent = m_parent.elementAt(contextIdent); DTM.NULL != contextIdent;
1228               contextIdent = m_parent.elementAt(contextIdent))
1229       {
1230         if (contextIdent == currentIdent)
1231           return true;
1232       }
1233 
1234       return false;
1235     }
1236 
1237     /**
1238      * Traverse to the next node after the current node.
1239      *
1240      * @param context The context node of this iteration.
1241      * @param current The current node of the iteration.
1242      *
1243      * @return the next node in the iteration, or DTM.NULL.
1244      */
next(int context, int current)1245     public int next(int context, int current)
1246     {
1247 			// compute in ID space
1248       int subtreeRootIdent = makeNodeIdentity(context);
1249 
1250       for (current = makeNodeIdentity(current) - 1; current >= 0; current--)
1251       {
1252         short type = _type(current);
1253 
1254         if (ATTRIBUTE_NODE == type || NAMESPACE_NODE == type
1255                 || isAncestor(subtreeRootIdent, current))
1256           continue;
1257 
1258         return makeNodeHandle(current);  // make handle.
1259       }
1260 
1261       return NULL;
1262     }
1263 
1264     /**
1265      * Traverse to the next node after the current node that is matched
1266      * by the expanded type ID.
1267      *
1268      * @param context The context node of this iteration.
1269      * @param current The current node of the iteration.
1270      * @param expandedTypeID The expanded type ID that must match.
1271      *
1272      * @return the next node in the iteration, or DTM.NULL.
1273      */
next(int context, int current, int expandedTypeID)1274     public int next(int context, int current, int expandedTypeID)
1275     {
1276 			// Compute in ID space
1277       int subtreeRootIdent = makeNodeIdentity(context);
1278 
1279       for (current = makeNodeIdentity(current) - 1; current >= 0; current--)
1280       {
1281         int exptype = m_exptype.elementAt(current);
1282 
1283         if (exptype != expandedTypeID
1284                 || isAncestor(subtreeRootIdent, current))
1285           continue;
1286 
1287         return makeNodeHandle(current);  // make handle.
1288       }
1289 
1290       return NULL;
1291     }
1292   }
1293 
1294   /**
1295    * Implements traversal of the Ancestor and the Preceding axis,
1296    * in reverse document order.
1297    */
1298   private class PrecedingAndAncestorTraverser extends DTMAxisTraverser
1299   {
1300 
1301     /**
1302      * Traverse to the next node after the current node.
1303      *
1304      * @param context The context node of this iteration.
1305      * @param current The current node of the iteration.
1306      *
1307      * @return the next node in the iteration, or DTM.NULL.
1308      */
next(int context, int current)1309     public int next(int context, int current)
1310     {
1311 			// Compute in ID space
1312       int subtreeRootIdent = makeNodeIdentity(context );
1313 
1314       for (current = makeNodeIdentity(current) - 1; current >= 0; current--)
1315       {
1316         short type = _type(current);
1317 
1318         if (ATTRIBUTE_NODE == type || NAMESPACE_NODE == type)
1319           continue;
1320 
1321         return makeNodeHandle(current);  // make handle.
1322       }
1323 
1324       return NULL;
1325     }
1326 
1327     /**
1328      * Traverse to the next node after the current node that is matched
1329      * by the expanded type ID.
1330      *
1331      * @param context The context node of this iteration.
1332      * @param current The current node of the iteration.
1333      * @param expandedTypeID The expanded type ID that must match.
1334      *
1335      * @return the next node in the iteration, or DTM.NULL.
1336      */
next(int context, int current, int expandedTypeID)1337     public int next(int context, int current, int expandedTypeID)
1338     {
1339 			// Compute in ID space
1340       int subtreeRootIdent = makeNodeIdentity(context);
1341 
1342       for (current = makeNodeIdentity(current) - 1; current >= 0; current--)
1343       {
1344         int exptype = m_exptype.elementAt(current);
1345 
1346         if (exptype != expandedTypeID)
1347           continue;
1348 
1349         return makeNodeHandle(current);  // make handle.
1350       }
1351 
1352       return NULL;
1353     }
1354   }
1355 
1356   /**
1357    * Implements traversal of the Ancestor access, in reverse document order.
1358    */
1359   private class PrecedingSiblingTraverser extends DTMAxisTraverser
1360   {
1361 
1362     /**
1363      * Traverse to the next node after the current node.
1364      *
1365      * @param context The context node of this iteration.
1366      * @param current The current node of the iteration.
1367      *
1368      * @return the next node in the iteration, or DTM.NULL.
1369      */
next(int context, int current)1370     public int next(int context, int current)
1371     {
1372       return getPreviousSibling(current);
1373     }
1374 
1375     /**
1376      * Traverse to the next node after the current node that is matched
1377      * by the expanded type ID.
1378      *
1379      * @param context The context node of this iteration.
1380      * @param current The current node of the iteration.
1381      * @param expandedTypeID The expanded type ID that must match.
1382      *
1383      * @return the next node in the iteration, or DTM.NULL.
1384      */
next(int context, int current, int expandedTypeID)1385     public int next(int context, int current, int expandedTypeID)
1386     {
1387 
1388       while (DTM.NULL != (current = getPreviousSibling(current)))
1389       {
1390         if (getExpandedTypeID(current) == expandedTypeID)
1391           return current;
1392       }
1393 
1394       return NULL;
1395     }
1396   }
1397 
1398   /**
1399    * Implements traversal of the Self axis.
1400    */
1401   private class SelfTraverser extends DTMAxisTraverser
1402   {
1403 
1404     /**
1405      * By the nature of the stateless traversal, the context node can not be
1406      * returned or the iteration will go into an infinate loop.  To see if
1407      * the self node should be processed, use this function.
1408      *
1409      * @param context The context node of this traversal.
1410      *
1411      * @return the first node in the traversal.
1412      */
first(int context)1413     public int first(int context)
1414     {
1415       return context;
1416     }
1417 
1418     /**
1419      * By the nature of the stateless traversal, the context node can not be
1420      * returned or the iteration will go into an infinate loop.  To see if
1421      * the self node should be processed, use this function.  If the context
1422      * node does not match the expanded type ID, this function will return
1423      * false.
1424      *
1425      * @param context The context node of this traversal.
1426      * @param expandedTypeID The expanded type ID that must match.
1427      *
1428      * @return the first node in the traversal.
1429      */
first(int context, int expandedTypeID)1430     public int first(int context, int expandedTypeID)
1431     {
1432       return (getExpandedTypeID(context) == expandedTypeID) ? context : NULL;
1433     }
1434 
1435     /**
1436      * Traverse to the next node after the current node.
1437      *
1438      * @param context The context node of this iteration.
1439      * @param current The current node of the iteration.
1440      *
1441      * @return Always return NULL for this axis.
1442      */
next(int context, int current)1443     public int next(int context, int current)
1444     {
1445       return NULL;
1446     }
1447 
1448     /**
1449      * Traverse to the next node after the current node that is matched
1450      * by the expanded type ID.
1451      *
1452      * @param context The context node of this iteration.
1453      * @param current The current node of the iteration.
1454      * @param expandedTypeID The expanded type ID that must match.
1455      *
1456      * @return the next node in the iteration, or DTM.NULL.
1457      */
next(int context, int current, int expandedTypeID)1458     public int next(int context, int current, int expandedTypeID)
1459     {
1460       return NULL;
1461     }
1462   }
1463 
1464   /**
1465    * Implements traversal of the Ancestor access, in reverse document order.
1466    */
1467   private class AllFromRootTraverser extends AllFromNodeTraverser
1468   {
1469 
1470     /**
1471      * Return the root.
1472      *
1473      * @param context The context node of this traversal.
1474      *
1475      * @return the first node in the traversal.
1476      */
first(int context)1477     public int first(int context)
1478     {
1479       return getDocumentRoot(context);
1480     }
1481 
1482     /**
1483      * Return the root if it matches the expanded type ID.
1484      *
1485      * @param context The context node of this traversal.
1486      * @param expandedTypeID The expanded type ID that must match.
1487      *
1488      * @return the first node in the traversal.
1489      */
first(int context, int expandedTypeID)1490     public int first(int context, int expandedTypeID)
1491     {
1492       return (getExpandedTypeID(getDocumentRoot(context)) == expandedTypeID)
1493              ? context : next(context, context, expandedTypeID);
1494     }
1495 
1496     /**
1497      * Traverse to the next node after the current node.
1498      *
1499      * @param context The context node of this iteration.
1500      * @param current The current node of the iteration.
1501      *
1502      * @return the next node in the iteration, or DTM.NULL.
1503      */
next(int context, int current)1504     public int next(int context, int current)
1505     {
1506 			// Compute in ID space
1507       int subtreeRootIdent = makeNodeIdentity(context);
1508 
1509       for (current = makeNodeIdentity(current) + 1; ; current++)
1510       {
1511 				// Kluge test: Just make sure +1 yielded a real node
1512         int type = _type(current);  // may call nextNode()
1513         if (type == NULL)
1514           return NULL;
1515 
1516         return makeNodeHandle(current);  // make handle.
1517       }
1518     }
1519 
1520     /**
1521      * Traverse to the next node after the current node that is matched
1522      * by the expanded type ID.
1523      *
1524      * @param context The context node of this iteration.
1525      * @param current The current node of the iteration.
1526      * @param expandedTypeID The expanded type ID that must match.
1527      *
1528      * @return the next node in the iteration, or DTM.NULL.
1529      */
next(int context, int current, int expandedTypeID)1530     public int next(int context, int current, int expandedTypeID)
1531     {
1532 			// Compute in ID space
1533       int subtreeRootIdent = makeNodeIdentity(context);
1534 
1535       for (current = makeNodeIdentity(current) + 1; ; current++)
1536       {
1537         int exptype = _exptype(current);  // may call nextNode()
1538 
1539         if (exptype == NULL)
1540           return NULL;
1541 
1542         if (exptype != expandedTypeID)
1543           continue;
1544 
1545         return makeNodeHandle(current);  // make handle.
1546       }
1547     }
1548   }
1549 
1550   /**
1551    * Implements traversal of the Self axis.
1552    */
1553   private class RootTraverser extends AllFromRootTraverser
1554   {
1555     /**
1556      * Return the root if it matches the expanded type ID,
1557      * else return null (nothing found)
1558      *
1559      * @param context The context node of this traversal.
1560      * @param expandedTypeID The expanded type ID that must match.
1561      *
1562      * @return the first node in the traversal.
1563      */
first(int context, int expandedTypeID)1564     public int first(int context, int expandedTypeID)
1565     {
1566       int root=getDocumentRoot(context);
1567       return (getExpandedTypeID(root) == expandedTypeID)
1568 	? root : NULL;
1569     }
1570 
1571     /**
1572      * Traverse to the next node after the current node.
1573      *
1574      * @param context The context node of this iteration.
1575      * @param current The current node of the iteration.
1576      *
1577      * @return Always return NULL for this axis.
1578      */
next(int context, int current)1579     public int next(int context, int current)
1580     {
1581       return NULL;
1582     }
1583 
1584     /**
1585      * Traverse to the next node after the current node that is matched
1586      * by the expanded type ID.
1587      *
1588      * @param context The context node of this iteration.
1589      * @param current The current node of the iteration.
1590      * @param expandedTypeID The expanded type ID that must match.
1591      *
1592      * @return the next node in the iteration, or DTM.NULL.
1593      */
next(int context, int current, int expandedTypeID)1594     public int next(int context, int current, int expandedTypeID)
1595     {
1596       return NULL;
1597     }
1598   }
1599 
1600   /**
1601    * A non-xpath axis, returns all nodes that aren't namespaces or attributes,
1602    * from and including the root.
1603    */
1604   private class DescendantOrSelfFromRootTraverser extends DescendantTraverser
1605   {
1606 
1607     /**
1608      * Get the first potential identity that can be returned, which is the axis
1609      * root context in this case.
1610      *
1611      * @param identity The node identity of the root context of the traversal.
1612      *
1613      * @return The identity argument.
1614      */
getFirstPotential(int identity)1615     protected int getFirstPotential(int identity)
1616     {
1617       return identity;
1618     }
1619 
1620     /**
1621      * Get the first potential identity that can be returned.
1622      * @param handle handle to the root context.
1623      * @return identity of the root of the subtree.
1624      */
getSubtreeRoot(int handle)1625     protected int getSubtreeRoot(int handle)
1626     {
1627 			// %REVIEW% Shouldn't this always be 0?
1628       return makeNodeIdentity(getDocument());
1629     }
1630 
1631     /**
1632      * Return the root.
1633      *
1634      * @param context The context node of this traversal.
1635      *
1636      * @return the first node in the traversal.
1637      */
first(int context)1638     public int first(int context)
1639     {
1640       return getDocumentRoot(context);
1641     }
1642 
1643     /**
1644      * By the nature of the stateless traversal, the context node can not be
1645      * returned or the iteration will go into an infinate loop.  So to traverse
1646      * an axis, the first function must be used to get the first node.
1647      *
1648      * <p>This method needs to be overloaded only by those axis that process
1649      * the self node. <\p>
1650      *
1651      * @param context The context node of this traversal. This is the point
1652      * of origin for the traversal -- its "root node" or starting point.
1653      * @param expandedTypeID The expanded type ID that must match.
1654      *
1655      * @return the first node in the traversal.
1656      */
first(int context, int expandedTypeID)1657     public int first(int context, int expandedTypeID)
1658     {
1659       if (isIndexed(expandedTypeID))
1660       {
1661         int identity = 0;
1662         int firstPotential = getFirstPotential(identity);
1663 
1664         return makeNodeHandle(getNextIndexed(identity, firstPotential, expandedTypeID));
1665       }
1666 
1667       int root = first(context);
1668       return next(root, root, expandedTypeID);
1669     }
1670   }
1671 
1672   /**
1673    * A non-xpath axis, returns all nodes that aren't namespaces or attributes,
1674    * from but not including the root.
1675    */
1676   private class DescendantFromRootTraverser extends DescendantTraverser
1677   {
1678 
1679     /**
1680      * Get the first potential identity that can be returned, which is the axis
1681      * root context in this case.
1682      *
1683      * @param identity The node identity of the root context of the traversal.
1684      *
1685      * @return The identity argument.
1686      */
getFirstPotential(int identity)1687     protected int getFirstPotential(int identity)
1688     {
1689       return _firstch(0);
1690     }
1691 
1692     /**
1693      * Get the first potential identity that can be returned.
1694      * @param handle handle to the root context.
1695      * @return identity of the root of the subtree.
1696      */
getSubtreeRoot(int handle)1697     protected int getSubtreeRoot(int handle)
1698     {
1699       return 0;
1700     }
1701 
1702     /**
1703      * Return the root.
1704      *
1705      * @param context The context node of this traversal.
1706      *
1707      * @return the first node in the traversal.
1708      */
first(int context)1709     public int first(int context)
1710     {
1711       return makeNodeHandle(_firstch(0));
1712     }
1713 
1714     /**
1715      * By the nature of the stateless traversal, the context node can not be
1716      * returned or the iteration will go into an infinate loop.  So to traverse
1717      * an axis, the first function must be used to get the first node.
1718      *
1719      * <p>This method needs to be overloaded only by those axis that process
1720      * the self node. <\p>
1721      *
1722      * @param context The context node of this traversal. This is the point
1723      * of origin for the traversal -- its "root node" or starting point.
1724      * @param expandedTypeID The expanded type ID that must match.
1725      *
1726      * @return the first node in the traversal.
1727      */
first(int context, int expandedTypeID)1728     public int first(int context, int expandedTypeID)
1729     {
1730       if (isIndexed(expandedTypeID))
1731       {
1732         int identity = 0;
1733         int firstPotential = getFirstPotential(identity);
1734 
1735         return makeNodeHandle(getNextIndexed(identity, firstPotential, expandedTypeID));
1736       }
1737 
1738       int root = getDocumentRoot(context);
1739       return next(root, root, expandedTypeID);
1740     }
1741 
1742   }
1743 
1744 }
1745