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 */
21package org.apache.xpath.axes;
22
23import org.apache.xalan.res.XSLMessages;
24import org.apache.xml.dtm.DTM;
25import org.apache.xml.dtm.DTMFilter;
26import org.apache.xml.dtm.DTMIterator;
27import org.apache.xml.dtm.DTMManager;
28import org.apache.xml.utils.PrefixResolver;
29import org.apache.xpath.ExpressionOwner;
30import org.apache.xpath.XPathContext;
31import org.apache.xpath.XPathVisitor;
32import org.apache.xpath.compiler.Compiler;
33import org.apache.xpath.objects.XNodeSet;
34import org.apache.xpath.objects.XObject;
35import 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 */
49public 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