You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@xalan.apache.org by sb...@locus.apache.org on 2000/12/27 23:24:18 UTC

cvs commit: xml-xalan/java/src/org/apache/xpath/axes RootWalkerMultiStep.java AttributeIterator.java AxesWalker.java ChildIterator.java ChildTestIterator.java DescendantIterator.java FilterExprWalker.java LocPathIterator.java PredicatedNodeTest.java ReverseAxesWalker.java RootWalker.java WalkerFactory.java

sboag       00/12/27 14:24:18

  Modified:    java/src/org/apache/xpath/axes AttributeIterator.java
                        AxesWalker.java ChildIterator.java
                        ChildTestIterator.java DescendantIterator.java
                        FilterExprWalker.java LocPathIterator.java
                        PredicatedNodeTest.java ReverseAxesWalker.java
                        RootWalker.java WalkerFactory.java
  Added:       java/src/org/apache/xpath/axes RootWalkerMultiStep.java
  Log:
  Optimize for "/foo/baz" patterns.  Add canTraverseOutsideSubtree support.
  
  Revision  Changes    Path
  1.5       +2 -2      xml-xalan/java/src/org/apache/xpath/axes/AttributeIterator.java
  
  Index: AttributeIterator.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xpath/axes/AttributeIterator.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- AttributeIterator.java	2000/12/21 22:32:49	1.4
  +++ AttributeIterator.java	2000/12/27 22:24:11	1.5
  @@ -87,11 +87,11 @@
      *
      * @throws javax.xml.transform.TransformerException
      */
  -  public AttributeIterator(Compiler compiler, int opPos)
  +  public AttributeIterator(Compiler compiler, int opPos, int analysis)
             throws javax.xml.transform.TransformerException
     {
   
  -    super(compiler, opPos, false);
  +    super(compiler, opPos, analysis, false);
   
       int firstStepPos = compiler.getFirstChildPos(opPos);
       int whatToShow = compiler.getWhatToShow(firstStepPos);
  
  
  
  1.17      +88 -99    xml-xalan/java/src/org/apache/xpath/axes/AxesWalker.java
  
  Index: AxesWalker.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xpath/axes/AxesWalker.java,v
  retrieving revision 1.16
  retrieving revision 1.17
  diff -u -r1.16 -r1.17
  --- AxesWalker.java	2000/12/18 08:48:20	1.16
  +++ AxesWalker.java	2000/12/27 22:24:11	1.17
  @@ -87,36 +87,7 @@
   public abstract class AxesWalker extends PredicatedNodeTest
           implements Cloneable, TreeWalker, NodeFilter
   {
  -
  -  // These are useful to enable if you want to turn diagnostics messages 
  -  // on or off temporarily from another module.
  -  //  public static boolean DEBUG = true;
  -  //  public static boolean DEBUG_WAITING = true;
  -  //  public static boolean DEBUG_TRAVERSAL = true;
  -  //  public static boolean DEBUG_LOCATED = true;
  -  //  public static boolean DEBUG_PREDICATECOUNTING = false;
     
  -  /** General static debug flag.  Setting this to false will suppress some 
  -   *  of the output messages caused by the other debug categories.  */
  -  static final boolean DEBUG = false;
  -
  -  /** If true, diagnostic messages about the waiting queue will be posted.  */
  -  static final boolean DEBUG_WAITING = false;
  -
  -  /** For diagnostic purposes, tells if we already did a subtree dump.  */
  -  static boolean m_didDumpAll = false;
  -
  -  /** If true, diagnostic messages about the tree traversal will be posted.  */
  -  static final boolean DEBUG_TRAVERSAL = false;
  -
  -  /** If true, diagnostic messages about the nodes that have 
  -   *  been 'located' will be posted.  */
  -  static final boolean DEBUG_LOCATED = false;
  -
  -  /** String passed to {@link org.w3c.dom.Node#isSupported} to see if it implements 
  -   *  a {@link org.apache.xpath.patterns.NodeTestFilter} interface. */
  -  public static final String FEATURE_NODETESTFILTER = "NodeTestFilter";
  -  
     /**
      * Construct an AxesWalker using a LocPathIterator.
      *
  @@ -254,9 +225,19 @@
     }
     
     /**
  -   * The step type of the XPath step. Does not change after the constructor.
  +   * Tell if this expression or it's subexpressions can traverse outside 
  +   * the current subtree.
  +   * 
  +   * @return true if traversal outside the context node's subtree can occur.
      */
  -  private int m_stepType;
  +   public boolean canTraverseOutsideSubtree()
  +   {
  +    if(super.canTraverseOutsideSubtree())
  +      return true;
  +    if(null != m_nextWalker)
  +      return m_nextWalker.canTraverseOutsideSubtree();
  +    return false;
  +   }
   
     /**
      * The the step type op code.
  @@ -271,12 +252,6 @@
     }
   
     /**
  -   * The arg length of the XPath step. Does not change after the constructor.
  -   * TODO: Can this be removed since it is only valuable at compile time?
  -   */
  -  private int m_argLen;
  -
  -  /**
      * Get the argument length of the location step in the opcode map.
      * TODO: Can this be removed since it is only valuable at compile time?
      *
  @@ -288,36 +263,6 @@
     }
   
     /**
  -   * The analysis pattern built by the WalkerFactory.
  -   * TODO: Move to LocPathIterator.
  -   * @see org.apache.xpath.axes.WalkerFactory
  -   */
  -  protected int m_analysis = 0x00000000;
  -
  -  /**
  -   * Get the analysis pattern built by the WalkerFactory.
  -   * TODO: Move to LocPathIterator.
  -   *
  -   * @return The analysis pattern built by the WalkerFactory.
  -   */
  -  int getAnalysis()
  -  {
  -    return m_analysis;
  -  }
  -
  -  /**
  -   * Set the analysis pattern built by the WalkerFactory.
  -   * TODO: Move to LocPathIterator.
  -   *
  -   * @param a The analysis pattern built by the WalkerFactory.
  -   */
  -  void setAnalysis(int a)
  -  {
  -    m_analysis = a;
  -  }
  -
  -
  -  /**
      * Tell if the given node is a parent of the
      * step context, or the step context node itself.
      *
  @@ -343,11 +288,6 @@
     //=============== TreeWalker Implementation ===============
   
     /**
  -   *  The root node of the TreeWalker, as specified when it was created.
  -   */
  -  transient Node m_root;
  -
  -  /**
      * The root node of the TreeWalker, as specified in setRoot(Node root).
      * Note that this may actually be below the current node.
      *
  @@ -358,9 +298,6 @@
       return m_root;
     }
   
  -  /** True if an itteration has not begun.  */
  -  boolean m_isFresh;
  -
     /**
      * Set the root node of the TreeWalker.
      * (Not part of the DOM2 TreeWalker interface).
  @@ -386,11 +323,6 @@
     }
   
     /**
  -   *  The node at which the TreeWalker is currently positioned.
  -   */
  -  transient Node m_currentNode;
  -
  -  /**
      * The node at which the TreeWalker is currently positioned.
      * <br> The value must not be null. Alterations to the DOM tree may cause
      * the current node to no longer be accepted by the TreeWalker's
  @@ -550,9 +482,6 @@
       throw new RuntimeException("previousNode not supported!");
     }
   
  -  /** The next walker in the location step chain.  */
  -  protected AxesWalker m_nextWalker;
  -
     /**
      * Set the next walker in the location step chain.
      *
  @@ -575,9 +504,6 @@
       return m_nextWalker;
     }
   
  -  /** The previous walker in the location step chain, or null.   */
  -  AxesWalker m_prevWalker;
  -
     /**
      * Set or clear the previous walker reference in the location step chain.
      *
  @@ -843,10 +769,6 @@
       return 0;
     }
   
  -  /** An estimation of the next level that this walker will traverse to.  Not 
  -   *  always accurate.  */
  -  protected int m_nextLevelAmount;
  -
     /**
      * Tell what's the next level this axes can descend to.
      *
  @@ -932,9 +854,6 @@
       return ok;
     }
   
  -  /** Fairly short lived flag to tell if we switched to a waiting walker.  */
  -  private boolean m_didSwitch = false;
  -
     /**
      * Check if any walkers need to fire before the given walker.  If they
      * do, then the given walker will be put on the waiting list, and the
  @@ -1116,9 +1035,6 @@
       return walker;
     }
   
  -  /** True if this walker has found it's last node.  */
  -  boolean m_isDone = false;
  -
     /**
      * Get the next node in document order on the axes.
      *
  @@ -1156,9 +1072,6 @@
       return next;
     }
   
  -  /** The node last returned from nextNode(). */
  -  transient Node m_prevReturned;
  -
     /**
      *  Moves the <code>TreeWalker</code> to the next visible node in document
      * order relative to the current node, and returns the new node. If the
  @@ -1400,4 +1313,80 @@
       return false;
     }
   
  +  //============= Static Data =============
  +
  +  // These are useful to enable if you want to turn diagnostics messages 
  +  // on or off temporarily from another module.
  +  //  public static boolean DEBUG = true;
  +  //  public static boolean DEBUG_WAITING = true;
  +  //  public static boolean DEBUG_TRAVERSAL = true;
  +  //  public static boolean DEBUG_LOCATED = true;
  +  //  public static boolean DEBUG_PREDICATECOUNTING = false;
  +  
  +  /** General static debug flag.  Setting this to false will suppress some 
  +   *  of the output messages caused by the other debug categories.  */
  +  static final boolean DEBUG = false;
  +
  +  /** If true, diagnostic messages about the waiting queue will be posted.  */
  +  static final boolean DEBUG_WAITING = false;
  +
  +  /** For diagnostic purposes, tells if we already did a subtree dump.  */
  +  static boolean m_didDumpAll = false;
  +
  +  /** If true, diagnostic messages about the tree traversal will be posted.  */
  +  static final boolean DEBUG_TRAVERSAL = false;
  +
  +  /** If true, diagnostic messages about the nodes that have 
  +   *  been 'located' will be posted.  */
  +  static final boolean DEBUG_LOCATED = false;
  +
  +  /** String passed to {@link org.w3c.dom.Node#isSupported} to see if it implements 
  +   *  a {@link org.apache.xpath.patterns.NodeTestFilter} interface. */
  +  public static final String FEATURE_NODETESTFILTER = "NodeTestFilter";
  +  
  +  //============= State Data =============
  +
  +  /**
  +   *  The root node of the TreeWalker, as specified when it was created.
  +   */
  +  transient Node m_root;
  +
  +  /**
  +   *  The node at which the TreeWalker is currently positioned.
  +   */
  +  transient Node m_currentNode;
  +  
  +  /** The node last returned from nextNode(). */
  +  transient Node m_prevReturned;
  +
  +  /**
  +   * The arg length of the XPath step. Does not change after the constructor.
  +   * TODO: Can this be removed since it is only valuable at compile time?
  +   */
  +  private int m_argLen;
  +  
  +  /**
  +   * The step type of the XPath step. Does not change after the constructor.
  +   */
  +  private int m_stepType;
  +    
  +  /** Fairly short lived flag to tell if we switched to a waiting walker.  */
  +  private boolean m_didSwitch = false;
  +
  +  /** True if this walker has found it's last node.  */
  +  boolean m_isDone = false;
  +
  +  /** True if an itteration has not begun.  */
  +  boolean m_isFresh;
  +
  +  /** An estimation of the next level that this walker will traverse to.  Not 
  +   *  always accurate.  */
  +  protected int m_nextLevelAmount;
  +
  +  /** The next walker in the location step chain.  */
  +  protected AxesWalker m_nextWalker;
  +  
  +  /** The previous walker in the location step chain, or null.   */
  +  AxesWalker m_prevWalker;
  +    
   }
  
  
  
  1.4       +2 -2      xml-xalan/java/src/org/apache/xpath/axes/ChildIterator.java
  
  Index: ChildIterator.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xpath/axes/ChildIterator.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- ChildIterator.java	2000/12/21 22:32:51	1.3
  +++ ChildIterator.java	2000/12/27 22:24:11	1.4
  @@ -82,10 +82,10 @@
      *
      * @throws javax.xml.transform.TransformerException
      */
  -  public ChildIterator(Compiler compiler, int opPos)
  +  public ChildIterator(Compiler compiler, int opPos, int analysis)
             throws javax.xml.transform.TransformerException
     {
  -    super(compiler, opPos, false);
  +    super(compiler, opPos, analysis, false);
     }
   
     /**
  
  
  
  1.6       +2 -2      xml-xalan/java/src/org/apache/xpath/axes/ChildTestIterator.java
  
  Index: ChildTestIterator.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xpath/axes/ChildTestIterator.java,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- ChildTestIterator.java	2000/12/21 22:32:51	1.5
  +++ ChildTestIterator.java	2000/12/27 22:24:11	1.6
  @@ -85,11 +85,11 @@
      *
      * @throws javax.xml.transform.TransformerException
      */
  -  public ChildTestIterator(Compiler compiler, int opPos)
  +  public ChildTestIterator(Compiler compiler, int opPos, int analysis)
             throws javax.xml.transform.TransformerException
     {
   
  -    super(compiler, opPos, false);
  +    super(compiler, opPos, analysis, false);
   
       int firstStepPos = compiler.getFirstChildPos(opPos);
       int whatToShow = compiler.getWhatToShow(firstStepPos);
  
  
  
  1.5       +7 -2      xml-xalan/java/src/org/apache/xpath/axes/DescendantIterator.java
  
  Index: DescendantIterator.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xpath/axes/DescendantIterator.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- DescendantIterator.java	2000/12/21 22:32:51	1.4
  +++ DescendantIterator.java	2000/12/27 22:24:11	1.5
  @@ -87,11 +87,11 @@
      *
      * @throws javax.xml.transform.TransformerException
      */
  -  public DescendantIterator(Compiler compiler, int opPos)
  +  public DescendantIterator(Compiler compiler, int opPos, int analysis)
             throws javax.xml.transform.TransformerException
     {
   
  -    super(compiler, opPos, false);
  +    super(compiler, opPos, analysis, false);
   
       int ops[] = compiler.getOpMap();
       int firstStepPos = compiler.getFirstChildPos(opPos);
  @@ -99,6 +99,11 @@
   
       if (OpCodes.FROM_DESCENDANTS_OR_SELF == stepType)
         m_orSelf = true;
  +    if (OpCodes.FROM_SELF == stepType)
  +    {
  +      m_orSelf = true;
  +      firstStepPos += 8;
  +    }
       else if(OpCodes.FROM_ROOT == stepType)
       {
         m_fromRoot = true;
  
  
  
  1.12      +1 -1      xml-xalan/java/src/org/apache/xpath/axes/FilterExprWalker.java
  
  Index: FilterExprWalker.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xpath/axes/FilterExprWalker.java,v
  retrieving revision 1.11
  retrieving revision 1.12
  diff -u -r1.11 -r1.12
  --- FilterExprWalker.java	2000/12/17 06:18:19	1.11
  +++ FilterExprWalker.java	2000/12/27 22:24:11	1.12
  @@ -209,7 +209,7 @@
   
       try
       {
  -      if (m_predicateCount > 0)
  +      if (getPredicateCount() > 0)
         {
           countProximityPosition(0);
   
  
  
  
  1.22      +151 -99   xml-xalan/java/src/org/apache/xpath/axes/LocPathIterator.java
  
  Index: LocPathIterator.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xpath/axes/LocPathIterator.java,v
  retrieving revision 1.21
  retrieving revision 1.22
  diff -u -r1.21 -r1.22
  --- LocPathIterator.java	2000/12/18 08:48:20	1.21
  +++ LocPathIterator.java	2000/12/27 22:24:11	1.22
  @@ -105,76 +105,7 @@
                      java.io.Serializable
   {
   
  -  /* The pool for cloned iterators.  Iterators need to be cloned
  -   * because the hold running state, and thus the original iterator
  -   * expression from the stylesheet pool can not be used.          */
  -
  -  // ObjectPool m_pool = new ObjectPool(this.getClass());
  -
  -  /** The last node that was fetched, usually by nextNode. */
  -  transient public Node m_lastFetched;
  -
     /**
  -   * If this iterator needs to cache nodes that are fetched, they
  -   * are stored here.
  -   */
  -  transient NodeSet m_cachedNodes;
  -
  -  /** The last used step walker in the walker list. */
  -  protected AxesWalker m_lastUsedWalker;
  -
  -  /** The head of the step walker list. */
  -  protected AxesWalker m_firstWalker;
  -
  -  /** This is true if nextNode returns null. */
  -  protected boolean m_foundLast = false;
  -
  -  /**
  -   * Quicker access to the DOM helper than going through the
  -   * XPathContext object.
  -   */
  -  transient protected DOMHelper m_dhelper;
  -
  -  /**
  -   * The context node for this iterator, which doesn't change through
  -   * the course of the iteration.
  -   */
  -  transient protected Node m_context;
  -
  -  /**
  -   * The node context from where the expression is being
  -   * executed from (i.e. for current() support).  Different
  -   * from m_context in that this is the context for the entire
  -   * expression, rather than the context for the subexpression.
  -   */
  -  transient protected Node m_currentContextNode;
  -
  -  /**
  -   * Fast access to the current prefix resolver.  It isn't really
  -   * clear that this is needed.
  -   */
  -  protected PrefixResolver m_prefixResolver;
  -
  -  /**
  -   * The XPathContext reference, needed for execution of many
  -   * operations.
  -   */
  -  transient protected XPathContext m_execContext;
  -
  -  /**
  -   * The index of the next node to be fetched.  Useful if this
  -   * is a cached iterator, and is being used as random access
  -   * NodeList.
  -   */
  -  protected int m_next = 0;
  -
  -  /**
  -   * The list of "waiting" step walkers.
  -   * @see org.apache.xpath.axes.AxesWalker
  -   */
  -  private Vector m_waiting = null;
  -
  -  /**
      * Get the waiting walker at the given index.
      *
      *
  @@ -203,34 +134,7 @@
         return m_waiting.size() - m_waitingBottom;
     }
   
  -  /** The starting point in m_waiting where the waiting step walkers are. */
  -  int m_waitingBottom = 0;
  -
  -  /**
  -   * An index to the point in the variable stack where we should
  -   * begin variable searches for this iterator.
  -   * This is -1 if m_isTopLevel is false.
  -   */
  -  int m_varStackPos = -1;
  -
     /**
  -   * An index into the variable stack where the variable context
  -   * ends, i.e. at the point we should terminate the search and
  -   * go looking for global variables.
  -   */
  -  int m_varStackContext;
  -
  -  /**
  -   * Value determined at compile time, indicates that this is an
  -   * iterator at the top level of the expression, rather than inside
  -   * a predicate.
  -   */
  -  private boolean m_isTopLevel = false;
  -
  -  /** The index of the last node in the iteration. */
  -  private int m_last = 0;
  -
  -  /**
      * Create a LocPathIterator object.
      *
      * @param nscontext The namespace context for this iterator,
  @@ -256,10 +160,10 @@
      *
      * @throws javax.xml.transform.TransformerException
      */
  -  public LocPathIterator(Compiler compiler, int opPos)
  +  public LocPathIterator(Compiler compiler, int opPos, int analysis)
             throws javax.xml.transform.TransformerException
     {
  -    this(compiler, opPos, true);
  +    this(compiler, opPos, analysis, true);
     }
   
     /**
  @@ -278,9 +182,10 @@
      * @throws javax.xml.transform.TransformerException
      */
     public LocPathIterator(
  -          Compiler compiler, int opPos, boolean shouldLoadWalkers)
  +          Compiler compiler, int opPos, int analysis, boolean shouldLoadWalkers)
               throws javax.xml.transform.TransformerException
     {
  +    m_analysis = analysis;
   
       setLocPathIterator(this);
   
  @@ -1044,4 +949,151 @@
       // System.out.println("pos: "+pos);
       return pos;
     }
  +  
  +  /**
  +   * Get the analysis pattern built by the WalkerFactory.
  +   *
  +   * @return The analysis pattern built by the WalkerFactory.
  +   */
  +  int getAnalysis()
  +  {
  +    return m_analysis;
  +  }
  +
  +  /**
  +   * Set the analysis pattern built by the WalkerFactory.
  +   *
  +   * @param a The analysis pattern built by the WalkerFactory.
  +   */
  +  void setAnalysis(int a)
  +  {
  +    m_analysis = a;
  +  }
  +  
  +  /**
  +   * Tell if this expression or it's subexpressions can traverse outside 
  +   * the current subtree.
  +   * 
  +   * @return true if traversal outside the context node's subtree can occur.
  +   */
  +   public boolean canTraverseOutsideSubtree()
  +   {
  +    if((m_analysis & WalkerFactory.BITMASK_TRAVERSES_OUTSIDE_SUBTREE) != 0)
  +    {
  +      return true;
  +    }
  +    // We have to ask subwalkers about their predicates.
  +    if(null != m_firstWalker)
  +    {
  +      if(m_firstWalker.canTraverseOutsideSubtree())
  +        return true;
  +    }
  +    return super.canTraverseOutsideSubtree();
  +   }
  +
  +  
  +  //============= State Data =============
  +  
  +  /** The starting point in m_waiting where the waiting step walkers are. */
  +  int m_waitingBottom = 0;
  +
  +  /**
  +   * An index to the point in the variable stack where we should
  +   * begin variable searches for this iterator.
  +   * This is -1 if m_isTopLevel is false.
  +   */
  +  int m_varStackPos = -1;
  +
  +  /**
  +   * An index into the variable stack where the variable context
  +   * ends, i.e. at the point we should terminate the search and
  +   * go looking for global variables.
  +   */
  +  int m_varStackContext;
  +
  +  /**
  +   * Value determined at compile time, indicates that this is an
  +   * iterator at the top level of the expression, rather than inside
  +   * a predicate.
  +   */
  +  private boolean m_isTopLevel = false;
  +
  +  /** The index of the last node in the iteration. */
  +  private int m_last = 0;
  +  
  +  /* The pool for cloned iterators.  Iterators need to be cloned
  +   * because the hold running state, and thus the original iterator
  +   * expression from the stylesheet pool can not be used.          */
  +
  +  // ObjectPool m_pool = new ObjectPool(this.getClass());
  +
  +  /** The last node that was fetched, usually by nextNode. */
  +  transient public Node m_lastFetched;
  +
  +  /**
  +   * If this iterator needs to cache nodes that are fetched, they
  +   * are stored here.
  +   */
  +  transient NodeSet m_cachedNodes;
  +
  +  /** The last used step walker in the walker list. */
  +  protected AxesWalker m_lastUsedWalker;
  +
  +  /** The head of the step walker list. */
  +  protected AxesWalker m_firstWalker;
  +
  +  /** This is true if nextNode returns null. */
  +  protected boolean m_foundLast = false;
  +
  +  /**
  +   * Quicker access to the DOM helper than going through the
  +   * XPathContext object.
  +   */
  +  transient protected DOMHelper m_dhelper;
  +
  +  /**
  +   * The context node for this iterator, which doesn't change through
  +   * the course of the iteration.
  +   */
  +  transient protected Node m_context;
  +
  +  /**
  +   * The node context from where the expression is being
  +   * executed from (i.e. for current() support).  Different
  +   * from m_context in that this is the context for the entire
  +   * expression, rather than the context for the subexpression.
  +   */
  +  transient protected Node m_currentContextNode;
  +
  +  /**
  +   * Fast access to the current prefix resolver.  It isn't really
  +   * clear that this is needed.
  +   */
  +  protected PrefixResolver m_prefixResolver;
  +
  +  /**
  +   * The XPathContext reference, needed for execution of many
  +   * operations.
  +   */
  +  transient protected XPathContext m_execContext;
  +
  +  /**
  +   * The index of the next node to be fetched.  Useful if this
  +   * is a cached iterator, and is being used as random access
  +   * NodeList.
  +   */
  +  protected int m_next = 0;
  +
  +  /**
  +   * The list of "waiting" step walkers.
  +   * @see org.apache.xpath.axes.AxesWalker
  +   */
  +  private Vector m_waiting = null;
  +  
  +  /**
  +   * The analysis pattern built by the WalkerFactory.
  +   * TODO: Move to LocPathIterator.
  +   * @see org.apache.xpath.axes.WalkerFactory
  +   */
  +  protected int m_analysis = 0x00000000;
   }
  
  
  
  1.2       +42 -15    xml-xalan/java/src/org/apache/xpath/axes/PredicatedNodeTest.java
  
  Index: PredicatedNodeTest.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xpath/axes/PredicatedNodeTest.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- PredicatedNodeTest.java	2000/12/18 08:48:20	1.1
  +++ PredicatedNodeTest.java	2000/12/27 22:24:11	1.2
  @@ -70,17 +70,33 @@
      */
     public int getPredicateCount()
     {
  -    return m_predicateCount;
  +    return (null == m_predicates) ? 0 : m_predicates.length;
     }
   
     /**
  -   * Set the number of predicates that this walker has.
  +   * Set the number of predicates that this walker has.  This does more 
  +   * that one would think, as it creates a new predicate array of the 
  +   * size of the count argument, and copies count predicates into the new 
  +   * one from the old, and then reassigns the predicates value.  All this 
  +   * to keep from having to have a predicate count value.
      *
  -   * @param count The number of predicates.
  +   * @param count The number of predicates, which must be equal or less 
  +   *               than the existing count.
      */
     public void setPredicateCount(int count)
     {
  -    m_predicateCount = count;
  +    if(count > 0)
  +    {
  +      Expression[] newPredicates = new Expression[count];
  +      for (int i = 0; i < count; i++) 
  +      {
  +        newPredicates[i] = m_predicates[i];
  +      }
  +      m_predicates = newPredicates;
  +    }
  +    else
  +      m_predicates = null;
  +    
     }
   
     /**
  @@ -99,7 +115,6 @@
       int pos = compiler.getFirstPredicateOpPos(opPos);
   
       m_predicates = compiler.getCompiledPredicates(pos);
  -    m_predicateCount = (null == m_predicates) ? 0 : m_predicates.length;
     }
   
     /**
  @@ -169,13 +184,13 @@
      */
     public void resetProximityPositions()
     {
  -
  -    if (m_predicateCount > 0)
  +    int nPredicates = getPredicateCount();
  +    if (nPredicates > 0)
       {
         if (null == m_proximityPositions)
  -        m_proximityPositions = new int[m_predicateCount];
  +        m_proximityPositions = new int[nPredicates];
   
  -      for (int i = 0; i < m_predicateCount; i++)
  +      for (int i = 0; i < nPredicates; i++)
         {
           try
           {
  @@ -250,7 +265,7 @@
   
       m_predicateIndex = 0;
   
  -    int nPredicates = m_predicateCount;
  +    int nPredicates = getPredicateCount();
       // System.out.println("nPredicates: "+nPredicates);
       if (nPredicates == 0)
         return true;
  @@ -377,7 +392,7 @@
         // System.out.println("\n::acceptNode - score: "+score.num()+"::");
         if (score != NodeTest.SCORE_NONE)
         {
  -        if (m_predicateCount > 0)
  +        if (getPredicateCount() > 0)
           {
             countProximityPosition(0);
   
  @@ -425,10 +440,22 @@
     }
     
     /**
  -   * Number of predicates (in effect).
  -   */
  -  protected int m_predicateCount;
  -  
  +   * Tell if this expression or it's subexpressions can traverse outside 
  +   * the current subtree.
  +   * 
  +   * @return true if traversal outside the context node's subtree can occur.
  +   */
  +   public boolean canTraverseOutsideSubtree()
  +   {
  +    int n = getPredicateCount();
  +    for (int i = 0; i < n; i++) 
  +    {
  +      if(getPredicate(i).canTraverseOutsideSubtree())
  +        return true;
  +    }
  +    return false;
  +   }
  +    
     /** The owning location path iterator. */
     protected LocPathIterator m_lpi;
     
  
  
  
  1.6       +2 -2      xml-xalan/java/src/org/apache/xpath/axes/ReverseAxesWalker.java
  
  Index: ReverseAxesWalker.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xpath/axes/ReverseAxesWalker.java,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- ReverseAxesWalker.java	2000/12/17 17:40:01	1.5
  +++ ReverseAxesWalker.java	2000/12/27 22:24:11	1.6
  @@ -135,7 +135,7 @@
   
           clone.setRoot(this.getRoot());
   
  -        clone.m_predicateCount = predicateIndex;
  +        clone.setPredicateCount(predicateIndex);
   
           clone.setPrevWalker(null);
           clone.setNextWalker(null);
  @@ -198,7 +198,7 @@
   
         clone.setRoot(this.getRoot());
   
  -      clone.m_predicateCount = this.m_predicateCount - 1;
  +      clone.setPredicateCount(this.getPredicateCount() - 1);
   
         clone.setPrevWalker(null);
         clone.setNextWalker(null);
  
  
  
  1.5       +6 -11     xml-xalan/java/src/org/apache/xpath/axes/RootWalker.java
  
  Index: RootWalker.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xpath/axes/RootWalker.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- RootWalker.java	2000/12/17 17:40:01	1.4
  +++ RootWalker.java	2000/12/27 22:24:11	1.5
  @@ -85,20 +85,15 @@
     }
   
     /**
  -   * Get a cloned RootWalker.
  +   *  Set the root node of the TreeWalker.
      *
  -   * @return a new RootWalker ready to be used.
  -   *
  -   * @throws CloneNotSupportedException
  +   * @param root The context node of this step.
      */
  -  public Object clone() throws CloneNotSupportedException
  -  {
  -
  -    RootWalker clone = (RootWalker) super.clone();
  -
  -    clone.m_processedRoot = false;
  +  public void setRoot(Node root)
  +  {      
   
  -    return clone;
  +    super.setRoot(root);
  +    m_processedRoot = false;
     }
   
     /**
  
  
  
  1.11      +130 -31   xml-xalan/java/src/org/apache/xpath/axes/WalkerFactory.java
  
  Index: WalkerFactory.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xpath/axes/WalkerFactory.java,v
  retrieving revision 1.10
  retrieving revision 1.11
  diff -u -r1.10 -r1.11
  --- WalkerFactory.java	2000/12/18 08:48:20	1.10
  +++ WalkerFactory.java	2000/12/27 22:24:11	1.11
  @@ -140,7 +140,7 @@
         walker = createDefaultWalker(compiler, stepOpCodePos, lpi, analysis);
   
         walker.init(compiler, stepOpCodePos, stepType);
  -      walker.setAnalysis(analysis);
  +      // walker.setAnalysis(analysis);
   
         if (null == firstWalker)
         {
  @@ -183,39 +183,43 @@
       int analysis = analyze(compiler, firstStepPos, 0);
       
       
  -    if (DEBUG_ITERATOR_CREATION)
  -      System.out.println("analysis -- newLocPathIterator: " 
  -                        + Integer.toBinaryString(analysis) + ", "
  -                         + compiler.toString());
  -
  -//    // Can't have optimized iterators at this time that have predicates.
  -//    if (BIT_PREDICATE == (analysis & BIT_PREDICATE))
  -//      return new LocPathIterator(compiler, opPos, true);
  -
  +    // Is the iteration exactly one child step?
       if ((BIT_CHILD | 0x00000001) == (analysis & (BIT_CHILD | BITS_COUNT)))
       {
  +      // Does the pattern specify *any* child with no predicate? (i.e. select="child::node()".
         if (BIT_CHILD == (analysis & BIT_NODETEST_ANY) && !(BIT_PREDICATE == (analysis & BIT_PREDICATE)))
         {
           if (DEBUG_ITERATOR_CREATION)
  -          System.out.println("ChildIterator!");
  +          System.out.println("new iterator:  ChildIterator: " 
  +                            + Integer.toBinaryString(analysis) + ", "
  +                             + compiler.toString());
   
  -        return new ChildIterator(compiler, opPos);
  +        // Use simple child iteration without any test.
  +        return new ChildIterator(compiler, opPos, analysis);
         }
         else
         {
           if (DEBUG_ITERATOR_CREATION)
  -          System.out.println("ChildTestIterator!");
  +          System.out.println("new iterator:  ChildTestIterator: " 
  +                            + Integer.toBinaryString(analysis) + ", "
  +                             + compiler.toString());
   
  -        return new ChildTestIterator(compiler, opPos);
  +        // Else use simple node test iteration with predicate test.
  +        return new ChildTestIterator(compiler, opPos, analysis);
         }
       }
  +    // Is the iteration a one-step attribute pattern (i.e. select="@foo")?
       else if ((BIT_ATTRIBUTE | 0x00000001)
                == (analysis & (BIT_ATTRIBUTE | BITS_COUNT)))
       {
         if (DEBUG_ITERATOR_CREATION)
  -        System.out.println("AttributeIterator!");
  -
  -      return new AttributeIterator(compiler, opPos);
  +        System.out.println("new iterator:  AttributeIterator: " 
  +                          + Integer.toBinaryString(analysis) + ", "
  +                           + compiler.toString());
  +
  +      // Then use a simple iteration of the attributes, with node test 
  +      // and predicate testing.
  +      return new AttributeIterator(compiler, opPos, analysis);
       }
       // Analysis of "//center":
       // bits: 1001000000001010000000000000011
  @@ -229,21 +233,36 @@
                == (analysis
                    & (BIT_DESCENDANT | BIT_DESCENDANT_OR_SELF | BITS_COUNT))) ||
               ((BIT_DESCENDANT_OR_SELF | BIT_SELF | 0x00000002)
  +             == (analysis
  +                 & (BIT_DESCENDANT_OR_SELF | BIT_SELF | BITS_COUNT))) 
  +            
  +            /* ".//center" -- 1000010000001010000000000000011 */     
  +            || ((BIT_DESCENDANT_OR_SELF | BIT_SELF | BIT_CHILD | BIT_NODETEST_ANY | 0x00000003)
                == (analysis
  -                 & (BIT_DESCENDANT_OR_SELF | BIT_SELF | BITS_COUNT))) ||
  -            ((BIT_DESCENDANT_OR_SELF | BIT_ROOT | BIT_CHILD | BIT_NODETEST_ANY | BIT_ANY_DESCENDANT_FROM_ROOT | 0x00000003)
  +              & (BIT_DESCENDANT_OR_SELF | BIT_SELF | BIT_CHILD | BIT_NODETEST_ANY | BITS_COUNT)))
  +
  +            /* "//center" -- 1001000000001010000000000000011 */
  +            || ((BIT_DESCENDANT_OR_SELF | BIT_ROOT | BIT_CHILD | BIT_NODETEST_ANY | 
  +              BIT_ANY_DESCENDANT_FROM_ROOT | 0x00000003)
                == (analysis
  -                 & (BIT_DESCENDANT_OR_SELF | BIT_ROOT | BIT_CHILD | BIT_NODETEST_ANY | BIT_ANY_DESCENDANT_FROM_ROOT | BITS_COUNT)))
  +                 & (BIT_DESCENDANT_OR_SELF | BIT_ROOT | BIT_CHILD | 
  +                    BIT_NODETEST_ANY | BIT_ANY_DESCENDANT_FROM_ROOT | BITS_COUNT)))
       )
       {
         if (DEBUG_ITERATOR_CREATION)
  -        System.out.println("DescendantIterator!");
  +        System.out.println("new iterator:  DescendantIterator: " 
  +                          + Integer.toBinaryString(analysis) + ", "
  +                           + compiler.toString());
   
  -      return new DescendantIterator(compiler, opPos);
  +      return new DescendantIterator(compiler, opPos, analysis);
       }
       else
       {
  -      return new LocPathIterator(compiler, opPos, true);
  +      if (DEBUG_ITERATOR_CREATION)
  +        System.out.println("new iterator:  LocPathIterator: " 
  +                          + Integer.toBinaryString(analysis) + ", "
  +                           + compiler.toString());
  +      return new LocPathIterator(compiler, opPos, analysis, true);
       }
     }
   
  @@ -448,25 +467,49 @@
       case OpCodes.OP_FUNCTION :
       case OpCodes.OP_GROUP :
         prevIsOneStepDown = false;
  +      if (DEBUG_WALKER_CREATION)
  +        System.out.println("new walker:  FilterExprWalker: " + analysis
  +                           + ", " + compiler.toString());
         ai = new FilterExprWalker(lpi);
         simpleInit = true;
         break;
       case OpCodes.FROM_ROOT :
  -      ai = new RootWalker(lpi);
  +      if (0 == (analysis & ~(BIT_ROOT | BIT_CHILD | BIT_ATTRIBUTE | 
  +                             BIT_NAMESPACE | BIT_PREDICATE | BITS_COUNT)))
  +      {
  +        if (DEBUG_WALKER_CREATION)
  +          System.out.println("new walker:  RootWalkerMultiStep: " + analysis
  +                             + ", " + compiler.toString());
  +                             
  +        ai = new RootWalkerMultiStep(lpi);
  +      }
  +      else
  +      {
  +        if (DEBUG_WALKER_CREATION)
  +          System.out.println("new walker:  RootWalker: " + analysis
  +                             + ", " + compiler.toString());
  +        ai = new RootWalker(lpi);
  +      }
         break;
       case OpCodes.FROM_ANCESTORS :
         prevIsOneStepDown = false;
  +      if (DEBUG_WALKER_CREATION)
  +        System.out.println("new walker:  AncestorWalker: " + analysis
  +                           + ", " + compiler.toString());
         ai = new AncestorWalker(lpi);
         break;
       case OpCodes.FROM_ANCESTORS_OR_SELF :
         prevIsOneStepDown = false;
  +      if (DEBUG_WALKER_CREATION)
  +        System.out.println("new walker:  AncestorOrSelfWalker: " + analysis
  +                           + ", " + compiler.toString());
         ai = new AncestorOrSelfWalker(lpi);
         break;
       case OpCodes.FROM_ATTRIBUTES :
         if (1 == totalNumberWalkers)
         {
           if (DEBUG_WALKER_CREATION)
  -          System.out.println("analysis -- AttributeWalkerOneStep: " + analysis
  +          System.out.println("new walker:  AttributeWalkerOneStep: " + analysis
                                + ", " + compiler.toString());
   
           // TODO: We should be able to do this as long as this is 
  @@ -476,89 +519,130 @@
         else
         {
           if (DEBUG_WALKER_CREATION)
  -          System.out.println("analysis -- AttributeWalker: " + analysis
  +          System.out.println("new walker:  AttributeWalker: " + analysis
                                + ", " + compiler.toString());
                                
           ai = new AttributeWalker(lpi);
         }
         break;
       case OpCodes.FROM_NAMESPACE :
  +      if (DEBUG_WALKER_CREATION)
  +        System.out.println("new walker:  NamespaceWalker: " + analysis
  +                           + ", " + compiler.toString());
         ai = new NamespaceWalker(lpi);
         break;
       case OpCodes.FROM_CHILDREN :
         if (1 == totalNumberWalkers)
         {
  +        // I don't think this will ever happen any more.  -sb
           if (DEBUG_WALKER_CREATION)
  -          System.out.println("analysis -- onestep child: " + analysis + ", "
  +          System.out.println("new walker:  ChildWalkerOneStep: " + analysis + ", "
                                + compiler.toString());
   
           ai = new ChildWalkerOneStep(lpi);
         }
         else
         {
  -        if (0 == (analysis & ~(BIT_CHILD | BIT_ATTRIBUTE | BIT_NAMESPACE | BIT_PREDICATE | BITS_COUNT)))
  +        if (0 == (analysis & ~(BIT_ROOT | BIT_CHILD | BIT_ATTRIBUTE | 
  +                               BIT_NAMESPACE | BIT_PREDICATE | BITS_COUNT)))
           {
             if (DEBUG_WALKER_CREATION)
  -            System.out.println("analysis -- multi-step child: " + analysis
  +            System.out.println("new walker:  ChildWalkerMultiStep: " + analysis
                                  + ", " + compiler.toString());
   
             ai = new ChildWalkerMultiStep(lpi);
           }
           else
           {
  +          if (DEBUG_WALKER_CREATION)
  +            System.out.println("new walker:  ChildWalker: " + analysis
  +                               + ", " + compiler.toString());
             ai = new ChildWalker(lpi);
           }
         }
         break;
       case OpCodes.FROM_DESCENDANTS :
         prevIsOneStepDown = false;
  +      if (DEBUG_WALKER_CREATION)
  +        System.out.println("new walker:  DescendantWalker: " + analysis
  +                           + ", " + compiler.toString());
         ai = new DescendantWalker(lpi);
         break;
       case OpCodes.FROM_DESCENDANTS_OR_SELF :
         prevIsOneStepDown = false;
  +      if (DEBUG_WALKER_CREATION)
  +        System.out.println("new walker:  DescendantOrSelfWalker: " + analysis
  +                           + ", " + compiler.toString());
         ai = new DescendantOrSelfWalker(lpi);
         break;
       case OpCodes.FROM_FOLLOWING :
         prevIsOneStepDown = false;
  +      if (DEBUG_WALKER_CREATION)
  +        System.out.println("new walker:  FollowingWalker: " + analysis
  +                           + ", " + compiler.toString());
         ai = new FollowingWalker(lpi);
         break;
       case OpCodes.FROM_FOLLOWING_SIBLINGS :
         prevIsOneStepDown = false;
  +      if (DEBUG_WALKER_CREATION)
  +        System.out.println("new walker:  FollowingSiblingWalker: " + analysis
  +                           + ", " + compiler.toString());
         ai = new FollowingSiblingWalker(lpi);
         break;
       case OpCodes.FROM_PRECEDING :
         prevIsOneStepDown = false;
  +      if (DEBUG_WALKER_CREATION)
  +        System.out.println("new walker:  PrecedingWalker: " + analysis
  +                           + ", " + compiler.toString());
         ai = new PrecedingWalker(lpi);
         break;
       case OpCodes.FROM_PRECEDING_SIBLINGS :
         prevIsOneStepDown = false;
  +      if (DEBUG_WALKER_CREATION)
  +        System.out.println("new walker:  PrecedingSiblingWalker: " + analysis
  +                           + ", " + compiler.toString());
         ai = new PrecedingSiblingWalker(lpi);
         break;
       case OpCodes.FROM_PARENT :
         prevIsOneStepDown = false;
  +      if (DEBUG_WALKER_CREATION)
  +        System.out.println("new walker:  ParentWalker: " + analysis
  +                           + ", " + compiler.toString());
         ai = new ParentWalker(lpi);
         break;
       case OpCodes.FROM_SELF :
         if (1 == totalNumberWalkers)
         {
           if (DEBUG_WALKER_CREATION)
  -          System.out.println("analysis -- SelfWalkerOneStep: " + analysis
  +          System.out.println("new walker:  SelfWalkerOneStep: " + analysis
                                + ", " + compiler.toString());
   
           ai = new SelfWalkerOneStep(lpi);
         }
         else
         {
  +        if (DEBUG_WALKER_CREATION)
  +          System.out.println("new walker:  SelfWalker: " + analysis
  +                             + ", " + compiler.toString());
           ai = new SelfWalker(lpi);
         }
         break;
       case OpCodes.MATCH_ATTRIBUTE :
  +      if (DEBUG_WALKER_CREATION)
  +        System.out.println("new walker:  AttributeWalker(MATCH_ATTRIBUTE): " + analysis
  +                           + ", " + compiler.toString());
         ai = new AttributeWalker(lpi);
         break;
       case OpCodes.MATCH_ANY_ANCESTOR :
  +      if (DEBUG_WALKER_CREATION)
  +        System.out.println("new walker:  ChildWalker(MATCH_ANY_ANCESTOR): " + analysis
  +                           + ", " + compiler.toString());
         ai = new ChildWalker(lpi);
         break;
       case OpCodes.MATCH_IMMEDIATE_ANCESTOR :
  +      if (DEBUG_WALKER_CREATION)
  +        System.out.println("new walker:  ChildWalker(MATCH_IMMEDIATE_ANCESTOR): " + analysis
  +                           + ", " + compiler.toString());
         ai = new ChildWalker(lpi);
         break;
       default :
  @@ -660,6 +744,20 @@
   
     /** Bit is on if any of the walkers contain a root step. */
     public static final int BIT_ROOT = (0x00001000 << 15);
  +  
  +  /** If any of these bits are on, the expression may likely traverse outside 
  +   *  the given subtree. */
  +  public static final int BITMASK_TRAVERSES_OUTSIDE_SUBTREE 
  +                                                   = (BIT_NAMESPACE // ??
  +                                                    | BIT_PRECEDING_SIBLING
  +                                                    | BIT_PRECEDING
  +                                                    | BIT_FOLLOWING_SIBLING
  +                                                    | BIT_FOLLOWING
  +                                                    | BIT_PARENT // except parent of attrs.
  +                                                    | BIT_ANCESTOR_OR_SELF
  +                                                    | BIT_ANCESTOR
  +                                                    | BIT_FILTER
  +                                                    | BIT_ROOT);                                                    
   
     /**
      * Bit is on if any of the walkers can go backwards in document
  @@ -675,9 +773,10 @@
      *  really only useful if the count is 1. 
      */
     public static final int BIT_NODETEST_ANY = (0x00001000 << 18);
  +  
  +  // can't go higher than 18!
   
     /** Bit is on if the expression is a match pattern. */
     public static final int BIT_MATCH_PATTERN = (0x00001000 << 19);
   
  -  // can't go higher than 19!
   }
  
  
  
  1.1                  xml-xalan/java/src/org/apache/xpath/axes/RootWalkerMultiStep.java
  
  Index: RootWalkerMultiStep.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 1999 The Apache Software Foundation.  All rights 
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer. 
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:  
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Xalan" and "Apache Software Foundation" must
   *    not be used to endorse or promote products derived from this
   *    software without prior written permission. For written 
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    nor may "Apache" appear in their name, without prior written
   *    permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation and was
   * originally based on software copyright (c) 1999, Lotus
   * Development Corporation., http://www.lotus.com.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  package org.apache.xpath.axes;
  
  import org.w3c.dom.Node;
  import org.w3c.dom.traversal.NodeFilter;
  
  import org.apache.xpath.patterns.NodeTestFilter;
  
  /**
   * This class extends ChildWalkerMultiStep to handle the root step of
   * patterns such as "/foo/baz" where the first step is the root, and the
   * rest of the steps are simple child steps.
   */
  public class RootWalkerMultiStep extends ChildWalkerMultiStep
  {
  
    /**
     * Construct an ChildWalkerMultiStep using a LocPathIterator.
     *
     * @param locPathIterator
     */
    public RootWalkerMultiStep(LocPathIterator locPathIterator)
    {
      super(locPathIterator);
    }
  
    /**
     *  Set the root node of the TreeWalker.
     *
     * @param root The context node of this step.
     */
    public void setRoot(Node root)
    {
  
      super.setRoot(root);
  
      m_processedRoot = false;
    }
  
    /**
     * Get the next node in document order on the axes.
     *
     * @return the next valid child node.
     */
    protected Node getNextNode()
    {
  
      if (m_isFresh)
        m_isFresh = false;
  
      Node current = this.getCurrentNode();
  
      if (current.isSupported(FEATURE_NODETESTFILTER, "1.0"))
        ((NodeTestFilter) current).setNodeTest(this);
  
      Node next;
  
      if (!m_processedRoot)
      {
        m_processedRoot = true;
        next = m_lpi.getDOMHelper().getRootNode(m_currentNode);
      }
      else
        next = null;
  
      if (null != next)
      {
        m_currentNode = next;
  
        // doesn't seem like we need to do this!
        if (acceptNode(next) != NodeFilter.FILTER_ACCEPT)
        {
          next = null;
        }
  
        if (null == next)
          m_currentNode = current;  // don't advance the current node.
      }
  
      if (null == next)
        this.m_isDone = true;
  
      return next;
    }
  
    /** True if the root node has been processed. */
    boolean m_processedRoot = false;
  }