1 /*
   2  * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
   3  * @LastModified: Nov 2017
   4  */
   5 /*
   6  * Licensed to the Apache Software Foundation (ASF) under one or more
   7  * contributor license agreements.  See the NOTICE file distributed with
   8  * this work for additional information regarding copyright ownership.
   9  * The ASF licenses this file to You under the Apache License, Version 2.0
  10  * (the "License"); you may not use this file except in compliance with
  11  * the License.  You may obtain a copy of the License at
  12  *
  13  *      http://www.apache.org/licenses/LICENSE-2.0
  14  *
  15  * Unless required by applicable law or agreed to in writing, software
  16  * distributed under the License is distributed on an "AS IS" BASIS,
  17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  18  * See the License for the specific language governing permissions and
  19  * limitations under the License.
  20  */
  21 
  22 package com.sun.org.apache.xpath.internal.axes;
  23 
  24 import com.sun.org.apache.xalan.internal.res.XSLMessages;
  25 import com.sun.org.apache.xml.internal.dtm.DTM;
  26 import com.sun.org.apache.xml.internal.dtm.DTMFilter;
  27 import com.sun.org.apache.xml.internal.dtm.DTMIterator;
  28 import com.sun.org.apache.xml.internal.dtm.DTMManager;
  29 import com.sun.org.apache.xml.internal.utils.PrefixResolver;
  30 import com.sun.org.apache.xpath.internal.ExpressionOwner;
  31 import com.sun.org.apache.xpath.internal.XPathContext;
  32 import com.sun.org.apache.xpath.internal.XPathVisitor;
  33 import com.sun.org.apache.xpath.internal.compiler.Compiler;
  34 import com.sun.org.apache.xpath.internal.objects.XNodeSet;
  35 import com.sun.org.apache.xpath.internal.objects.XObject;
  36 import com.sun.org.apache.xpath.internal.res.XPATHErrorResources;
  37 
  38 /**
  39  * This class extends NodeSetDTM, which implements NodeIterator,
  40  * and fetches nodes one at a time in document order based on a XPath
  41  * <a href="http://www.w3.org/TR/xpath#NT-LocationPath>LocationPath</a>.
  42  *
  43  * <p>If setShouldCacheNodes(true) is called,
  44  * as each node is iterated via nextNode(), the node is also stored
  45  * in the NodeVector, so that previousNode() can easily be done, except in
  46  * the case where the LocPathIterator is "owned" by a UnionPathIterator,
  47  * in which case the UnionPathIterator will cache the nodes.</p>
  48  * @xsl.usage advanced

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