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: LocPathIterator.java 468655 2006-10-28 07:12:06Z minchau $
020     */
021    package org.apache.xpath.axes;
022    
023    import org.apache.xalan.res.XSLMessages;
024    import org.apache.xml.dtm.DTM;
025    import org.apache.xml.dtm.DTMFilter;
026    import org.apache.xml.dtm.DTMIterator;
027    import org.apache.xml.dtm.DTMManager;
028    import org.apache.xml.utils.PrefixResolver;
029    import org.apache.xpath.ExpressionOwner;
030    import org.apache.xpath.XPathContext;
031    import org.apache.xpath.XPathVisitor;
032    import org.apache.xpath.compiler.Compiler;
033    import org.apache.xpath.objects.XNodeSet;
034    import org.apache.xpath.objects.XObject;
035    import org.apache.xpath.res.XPATHErrorResources;
036    
037    /**
038     * This class extends NodeSetDTM, which implements NodeIterator,
039     * and fetches nodes one at a time in document order based on a XPath
040     * <a href="http://www.w3.org/TR/xpath#NT-LocationPath>LocationPath</a>.
041     *
042     * <p>If setShouldCacheNodes(true) is called,
043     * as each node is iterated via nextNode(), the node is also stored
044     * in the NodeVector, so that previousNode() can easily be done, except in
045     * the case where the LocPathIterator is "owned" by a UnionPathIterator,
046     * in which case the UnionPathIterator will cache the nodes.</p>
047     * @xsl.usage advanced
048     */
049    public abstract class LocPathIterator extends PredicatedNodeTest
050            implements Cloneable, DTMIterator, java.io.Serializable, PathComponent
051    {
052        static final long serialVersionUID = -4602476357268405754L;
053            
054      /**
055       * Create a LocPathIterator object.
056       *
057       */
058      protected LocPathIterator()
059      {
060      }
061    
062    
063      /**
064       * Create a LocPathIterator object.
065       *
066       * @param nscontext The namespace context for this iterator,
067       * should be OK if null.
068       */
069      protected LocPathIterator(PrefixResolver nscontext)
070      {
071    
072        setLocPathIterator(this);
073        m_prefixResolver = nscontext;
074      }
075    
076      /**
077       * Create a LocPathIterator object, including creation
078       * of step walkers from the opcode list, and call back
079       * into the Compiler to create predicate expressions.
080       *
081       * @param compiler The Compiler which is creating
082       * this expression.
083       * @param opPos The position of this iterator in the
084       * opcode list from the compiler.
085       *
086       * @throws javax.xml.transform.TransformerException
087       */
088      protected LocPathIterator(Compiler compiler, int opPos, int analysis)
089              throws javax.xml.transform.TransformerException
090      {
091        this(compiler, opPos, analysis, true);
092      }
093    
094      /**
095       * Create a LocPathIterator object, including creation
096       * of step walkers from the opcode list, and call back
097       * into the Compiler to create predicate expressions.
098       *
099       * @param compiler The Compiler which is creating
100       * this expression.
101       * @param opPos The position of this iterator in the
102       * opcode list from the compiler.
103       * @param shouldLoadWalkers True if walkers should be
104       * loaded, or false if this is a derived iterator and
105       * it doesn't wish to load child walkers.
106       *
107       * @throws javax.xml.transform.TransformerException
108       */
109      protected LocPathIterator(
110              Compiler compiler, int opPos, int analysis, boolean shouldLoadWalkers)
111                throws javax.xml.transform.TransformerException
112      {
113        setLocPathIterator(this);
114      }
115      
116      /** 
117       * Get the analysis bits for this walker, as defined in the WalkerFactory.
118       * @return One of WalkerFactory#BIT_DESCENDANT, etc.
119       */
120      public int getAnalysisBits()
121      {
122            int axis = getAxis();
123            int bit = WalkerFactory.getAnalysisBitFromAxes(axis);
124            return bit;
125      }
126      
127      /**
128       * Read the object from a serialization stream.
129       *
130       * @param stream Input stream to read from
131       *
132       * @throws java.io.IOException
133       * @throws javax.xml.transform.TransformerException
134       */
135      private void readObject(java.io.ObjectInputStream stream)
136              throws java.io.IOException, javax.xml.transform.TransformerException
137      {
138        try
139        {
140          stream.defaultReadObject();
141          m_clones =  new IteratorPool(this);
142        }
143        catch (ClassNotFoundException cnfe)
144        {
145          throw new javax.xml.transform.TransformerException(cnfe);
146        }
147      }
148      
149      /**
150       * Set the environment in which this iterator operates, which should provide:
151       * a node (the context node... same value as "root" defined below) 
152       * a pair of non-zero positive integers (the context position and the context size) 
153       * a set of variable bindings 
154       * a function library 
155       * the set of namespace declarations in scope for the expression.
156       * 
157       * <p>At this time the exact implementation of this environment is application 
158       * dependent.  Probably a proper interface will be created fairly soon.</p>
159       * 
160       * @param environment The environment object.
161       */
162      public void setEnvironment(Object environment)
163      {
164        // no-op for now.
165      }
166      
167      /**
168       * Get an instance of a DTM that "owns" a node handle.  Since a node 
169       * iterator may be passed without a DTMManager, this allows the 
170       * caller to easily get the DTM using just the iterator.
171       *
172       * @param nodeHandle the nodeHandle.
173       *
174       * @return a non-null DTM reference.
175       */
176      public DTM getDTM(int nodeHandle)
177      {
178        // %OPT%
179        return m_execContext.getDTM(nodeHandle);
180      }
181      
182      /**
183       * Get an instance of the DTMManager.  Since a node 
184       * iterator may be passed without a DTMManager, this allows the 
185       * caller to easily get the DTMManager using just the iterator.
186       *
187       * @return a non-null DTMManager reference.
188       */
189      public DTMManager getDTMManager()
190      {
191        return m_execContext.getDTMManager();
192      }
193      
194      /**
195       * Execute this iterator, meaning create a clone that can
196       * store state, and initialize it for fast execution from
197       * the current runtime state.  When this is called, no actual
198       * query from the current context node is performed.
199       *
200       * @param xctxt The XPath execution context.
201       *
202       * @return An XNodeSet reference that holds this iterator.
203       *
204       * @throws javax.xml.transform.TransformerException
205       */
206      public XObject execute(XPathContext xctxt)
207              throws javax.xml.transform.TransformerException
208      {
209    
210        XNodeSet iter = new XNodeSet((LocPathIterator)m_clones.getInstance());
211    
212        iter.setRoot(xctxt.getCurrentNode(), xctxt);
213    
214        return iter;
215      }
216        
217      /**
218       * Execute an expression in the XPath runtime context, and return the
219       * result of the expression.
220       *
221       *
222       * @param xctxt The XPath runtime context.
223       * @param handler The target content handler.
224       *
225       * @return The result of the expression in the form of a <code>XObject</code>.
226       *
227       * @throws javax.xml.transform.TransformerException if a runtime exception
228       *         occurs.
229       * @throws org.xml.sax.SAXException
230       */
231      public void executeCharsToContentHandler(
232              XPathContext xctxt, org.xml.sax.ContentHandler handler)
233                throws javax.xml.transform.TransformerException,
234                       org.xml.sax.SAXException
235      {
236        LocPathIterator clone = (LocPathIterator)m_clones.getInstance();
237    
238        int current = xctxt.getCurrentNode();
239        clone.setRoot(current, xctxt);
240        
241        int node = clone.nextNode();
242        DTM dtm = clone.getDTM(node);
243        clone.detach();
244            
245        if(node != DTM.NULL)
246        {
247          dtm.dispatchCharactersEvents(node, handler, false);
248        }
249      }
250      
251      /**
252       * Given an select expression and a context, evaluate the XPath
253       * and return the resulting iterator.
254       * 
255       * @param xctxt The execution context.
256       * @param contextNode The node that "." expresses.
257       * @throws TransformerException thrown if the active ProblemListener decides
258       * the error condition is severe enough to halt processing.
259       *
260       * @throws javax.xml.transform.TransformerException
261       * @xsl.usage experimental
262       */
263      public DTMIterator asIterator(
264              XPathContext xctxt, int contextNode)
265                throws javax.xml.transform.TransformerException
266      {
267        XNodeSet iter = new XNodeSet((LocPathIterator)m_clones.getInstance());
268    
269        iter.setRoot(contextNode, xctxt);
270    
271        return iter;
272      }
273    
274      
275      /**
276       * Tell if the expression is a nodeset expression.
277       * 
278       * @return true if the expression can be represented as a nodeset.
279       */
280      public boolean isNodesetExpr()
281      {
282        return true;
283      }
284      
285      /**
286       * Return the first node out of the nodeset, if this expression is 
287       * a nodeset expression.  This is the default implementation for 
288       * nodesets.  Derived classes should try and override this and return a 
289       * value without having to do a clone operation.
290       * @param xctxt The XPath runtime context.
291       * @return the first node out of the nodeset, or DTM.NULL.
292       */
293      public int asNode(XPathContext xctxt)
294        throws javax.xml.transform.TransformerException
295      {
296        DTMIterator iter = (DTMIterator)m_clones.getInstance();
297        
298        int current = xctxt.getCurrentNode();
299        
300        iter.setRoot(current, xctxt);
301    
302        int next = iter.nextNode();
303        // m_clones.freeInstance(iter);
304        iter.detach();
305        return next;
306      }
307      
308      /**
309       * Evaluate this operation directly to a boolean.
310       *
311       * @param xctxt The runtime execution context.
312       *
313       * @return The result of the operation as a boolean.
314       *
315       * @throws javax.xml.transform.TransformerException
316       */
317      public boolean bool(XPathContext xctxt)
318              throws javax.xml.transform.TransformerException
319      {
320        return (asNode(xctxt) != DTM.NULL);
321      }
322    
323    
324      /**
325       * Set if this is an iterator at the upper level of
326       * the XPath.
327       *
328       * @param b true if this location path is at the top level of the
329       *          expression.
330       * @xsl.usage advanced
331       */
332      public void setIsTopLevel(boolean b)
333      {
334        m_isTopLevel = b;
335      }
336    
337      /**
338       * Get if this is an iterator at the upper level of
339       * the XPath.
340       *
341       * @return true if this location path is at the top level of the
342       *          expression.
343       * @xsl.usage advanced
344       */
345      public boolean getIsTopLevel()
346      {
347        return m_isTopLevel;
348      }
349      
350      /**
351       * Initialize the context values for this expression
352       * after it is cloned.
353       *
354       * @param context The XPath runtime context for this
355       * transformation.
356       */
357      public void setRoot(int context, Object environment)
358      {
359    
360        m_context = context;
361        
362        XPathContext xctxt = (XPathContext)environment;
363        m_execContext = xctxt;
364        m_cdtm = xctxt.getDTM(context);
365        
366        m_currentContextNode = context; // only if top level?
367        
368        // Yech, shouldn't have to do this.  -sb
369        if(null == m_prefixResolver)
370            m_prefixResolver = xctxt.getNamespaceContext();
371            
372        m_lastFetched = DTM.NULL;
373        m_foundLast = false;
374        m_pos = 0;
375        m_length = -1;
376    
377        if (m_isTopLevel)
378          this.m_stackFrame = xctxt.getVarStack().getStackFrame();
379          
380        // reset();
381      }
382    
383      /**
384       * Set the next position index of this iterator.
385       *
386       * @param next A value greater than or equal to zero that indicates the next
387       * node position to fetch.
388       */
389      protected void setNextPosition(int next)
390      {
391        assertion(false, "setNextPosition not supported in this iterator!");
392      }
393    
394      /**
395       * Get the current position, which is one less than
396       * the next nextNode() call will retrieve.  i.e. if
397       * you call getCurrentPos() and the return is 0, the next
398       * fetch will take place at index 1.
399       *
400       * @return A value greater than or equal to zero that indicates the next
401       * node position to fetch.
402       */
403      public final int getCurrentPos()
404      {
405        return m_pos;
406      }
407    
408    
409      /**
410       * If setShouldCacheNodes(true) is called, then nodes will
411       * be cached.  They are not cached by default.
412       *
413       * @param b True if this iterator should cache nodes.
414       */
415      public void setShouldCacheNodes(boolean b)
416      {
417    
418        assertion(false, "setShouldCacheNodes not supported by this iterater!");
419      }
420      
421      /**
422       * Tells if this iterator can have nodes added to it or set via 
423       * the <code>setItem(int node, int index)</code> method.
424       * 
425       * @return True if the nodelist can be mutated.
426       */
427      public boolean isMutable()
428      {
429        return false;
430      }
431    
432      /**
433       * Set the current position in the node set.
434       *
435       * @param i Must be a valid index greater
436       * than or equal to zero and less than m_cachedNodes.size().
437       */
438      public void setCurrentPos(int i)
439      {
440            assertion(false, "setCurrentPos not supported by this iterator!");
441      }
442      
443      /**
444       * Increment the current position in the node set.
445       */
446      public void incrementCurrentPos()
447      {
448            m_pos++;
449      }
450    
451    
452      /**
453       * Get the length of the cached nodes.
454       *
455       * <p>Note: for the moment at least, this only returns
456       * the size of the nodes that have been fetched to date,
457       * it doesn't attempt to run to the end to make sure we
458       * have found everything.  This should be reviewed.</p>
459       *
460       * @return The size of the current cache list.
461       */
462      public int size()
463      {
464            assertion(false, "size() not supported by this iterator!");
465            return 0;
466      }
467    
468      /**
469       *  Returns the <code>index</code> th item in the collection. If
470       * <code>index</code> is greater than or equal to the number of nodes in
471       * the list, this returns <code>null</code> .
472       * @param index  Index into the collection.
473       * @return  The node at the <code>index</code> th position in the
474       *   <code>NodeList</code> , or <code>null</code> if that is not a valid
475       *   index.
476       */
477      public int item(int index)
478      {
479            assertion(false, "item(int index) not supported by this iterator!");
480            return 0;
481      }
482      
483      /**
484       * Sets the node at the specified index of this vector to be the
485       * specified node. The previous component at that position is discarded.
486       *
487       * <p>The index must be a value greater than or equal to 0 and less
488       * than the current size of the vector.  
489       * The iterator must be in cached mode.</p>
490       * 
491       * <p>Meant to be used for sorted iterators.</p>
492       *
493       * @param node Node to set
494       * @param index Index of where to set the node
495       */
496      public void setItem(int node, int index)
497      {
498            assertion(false, "setItem not supported by this iterator!");
499      }
500    
501      /**
502       *  The number of nodes in the list. The range of valid child node indices
503       * is 0 to <code>length-1</code> inclusive.
504       *
505       * @return The number of nodes in the list, always greater or equal to zero.
506       */
507      public int getLength()
508      {      
509        // Tell if this is being called from within a predicate.
510            boolean isPredicateTest = (this == m_execContext.getSubContextList());
511    
512        // And get how many total predicates are part of this step.
513            int predCount = getPredicateCount();
514            
515        // If we have already calculated the length, and the current predicate 
516        // is the first predicate, then return the length.  We don't cache 
517        // the anything but the length of the list to the first predicate.
518        if (-1 != m_length && isPredicateTest && m_predicateIndex < 1)
519                    return m_length;
520            
521        // I'm a bit worried about this one, since it doesn't have the 
522        // checks found above.  I suspect it's fine.  -sb
523        if (m_foundLast)
524                    return m_pos;
525                    
526        // Create a clone, and count from the current position to the end 
527        // of the list, not taking into account the current predicate and 
528        // predicates after the current one.
529        int pos = (m_predicateIndex >= 0) ? getProximityPosition() : m_pos;
530                  
531        LocPathIterator clone;
532    
533        try
534        {
535          clone = (LocPathIterator) clone();        
536        }
537        catch (CloneNotSupportedException cnse)
538        {
539          return -1;
540        }
541    
542        // We want to clip off the last predicate, but only if we are a sub 
543        // context node list, NOT if we are a context list.  See pos68 test, 
544        // also test against bug4638.
545        if (predCount > 0 && isPredicateTest)
546        {
547          // Don't call setPredicateCount, because it clones and is slower.
548          clone.m_predCount = m_predicateIndex;
549          // The line above used to be:
550          // clone.m_predCount = predCount - 1;
551          // ...which looks like a dumb bug to me. -sb
552        }
553    
554        int next;
555    
556        while (DTM.NULL != (next = clone.nextNode()))
557        {
558          pos++;
559        }
560        
561        if (isPredicateTest && m_predicateIndex < 1)
562          m_length = pos;
563        
564        return pos;
565      }
566    
567      /**
568       * Tells if this NodeSetDTM is "fresh", in other words, if
569       * the first nextNode() that is called will return the
570       * first node in the set.
571       *
572       * @return true of nextNode has not been called.
573       */
574      public boolean isFresh()
575      {
576        return (m_pos == 0);
577      }
578    
579      /**
580       *  Returns the previous node in the set and moves the position of the
581       * iterator backwards in the set.
582       * @return  The previous <code>Node</code> in the set being iterated over,
583       *   or<code>null</code> if there are no more members in that set.
584       */
585      public int previousNode()
586      {
587        throw new RuntimeException(
588          XSLMessages.createXPATHMessage(XPATHErrorResources.ER_NODESETDTM_CANNOT_ITERATE, null)); //"This NodeSetDTM can not iterate to a previous node!");
589      }
590    
591      /**
592       * This attribute determines which node types are presented via the
593       * iterator. The available set of constants is defined in the
594       * <code>NodeFilter</code> interface.
595       *
596       * <p>This is somewhat useless at this time, since it doesn't
597       * really return information that tells what this iterator will
598       * show.  It is here only to fullfill the DOM NodeIterator
599       * interface.</p>
600       *
601       * @return For now, always NodeFilter.SHOW_ALL & ~NodeFilter.SHOW_ENTITY_REFERENCE.
602       * @see org.w3c.dom.traversal.NodeIterator
603       */
604      public int getWhatToShow()
605      {
606    
607        // TODO: ??
608        return DTMFilter.SHOW_ALL & ~DTMFilter.SHOW_ENTITY_REFERENCE;
609      }
610    
611      /**
612       *  The filter used to screen nodes.  Not used at this time,
613       * this is here only to fullfill the DOM NodeIterator
614       * interface.
615       *
616       * @return Always null.
617       * @see org.w3c.dom.traversal.NodeIterator
618       */
619      public DTMFilter getFilter()
620      {
621        return null;
622      }
623    
624      /**
625       * The root node of the Iterator, as specified when it was created.
626       *
627       * @return The "root" of this iterator, which, in XPath terms,
628       * is the node context for this iterator.
629       */
630      public int getRoot()
631      {
632        return m_context;
633      }
634    
635      /**
636       *  The value of this flag determines whether the children of entity
637       * reference nodes are visible to the iterator. If false, they will be
638       * skipped over.
639       * <br> To produce a view of the document that has entity references
640       * expanded and does not expose the entity reference node itself, use the
641       * whatToShow flags to hide the entity reference node and set
642       * expandEntityReferences to true when creating the iterator. To produce
643       * a view of the document that has entity reference nodes but no entity
644       * expansion, use the whatToShow flags to show the entity reference node
645       * and set expandEntityReferences to false.
646       *
647       * @return Always true, since entity reference nodes are not
648       * visible in the XPath model.
649       */
650      public boolean getExpandEntityReferences()
651      {
652        return true;
653      }
654      
655      /** Control over whether it is OK for detach to reset the iterator. */
656      protected boolean m_allowDetach = true;
657      
658      /**
659       * Specify if it's OK for detach to release the iterator for reuse.
660       * 
661       * @param allowRelease true if it is OK for detach to release this iterator 
662       * for pooling.
663       */
664      public void allowDetachToRelease(boolean allowRelease)
665      {
666        m_allowDetach = allowRelease;
667      }
668    
669      /**
670       *  Detaches the iterator from the set which it iterated over, releasing
671       * any computational resources and placing the iterator in the INVALID
672       * state. After<code>detach</code> has been invoked, calls to
673       * <code>nextNode</code> or<code>previousNode</code> will raise the
674       * exception INVALID_STATE_ERR.
675       */
676      public void detach()
677      {    
678        if(m_allowDetach)
679        {
680          // sb: allow reusing of cached nodes when possible?
681          // m_cachedNodes = null;
682          m_execContext = null;
683          // m_prefixResolver = null;  sb: Why would this ever want to be null?
684          m_cdtm = null;
685          m_length = -1;
686          m_pos = 0;
687          m_lastFetched = DTM.NULL;
688          m_context = DTM.NULL;
689          m_currentContextNode = DTM.NULL;
690          
691          m_clones.freeInstance(this);
692        }
693      }
694      
695      /**
696       * Reset the iterator.
697       */
698      public void reset()
699      {
700            assertion(false, "This iterator can not reset!");
701      }
702    
703      /**
704       * Get a cloned Iterator that is reset to the beginning
705       * of the query.
706       *
707       * @return A cloned NodeIterator set of the start of the query.
708       *
709       * @throws CloneNotSupportedException
710       */
711      public DTMIterator cloneWithReset() throws CloneNotSupportedException
712      {
713        LocPathIterator clone;
714    //    clone = (LocPathIterator) clone();
715        clone = (LocPathIterator)m_clones.getInstanceOrThrow();
716        clone.m_execContext = m_execContext;
717        clone.m_cdtm = m_cdtm;
718        
719        clone.m_context = m_context;
720        clone.m_currentContextNode = m_currentContextNode;
721        clone.m_stackFrame = m_stackFrame;
722    
723        // clone.reset();
724    
725        return clone;
726      }
727    
728    //  /**
729    //   * Get a cloned LocPathIterator that holds the same
730    //   * position as this iterator.
731    //   *
732    //   * @return A clone of this iterator that holds the same node position.
733    //   *
734    //   * @throws CloneNotSupportedException
735    //   */
736    //  public Object clone() throws CloneNotSupportedException
737    //  {
738    //
739    //    LocPathIterator clone = (LocPathIterator) super.clone();
740    //
741    //    return clone;
742    //  }
743    
744      /**
745       *  Returns the next node in the set and advances the position of the
746       * iterator in the set. After a NodeIterator is created, the first call
747       * to nextNode() returns the first node in the set.
748       * @return  The next <code>Node</code> in the set being iterated over, or
749       *   <code>null</code> if there are no more members in that set.
750       */
751      public abstract int nextNode();
752    
753      /**
754       * Bottleneck the return of a next node, to make returns
755       * easier from nextNode().
756       *
757       * @param nextNode The next node found, may be null.
758       *
759       * @return The same node that was passed as an argument.
760       */
761      protected int returnNextNode(int nextNode)
762      {
763    
764        if (DTM.NULL != nextNode)
765        {
766          m_pos++;
767        }
768    
769        m_lastFetched = nextNode;
770    
771        if (DTM.NULL == nextNode)
772          m_foundLast = true;
773    
774        return nextNode;
775      }
776    
777      /**
778       * Return the last fetched node.  Needed to support the UnionPathIterator.
779       *
780       * @return The last fetched node, or null if the last fetch was null.
781       */
782      public int getCurrentNode()
783      {
784        return m_lastFetched;
785      }
786    
787      /**
788       * If an index is requested, NodeSetDTM will call this method
789       * to run the iterator to the index.  By default this sets
790       * m_next to the index.  If the index argument is -1, this
791       * signals that the iterator should be run to the end.
792       *
793       * @param index The index to run to, or -1 if the iterator
794       * should run to the end.
795       */
796      public void runTo(int index)
797      {
798    
799        if (m_foundLast || ((index >= 0) && (index <= getCurrentPos())))
800          return;
801    
802        int n;
803    
804        if (-1 == index)
805        {
806          while (DTM.NULL != (n = nextNode()));
807        }
808        else
809        {
810          while (DTM.NULL != (n = nextNode()))
811          {
812            if (getCurrentPos() >= index)
813              break;
814          }
815        }
816      }
817    
818      /**
819       * Tells if we've found the last node yet.
820       *
821       * @return true if the last nextNode returned null.
822       */
823      public final boolean getFoundLast()
824      {
825        return m_foundLast;
826      }
827    
828      /**
829       * The XPath execution context we are operating on.
830       *
831       * @return XPath execution context this iterator is operating on,
832       * or null if setRoot has not been called.
833       */
834      public final XPathContext getXPathContext()
835      {
836        return m_execContext;
837      }
838    
839      /**
840       * The node context for the iterator.
841       *
842       * @return The node context, same as getRoot().
843       */
844      public final int getContext()
845      {
846        return m_context;
847      }
848    
849      /**
850       * The node context from where the expression is being
851       * executed from (i.e. for current() support).
852       *
853       * @return The top-level node context of the entire expression.
854       */
855      public final int getCurrentContextNode()
856      {
857        return m_currentContextNode;
858      }
859    
860      /**
861       * Set the current context node for this iterator.
862       *
863       * @param n Must be a non-null reference to the node context.
864       */
865      public final void setCurrentContextNode(int n)
866      {
867        m_currentContextNode = n;
868      }
869      
870    //  /**
871    //   * Set the current context node for this iterator.
872    //   *
873    //   * @param n Must be a non-null reference to the node context.
874    //   */
875    //  public void setRoot(int n)
876    //  {
877    //    m_context = n;
878    //    m_cdtm = m_execContext.getDTM(n);
879    //  }
880    
881      /**
882       * Return the saved reference to the prefix resolver that
883       * was in effect when this iterator was created.
884       *
885       * @return The prefix resolver or this iterator, which may be null.
886       */
887      public final PrefixResolver getPrefixResolver()
888      {
889            if(null == m_prefixResolver)
890            {
891            m_prefixResolver = (PrefixResolver)getExpressionOwner();
892            }
893    
894        return m_prefixResolver;
895      }
896            
897    //  /**
898    //   * Get the analysis pattern built by the WalkerFactory.
899    //   *
900    //   * @return The analysis pattern built by the WalkerFactory.
901    //   */
902    //  int getAnalysis()
903    //  {
904    //    return m_analysis;
905    //  }
906    
907    //  /**
908    //   * Set the analysis pattern built by the WalkerFactory.
909    //   *
910    //   * @param a The analysis pattern built by the WalkerFactory.
911    //   */
912    //  void setAnalysis(int a)
913    //  {
914    //    m_analysis = a;
915    //  }
916    
917      /**
918       * @see org.apache.xpath.XPathVisitable#callVisitors(ExpressionOwner, XPathVisitor)
919       */
920      public void callVisitors(ExpressionOwner owner, XPathVisitor visitor)
921      {
922                    if(visitor.visitLocationPath(owner, this))
923                    {
924                            visitor.visitStep(owner, this);
925                            callPredicateVisitors(visitor);
926                    }
927      }  
928    
929      
930      //============= State Data =============
931      
932      /** 
933       * The pool for cloned iterators.  Iterators need to be cloned
934       * because the hold running state, and thus the original iterator
935       * expression from the stylesheet pool can not be used.          
936       */
937      transient protected IteratorPool m_clones = new IteratorPool(this);
938      
939      /** 
940       * The dtm of the context node.  Careful about using this... it may not 
941       * be the dtm of the current node.
942       */
943      transient protected DTM m_cdtm;
944      
945      /**
946       * The stack frame index for this iterator.
947       */
948      transient int m_stackFrame = -1;
949    
950      /**
951       * Value determined at compile time, indicates that this is an
952       * iterator at the top level of the expression, rather than inside
953       * a predicate.
954       * @serial
955       */
956      private boolean m_isTopLevel = false;
957    
958      /** The last node that was fetched, usually by nextNode. */
959      transient public int m_lastFetched = DTM.NULL;
960    
961      /**
962       * The context node for this iterator, which doesn't change through
963       * the course of the iteration.
964       */
965      transient protected int m_context = DTM.NULL;
966    
967      /**
968       * The node context from where the expression is being
969       * executed from (i.e. for current() support).  Different
970       * from m_context in that this is the context for the entire
971       * expression, rather than the context for the subexpression.
972       */
973      transient protected int m_currentContextNode = DTM.NULL;
974      
975      /**
976       * The current position of the context node.
977       */
978      transient protected int m_pos = 0;
979      
980      transient protected int m_length = -1;
981    
982      /**
983       * Fast access to the current prefix resolver.  It isn't really
984       * clear that this is needed.
985       * @serial
986       */
987      private PrefixResolver m_prefixResolver;
988    
989      /**
990       * The XPathContext reference, needed for execution of many
991       * operations.
992       */
993      transient protected XPathContext m_execContext;
994      
995      /**
996       * Returns true if all the nodes in the iteration well be returned in document 
997       * order.
998       * 
999       * @return true as a default.
1000       */
1001      public boolean isDocOrdered()
1002      {
1003        return true;
1004      }
1005      
1006      /**
1007       * Returns the axis being iterated, if it is known.
1008       * 
1009       * @return Axis.CHILD, etc., or -1 if the axis is not known or is of multiple 
1010       * types.
1011       */
1012      public int getAxis()
1013      {
1014        return -1;
1015      }
1016    
1017    
1018    //  /**
1019    //   * The analysis pattern built by the WalkerFactory.
1020    //   * TODO: Move to LocPathIterator.
1021    //   * @see org.apache.xpath.axes.WalkerFactory
1022    //   * @serial
1023    //   */
1024    //  protected int m_analysis = 0x00000000;
1025      /**
1026       * @see PredicatedNodeTest#getLastPos(XPathContext)
1027       */
1028      public int getLastPos(XPathContext xctxt)
1029      {
1030        return getLength();
1031      }
1032    
1033    }