Home | History | Annotate | Download | only in axes
      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: LocPathIterator.java 468655 2006-10-28 07:12:06Z minchau $
     20  */
     21 package org.apache.xpath.axes;
     22 
     23 import org.apache.xalan.res.XSLMessages;
     24 import org.apache.xml.dtm.DTM;
     25 import org.apache.xml.dtm.DTMFilter;
     26 import org.apache.xml.dtm.DTMIterator;
     27 import org.apache.xml.dtm.DTMManager;
     28 import org.apache.xml.utils.PrefixResolver;
     29 import org.apache.xpath.ExpressionOwner;
     30 import org.apache.xpath.XPathContext;
     31 import org.apache.xpath.XPathVisitor;
     32 import org.apache.xpath.compiler.Compiler;
     33 import org.apache.xpath.objects.XNodeSet;
     34 import org.apache.xpath.objects.XObject;
     35 import org.apache.xpath.res.XPATHErrorResources;
     36 
     37 /**
     38  * This class extends NodeSetDTM, which implements NodeIterator,
     39  * and fetches nodes one at a time in document order based on a XPath
     40  * <a href="http://www.w3.org/TR/xpath#NT-LocationPath>LocationPath</a>.
     41  *
     42  * <p>If setShouldCacheNodes(true) is called,
     43  * as each node is iterated via nextNode(), the node is also stored
     44  * in the NodeVector, so that previousNode() can easily be done, except in
     45  * the case where the LocPathIterator is "owned" by a UnionPathIterator,
     46  * in which case the UnionPathIterator will cache the nodes.</p>
     47  * @xsl.usage advanced
     48  */
     49 public abstract class LocPathIterator extends PredicatedNodeTest
     50         implements Cloneable, DTMIterator, java.io.Serializable, PathComponent
     51 {
     52     static final long serialVersionUID = -4602476357268405754L;
     53 
     54   /**
     55    * Create a LocPathIterator object.
     56    *
     57    */
     58   protected LocPathIterator()
     59   {
     60   }
     61 
     62 
     63   /**
     64    * Create a LocPathIterator object.
     65    *
     66    * @param nscontext The namespace context for this iterator,
     67    * should be OK if null.
     68    */
     69   protected LocPathIterator(PrefixResolver nscontext)
     70   {
     71 
     72     setLocPathIterator(this);
     73     m_prefixResolver = nscontext;
     74   }
     75 
     76   /**
     77    * Create a LocPathIterator object, including creation
     78    * of step walkers from the opcode list, and call back
     79    * into the Compiler to create predicate expressions.
     80    *
     81    * @param compiler The Compiler which is creating
     82    * this expression.
     83    * @param opPos The position of this iterator in the
     84    * opcode list from the compiler.
     85    *
     86    * @throws javax.xml.transform.TransformerException
     87    */
     88   protected LocPathIterator(Compiler compiler, int opPos, int analysis)
     89           throws javax.xml.transform.TransformerException
     90   {
     91     this(compiler, opPos, analysis, true);
     92   }
     93 
     94   /**
     95    * Create a LocPathIterator object, including creation
     96    * of step walkers from the opcode list, and call back
     97    * into the Compiler to create predicate expressions.
     98    *
     99    * @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 }
   1034