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/18 09:48:23 UTC

cvs commit: xml-xalan/java/src/org/apache/xpath/axes PredicatedNodeTest.java AttributeIterator.java AxesWalker.java ChildTestIterator.java ChildWalkerMultiStep.java DescendantIterator.java LocPathIterator.java PrecedingWalker.java WalkerFactory.java

sboag       00/12/18 00:48:23

  Modified:    java/src/org/apache/xpath/axes AttributeIterator.java
                        AxesWalker.java ChildTestIterator.java
                        ChildWalkerMultiStep.java DescendantIterator.java
                        LocPathIterator.java PrecedingWalker.java
                        WalkerFactory.java
  Added:       java/src/org/apache/xpath/axes PredicatedNodeTest.java
  Log:
  Add new PredicatedNodeTest base class for both the LocPathIterator
  and the AxesWalker.  This helps break up AxesWalker a bit, and
  allows optimized location path iterators to have predicates.
  Adapted optimized iterators to this new scheme.
  Also fixed bad bit test for creating childWalkerMultiStep, which
  may have been the source of the performance degragation reported.
  Also set the waiting list in LocPathIterator to null by default.
  Also made it so that, for AxesWalker#cloneDeep, don't pass a
  vector in (and don't create one in the first place) if the waiting
  list is null.  Also fixed childWalkerMultiStep so that it can be built
  for as long as the steps are down pointing and one level traversing.
  
  Revision  Changes    Path
  1.3       +23 -19    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.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- AttributeIterator.java	2000/12/16 17:16:25	1.2
  +++ AttributeIterator.java	2000/12/18 08:48:20	1.3
  @@ -58,6 +58,7 @@
   
   import javax.xml.transform.TransformerException;
   
  +import org.apache.xpath.XPathContext;
   import org.apache.xpath.compiler.Compiler;
   import org.apache.xpath.patterns.NodeTest;
   import org.apache.xpath.objects.XObject;
  @@ -92,20 +93,19 @@
   
       super(compiler, opPos, false);
   
  -    m_nodeTest = new NodeTest();
  -
       int firstStepPos = compiler.getFirstChildPos(opPos);
       int whatToShow = compiler.getWhatToShow(firstStepPos);
   
       if ((0 == (whatToShow
                  & (NodeFilter.SHOW_ATTRIBUTE | NodeFilter.SHOW_ELEMENT
                     | NodeFilter.SHOW_PROCESSING_INSTRUCTION))) || (whatToShow == NodeFilter.SHOW_ALL))
  -      m_nodeTest.initNodeTest(whatToShow);
  +      initNodeTest(whatToShow);
       else
       {
  -      m_nodeTest.initNodeTest(whatToShow, compiler.getStepNS(firstStepPos),
  +      initNodeTest(whatToShow, compiler.getStepNS(firstStepPos),
                                 compiler.getStepLocalName(firstStepPos));
       }
  +    initPredicateInfo(compiler, firstStepPos);
     }
     
     /**
  @@ -136,6 +136,8 @@
       AttributeIterator clone = (AttributeIterator) super.cloneWithReset();
   
       clone.m_attrListPos = 0;
  +    
  +    clone.resetProximityPositions();
   
       return clone;
     }
  @@ -197,6 +199,7 @@
       if (null == m_attributeList)
       {
         initAttrList();
  +      resetProximityPositions();
       }
   
       Node next;
  @@ -209,19 +212,10 @@
   
         if (null != next)
         {
  -        try
  -        {
  -          XObject score = m_nodeTest.execute(m_execContext, next);
  -
  -          if (NodeTest.SCORE_NONE == score)
  -            continue;
  -          else
  -            break;
  -        }
  -        catch (TransformerException te)
  -        {
  -          throw new org.apache.xml.utils.WrappedRuntimeException(te);
  -        }
  +        if(NodeFilter.FILTER_ACCEPT == acceptNode(next))
  +          break;
  +        else
  +          continue;
         }
         else
           break;
  @@ -244,9 +238,19 @@
         return null;
       }
     }
  +  
  +  /**
  +   * Get the index of the last node that can be itterated to.
  +   *
  +   * @param xctxt XPath runtime context.
  +   *
  +   * @return the index of the last node that can be itterated to.
  +   */
  +  public int getLastPos(XPathContext xctxt)
  +  {
  +    return m_nAttrs;
  +  }
   
  -  /** The NodeTest for this iterator. */
  -  private NodeTest m_nodeTest;
   
     /** The attribute list for the given context. */
     transient private NamedNodeMap m_attributeList;
  
  
  
  1.16      +55 -409   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.15
  retrieving revision 1.16
  diff -u -r1.15 -r1.16
  --- AxesWalker.java	2000/12/17 17:40:00	1.15
  +++ AxesWalker.java	2000/12/18 08:48:20	1.16
  @@ -61,17 +61,17 @@
   
   // Xalan imports
   import org.apache.xpath.axes.LocPathIterator;
  -import org.apache.xpath.XPath;
  -import org.apache.xpath.XPathContext;
  +import org.apache.xml.utils.PrefixResolver;
   import org.apache.xpath.axes.SubContextList;
  -import org.apache.xpath.compiler.OpCodes;
   import org.apache.xpath.compiler.Compiler;
  -import org.apache.xpath.objects.XObject;
  +import org.apache.xpath.compiler.OpCodes;
   import org.apache.xpath.DOMHelper;
   import org.apache.xpath.Expression;
  -import org.apache.xpath.patterns.NodeTest;
  +import org.apache.xpath.objects.XObject;
   import org.apache.xpath.patterns.NodeTestFilter;
  -import org.apache.xml.utils.PrefixResolver;
  +import org.apache.xpath.patterns.NodeTest;
  +import org.apache.xpath.XPathContext;
  +import org.apache.xpath.XPath;
   
   // DOM2 imports
   import org.w3c.dom.Node;
  @@ -84,10 +84,12 @@
    * Serves as common interface for axes Walkers, and stores common
    * state variables.
    */
  -public abstract class AxesWalker extends NodeTest
  -        implements Cloneable, TreeWalker, NodeFilter, SubContextList
  +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;
  @@ -111,36 +113,9 @@
      *  been 'located' will be posted.  */
     static final boolean DEBUG_LOCATED = false;
   
  -  /** If true, diagnostic messages about predicate execution will be posted.  */
  -  static final boolean DEBUG_PREDICATECOUNTING = 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";
  -
  -  /** The owning location path iterator. */
  -  protected LocPathIterator m_lpi;
  -
  -  /**
  -   * Get the owning location path iterator.
  -   *
  -   * @return the owning location path iterator, which should not be null.
  -   */
  -  public LocPathIterator getLocPathIterator()
  -  {
  -    return m_lpi;
  -  }
  -
  -  /**
  -   * Set the location path iterator owner for this walker.  Besides 
  -   * initialization, this function is called during cloning operations.
  -   *
  -   * @param li non-null reference to the owning location path iterator.
  -   */
  -  public void setLocPathIterator(LocPathIterator li)
  -  {
  -    m_lpi = li;
  -  }
     
     /**
      * Construct an AxesWalker using a LocPathIterator.
  @@ -149,7 +124,7 @@
      */
     public AxesWalker(LocPathIterator locPathIterator)
     {
  -    m_lpi = locPathIterator;
  +    super( locPathIterator );
     }
   
     /**
  @@ -199,16 +174,6 @@
       
       AxesWalker clone = (AxesWalker) super.clone();
   
  -    if ((null != this.m_proximityPositions)
  -            && (this.m_proximityPositions == clone.m_proximityPositions))
  -    {
  -      clone.m_proximityPositions = new int[this.m_proximityPositions.length];
  -
  -      System.arraycopy(this.m_proximityPositions, 0,
  -                       clone.m_proximityPositions, 0,
  -                       this.m_proximityPositions.length);
  -    }
  -
       //clone.setCurrentNode(clone.m_root);
   
       // clone.m_isFresh = true;
  @@ -237,12 +202,30 @@
         return clone;
       clone = (AxesWalker)this.clone();
       clone.setLocPathIterator(cloneOwner);
  -    cloneList.addElement(this);
  -    cloneList.addElement(clone);
  +    if(null != cloneList)
  +    {
  +      cloneList.addElement(this);
  +      cloneList.addElement(clone);
  +    }
  +    
  +    if(m_lpi.m_lastUsedWalker == this)
  +      cloneOwner.m_lastUsedWalker = clone;
  +      
       if(null != m_nextWalker)
         clone.m_nextWalker = m_nextWalker.cloneDeep(cloneOwner, cloneList);
  -    if(null != m_prevWalker)
  -      clone.m_prevWalker = m_prevWalker.cloneDeep(cloneOwner, cloneList);
  +      
  +    // If you don't check for the cloneList here, you'll go into an 
  +    // recursive infinate loop.  
  +    if(null != cloneList)
  +    {
  +      if(null != m_prevWalker)
  +        clone.m_prevWalker = m_prevWalker.cloneDeep(cloneOwner, cloneList);
  +    }
  +    else
  +    {
  +      if(null != m_nextWalker)
  +        clone.m_nextWalker.m_prevWalker = clone;
  +    }
       return clone;
     }
     
  @@ -250,19 +233,22 @@
      * Find a clone that corresponds to the key argument.
      * 
      * @param key The original AxesWalker for which there may be a clone.
  -   * @param cloneList non-null vector of sources in odd elements, and the 
  -   *                  corresponding clones in even vectors.
  +   * @param cloneList vector of sources in odd elements, and the 
  +   *                  corresponding clones in even vectors, may be null.
      * 
      * @return A clone that corresponds to the key, or null if key not found.
      */
     static AxesWalker findClone(AxesWalker key, Vector cloneList)
     {
  -    // First, look for clone on list.
  -    int n = cloneList.size();
  -    for (int i = 0; i < n; i+=2) 
  +    if(null != cloneList)
       {
  -      if(key == cloneList.elementAt(i))
  -        return (AxesWalker)cloneList.elementAt(i+1);
  +      // First, look for clone on list.
  +      int n = cloneList.size();
  +      for (int i = 0; i < n; i+=2) 
  +      {
  +        if(key == cloneList.elementAt(i))
  +          return (AxesWalker)cloneList.elementAt(i+1);
  +      }
       }
       return null;    
     }
  @@ -330,276 +316,8 @@
       m_analysis = a;
     }
   
  -  /**
  -   * An array of counts that correspond to the number
  -   * of predicates the step contains.
  -   */
  -  protected int[] m_proximityPositions;
  -
  -  /**
  -   * Get the current sub-context position.
  -   *
  -   * @return The node position of this walker in the sub-context node list.
  -   */
  -  public int getProximityPosition()
  -  {
  -
  -    // System.out.println("getProximityPosition - m_predicateIndex: "+m_predicateIndex);
  -    return getProximityPosition(m_predicateIndex);
  -  }
  -
  -  /**
  -   * Get the current sub-context position.
  -   *
  -   * @param xctxt The XPath runtime context.
  -   *
  -   * @return The node position of this walker in the sub-context node list.
  -   */
  -  public int getProximityPosition(XPathContext xctxt)
  -  {
  -    return getProximityPosition();
  -  }
  -
  -  /**
  -   * Get the current sub-context position.
  -   *
  -   * @param predicateIndex The index of the predicate where the proximity 
  -   *                       should be taken from.
  -   *
  -   * @return The node position of this walker in the sub-context node list.
  -   */
  -  protected int getProximityPosition(int predicateIndex)
  -  {
  -    return (predicateIndex >= 0) ? m_proximityPositions[predicateIndex] : 0;
  -  }
  -
  -  /**
  -   * Reset the proximity positions counts.
  -   *
  -   * @throws javax.xml.transform.TransformerException
  -   */
  -  public void resetProximityPositions() throws javax.xml.transform.TransformerException
  -  {
  -
  -    if (m_predicateCount > 0)
  -    {
  -      if (null == m_proximityPositions)
  -        m_proximityPositions = new int[m_predicateCount];
  -
  -      for (int i = 0; i < m_predicateCount; i++)
  -      {
  -        initProximityPosition(i);
  -      }
  -    }
  -  }
   
     /**
  -   * Init the proximity position to zero for a forward axes.
  -   *
  -   * @param i The index into the m_proximityPositions array.
  -   *
  -   * @throws javax.xml.transform.TransformerException
  -   */
  -  public void initProximityPosition(int i) throws javax.xml.transform.TransformerException
  -  {
  -    m_proximityPositions[i] = 0;
  -  }
  -
  -  /**
  -   * Count forward one proximity position.
  -   *
  -   * @param i The index into the m_proximityPositions array, where the increment 
  -   *          will occur.
  -   */
  -  protected void countProximityPosition(int i)
  -  {
  -    if (i < m_proximityPositions.length)
  -      m_proximityPositions[i]++;
  -  }
  -
  -  /**
  -   * Tells if this is a reverse axes.
  -   *
  -   * @return false, unless a derived class overrides.
  -   */
  -  public boolean isReverseAxes()
  -  {
  -    return false;
  -  }
  -
  -  /**
  -   * Which predicate we are executing.
  -   */
  -  int m_predicateIndex = -1;
  -
  -  /**
  -   * Get which predicate is executing.
  -   *
  -   * @return The current predicate index, or -1 if no predicate is executing.
  -   */
  -  public int getPredicateIndex()
  -  {
  -    return m_predicateIndex;
  -  }
  -
  -  /**
  -   * Process the predicates.
  -   *
  -   * @param context The current context node.
  -   * @param xctxt The XPath runtime context.
  -   *
  -   * @return the result of executing the predicate expressions.
  -   *
  -   * @throws javax.xml.transform.TransformerException
  -   */
  -  boolean executePredicates(Node context, XPathContext xctxt)
  -          throws javax.xml.transform.TransformerException
  -  {
  -
  -    m_predicateIndex = 0;
  -
  -    int nPredicates = m_predicateCount;
  -    // System.out.println("nPredicates: "+nPredicates);
  -    if (nPredicates == 0)
  -      return true;
  -
  -    PrefixResolver savedResolver = xctxt.getNamespaceContext();
  -
  -    try
  -    {
  -      xctxt.pushSubContextList(this);
  -      xctxt.setNamespaceContext(m_lpi.getPrefixResolver());
  -      xctxt.pushCurrentNode(context);
  -
  -      for (int i = 0; i < nPredicates; i++)
  -      {
  -        // System.out.println("Executing predicate expression - waiting count: "+m_lpi.getWaitingCount());
  -        int savedWaitingBottom = m_lpi.m_waitingBottom;
  -        m_lpi.m_waitingBottom = m_lpi.getWaitingCount();
  -        XObject pred;
  -        try
  -        {
  -          pred = m_predicates[i].execute(xctxt);
  -        }
  -        finally
  -        {
  -          m_lpi.m_waitingBottom = savedWaitingBottom;
  -        }
  -        // System.out.println("\nBack from executing predicate expression - waiting count: "+m_lpi.getWaitingCount());
  -        // System.out.println("pred.getType(): "+pred.getType());
  -        if (XObject.CLASS_NUMBER == pred.getType())
  -        {
  -          if (DEBUG_PREDICATECOUNTING)
  -          {
  -            System.out.flush();
  -            System.out.println("\n===== start predicate count ========");
  -            System.out.println("m_predicateIndex: " + m_predicateIndex);
  -            // System.out.println("getProximityPosition(m_predicateIndex): "
  -            //                   + getProximityPosition(m_predicateIndex));
  -            System.out.println("pred.num(): " + pred.num());
  -            System.out.println("waiting count: "+m_lpi.getWaitingCount());
  -          }
  -
  -          int proxPos = this.getProximityPosition(m_predicateIndex);
  -          if (proxPos != (int) pred.num())
  -          {
  -            if (DEBUG_PREDICATECOUNTING)
  -            {
  -              System.out.println("\nnode context: "+nodeToString(context));
  -              System.out.println("index predicate is false: "+proxPos);
  -              System.out.println("waiting count: "+m_lpi.getWaitingCount());
  -              System.out.println("\n===== end predicate count ========");
  -            }
  -            return false;
  -          }
  -          else if (DEBUG_PREDICATECOUNTING)
  -          {
  -            System.out.println("\nnode context: "+nodeToString(context));
  -            System.out.println("index predicate is true: "+proxPos);
  -            System.out.println("waiting count: "+m_lpi.getWaitingCount());
  -            System.out.println("\n===== end predicate count ========");
  -          }
  -        }
  -        else if (!pred.bool())
  -          return false;
  -
  -        countProximityPosition(++m_predicateIndex);
  -      }
  -    }
  -    finally
  -    {
  -      xctxt.popCurrentNode();
  -      xctxt.setNamespaceContext(savedResolver);
  -      xctxt.popSubContextList();
  -    }
  -
  -    m_predicateIndex = -1;
  -
  -    return true;
  -  }
  -
  -  /**
  -   * Number of predicates (in effect).
  -   */
  -  int m_predicateCount;
  -
  -  /**
  -   * Get the number of predicates that this walker has.
  -   *
  -   * @return the number of predicates that this walker has.
  -   */
  -  public int getPredicateCount()
  -  {
  -    return m_predicateCount;
  -  }
  -
  -  /**
  -   * Set the number of predicates that this walker has.
  -   *
  -   * @param count The number of predicates.
  -   */
  -  public void setPredicateCount(int count)
  -  {
  -    m_predicateCount = count;
  -  }
  -
  -  /**
  -   * Init predicate info.
  -   *
  -   * @param compiler The Compiler object that has information about this 
  -   *                 walker in the op map.
  -   * @param opPos The op code position of this location step.
  -   *
  -   * @throws javax.xml.transform.TransformerException
  -   */
  -  private void initPredicateInfo(Compiler compiler, int opPos)
  -          throws javax.xml.transform.TransformerException
  -  {
  -
  -    int pos = compiler.getFirstPredicateOpPos(opPos);
  -
  -    m_predicates = compiler.getCompiledPredicates(pos);
  -    m_predicateCount = (null == m_predicates) ? 0 : m_predicates.length;
  -  }
  -
  -  /** The list of predicate expressions. Is static and does not need 
  -   *  to be deep cloned. */
  -  private Expression[] m_predicates;
  -
  -  /**
  -   * Get a predicate expression at the given index.
  -   *
  -   *
  -   * @param index Index of the predicate.
  -   *
  -   * @return A predicate expression.
  -   */
  -  Expression getPredicate(int index)
  -  {
  -    return m_predicates[index];
  -  }
  -
  -  /**
      * Tell if the given node is a parent of the
      * step context, or the step context node itself.
      *
  @@ -653,6 +371,7 @@
     {
   
       m_isFresh = true;
  +    m_isDone = false;
       m_root = root;
       m_currentNode = root;
       m_prevReturned = null;
  @@ -663,16 +382,7 @@
           "\n !!!! Error! Setting the root of a walker to null!!!");
       }
   
  -    try
  -    {
  -      resetProximityPositions();
  -    }
  -    catch (javax.xml.transform.TransformerException se)
  -    {
  -
  -      // TODO: Fix this...
  -      throw new RuntimeException(se.getMessage());
  -    }
  +    resetProximityPositions();
     }
   
     /**
  @@ -936,28 +646,6 @@
     }
   
     /**
  -   * Diagnostics.
  -   *
  -   * @param n Node to give diagnostic information about, or null.
  -   *
  -   * @return Informative string about the argument.
  -   */
  -  protected String nodeToString(Node n)
  -  {
  -
  -    try
  -    {
  -      return (null != n)
  -             ? n.getNodeName() + "{" + ((org.apache.xalan.stree.Child) n).getUid() + "}"
  -             : "null";
  -    }
  -    catch (ClassCastException cce)
  -    {
  -      return (null != n) ? n.getNodeName() : "null";
  -    }
  -  }
  -
  -  /**
      * This is simply a way to bottle-neck the return of the next node, for 
      * diagnostic purposes.
      *
  @@ -1135,7 +823,7 @@
   
         for (int i = m_lpi.m_waitingBottom; i < nWaiting; i++)
         {
  -        AxesWalker ws = (AxesWalker) m_lpi.m_waiting.elementAt(i);
  +        AxesWalker ws = (AxesWalker) m_lpi.getWaiting(i);
   
           printDebug("[" + ws.toString() + " WAITING... ]");
         }
  @@ -1265,7 +953,7 @@
   
       for (int i = m_lpi.m_waitingBottom; i < nWaiting; i++)
       {
  -      AxesWalker ws = (AxesWalker) m_lpi.m_waiting.elementAt(i);
  +      AxesWalker ws = (AxesWalker) m_lpi.getWaiting(i);
         AxesWalker prevStepWalker = ws.m_prevWalker;
   
         if (null != prevStepWalker)
  @@ -1321,7 +1009,7 @@
   
       for (int i = m_lpi.m_waitingBottom; i < nWaiting; i++)
       {
  -      AxesWalker ws = (AxesWalker) m_lpi.m_waiting.elementAt(i);
  +      AxesWalker ws = (AxesWalker) m_lpi.getWaiting(i);
   
         if (first == null)
           first = ws;
  @@ -1360,7 +1048,7 @@
   
       for (int i = m_lpi.m_waitingBottom; i < nWaiting; i++)
       {
  -      AxesWalker ws = (AxesWalker) m_lpi.m_waiting.elementAt(i);
  +      AxesWalker ws = (AxesWalker) m_lpi.getWaiting(i);
   
         if (ws == walker)
           return true;
  @@ -1701,57 +1389,15 @@
       // System.out.println("pos: "+pos);
       return pos;
     }
  -
  -  //=============== NodeFilter Implementation ===============
  -
  +  
     /**
  -   *  Test whether a specified node is visible in the logical view of a
  -   * TreeWalker or NodeIterator. This function will be called by the
  -   * implementation of TreeWalker and NodeIterator; it is not intended to
  -   * be called directly from user code.
  -   * @param n  The node to check to see if it passes the filter or not.
  -   * @return  a constant to determine whether the node is accepted,
  -   *   rejected, or skipped, as defined  above .
  +   * Tell if this is a special type of walker compatible with ChildWalkerMultiStep.
  +   * 
  +   * @return true this is a special type of walker compatible with ChildWalkerMultiStep.
      */
  -  public short acceptNode(Node n)
  +  protected boolean isFastWalker()
     {
  -
  -    XPathContext xctxt = m_lpi.getXPathContext();
  -
  -    try
  -    {
  -      xctxt.pushCurrentNode(n);
  -
  -      XObject score = execute(xctxt);
  -
  -      if(DEBUG)
  -        System.out.println("\n::acceptNode - score: "+score.num()+"::");
  -      if (score != NodeTest.SCORE_NONE)
  -      {
  -        if (m_predicateCount > 0)
  -        {
  -          countProximityPosition(0);
  -
  -          if (!executePredicates(n, xctxt))
  -            return NodeFilter.FILTER_SKIP;
  -        }
  -
  -        return NodeFilter.FILTER_ACCEPT;
  -      }
  -    }
  -    catch (javax.xml.transform.TransformerException se)
  -    {
  -
  -      // TODO: Fix this.
  -      throw new RuntimeException(se.getMessage());
  -    }
  -    finally
  -    {
  -      xctxt.popCurrentNode();
  -    }
  -
  -    return NodeFilter.FILTER_SKIP;
  +    return false;
     }
   
  -  //============= End NodeFilter Implementation =============
   }
  
  
  
  1.4       +31 -20    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.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- ChildTestIterator.java	2000/12/13 21:54:43	1.3
  +++ ChildTestIterator.java	2000/12/18 08:48:20	1.4
  @@ -65,6 +65,7 @@
   import org.w3c.dom.Node;
   import org.w3c.dom.DOMException;
   import org.w3c.dom.traversal.NodeFilter;
  +import org.w3c.dom.traversal.NodeIterator;
   
   /**
    * <meta name="usage" content="advanced"/>
  @@ -75,9 +76,6 @@
   public class ChildTestIterator extends LocPathIterator
   {
   
  -  /** The NodeTest for this iterator. */
  -  NodeTest m_nodeTest;
  -
     /**
      * Create a ChildTestIterator object.
      *
  @@ -93,22 +91,39 @@
   
       super(compiler, opPos, false);
   
  -    m_nodeTest = new NodeTest();
  -
       int firstStepPos = compiler.getFirstChildPos(opPos);
       int whatToShow = compiler.getWhatToShow(firstStepPos);
   
       if ((0 == (whatToShow
                  & (NodeFilter.SHOW_ATTRIBUTE | NodeFilter.SHOW_ELEMENT
                     | NodeFilter.SHOW_PROCESSING_INSTRUCTION))) || (whatToShow == NodeFilter.SHOW_ALL))
  -      m_nodeTest.initNodeTest(whatToShow);
  +      initNodeTest(whatToShow);
       else
       {
  -      m_nodeTest.initNodeTest(whatToShow, compiler.getStepNS(firstStepPos),
  +      initNodeTest(whatToShow, compiler.getStepNS(firstStepPos),
                                 compiler.getStepLocalName(firstStepPos));
       }
  +    initPredicateInfo(compiler, firstStepPos);
     }
  +  
  +  /**
  +   *  Get a cloned Iterator that is reset to the beginning
  +   *  of the query.
  +   * 
  +   *  @return A cloned NodeIterator set of the start of the query.
  +   * 
  +   *  @throws CloneNotSupportedException
  +   */
  +  public NodeIterator cloneWithReset() throws CloneNotSupportedException
  +  {
  +
  +    ChildTestIterator clone = (ChildTestIterator) super.cloneWithReset();
   
  +    clone.resetProximityPositions();
  +
  +    return clone;
  +  }
  +
     /**
      *  Returns the next node in the set and advances the position of the
      * iterator in the set. After a NodeIterator is created, the first call
  @@ -138,6 +153,11 @@
   
       if (m_foundLast)
         return null;
  +      
  +    if(null == m_lastFetched)
  +    {
  +      resetProximityPositions();
  +    }
   
       Node next;
   
  @@ -149,19 +169,10 @@
   
         if (null != next)
         {
  -        try
  -        {
  -          XObject score = m_nodeTest.execute(m_execContext, next);
  -
  -          if (NodeTest.SCORE_NONE == score)
  -            continue;
  -          else
  -            break;
  -        }
  -        catch (TransformerException te)
  -        {
  -          throw new org.apache.xml.utils.WrappedRuntimeException(te);
  -        }
  +        if(NodeFilter.FILTER_ACCEPT == acceptNode(next))
  +          break;
  +        else
  +          continue;
         }
         else
           break;
  
  
  
  1.5       +36 -10    xml-xalan/java/src/org/apache/xpath/axes/ChildWalkerMultiStep.java
  
  Index: ChildWalkerMultiStep.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xpath/axes/ChildWalkerMultiStep.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- ChildWalkerMultiStep.java	2000/12/17 17:40:00	1.4
  +++ ChildWalkerMultiStep.java	2000/12/18 08:48:20	1.5
  @@ -63,8 +63,7 @@
   
   /**
    * <meta name="usage" content="advanced"/>
  - * Class ChildWalkerMultiStep
  - * <needs-description/>
  + * A child walker multistep is created while only child steps are found.
    *
    * @author sboag@lotus.com
    */
  @@ -88,12 +87,11 @@
      */
     protected Node getNextNode()
     {
  -
       if (m_isFresh)
         m_isFresh = false;
   
       Node current = this.getCurrentNode();
  -
  +    
       if (current.isSupported(FEATURE_NODETESTFILTER, "1.0"))
         ((NodeTestFilter) current).setNodeTest(this);
   
  @@ -109,12 +107,15 @@
         {
           next = next.getNextSibling();
   
  -        if (null != next)
  -          m_currentNode = next;
  -        else
  +        if (null == next)
             break;
  +        else
  +          m_currentNode = next;
         }
  -    }
  +      
  +      if(null == next)
  +        m_currentNode = current; // don't advance the current node.
  +    }          
   
       if (null == next)
         this.m_isDone = true;
  @@ -136,10 +137,22 @@
     {
   
       AxesWalker walker = m_lpi.getLastUsedWalker();
  +    boolean fast = walker.isFastWalker();
   
       while (null != walker)
       {
  -      Node next = walker.getNextNode();
  +      Node next;
  +      if(fast)
  +      {
  +        next = walker.getNextNode();
  +      }
  +      else
  +      {
  +        next = walker.nextNode();
  +        // In this case, nextNode finished the walk, so we just return.
  +        if(null != next)
  +          return next;
  +      }
   
         if (null != next)
         {
  @@ -149,6 +162,7 @@
   
             walker.setRoot(next);
             m_lpi.setLastUsedWalker(walker);
  +          fast = walker.isFastWalker();
           }
           else
             return next;
  @@ -158,10 +172,22 @@
           walker = walker.m_prevWalker;
   
           if (null != walker)
  -          m_lpi.setLastUsedWalker(walker);
  +          fast = walker.isFastWalker();
  +        m_lpi.setLastUsedWalker(walker);
         }
       }
   
       return null;
     }
  +  
  +  /**
  +   * Tell if this is a special type of walker compatible with ChildWalkerMultiStep.
  +   * 
  +   * @return true this is a special type of walker compatible with ChildWalkerMultiStep.
  +   */
  +  protected boolean isFastWalker()
  +  {
  +    return true;
  +  }
  +
   }
  
  
  
  1.3       +25 -18    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.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- DescendantIterator.java	2000/12/16 17:16:25	1.2
  +++ DescendantIterator.java	2000/12/18 08:48:20	1.3
  @@ -108,19 +108,36 @@
       else
         m_orSelf = false;
   
  -    m_nodeTest = new NodeTest();
  -
       int whatToShow = compiler.getWhatToShow(firstStepPos);
   
       if ((0 == (whatToShow
                  & (NodeFilter.SHOW_ATTRIBUTE | NodeFilter.SHOW_ELEMENT
                     | NodeFilter.SHOW_PROCESSING_INSTRUCTION))) || (whatToShow == NodeFilter.SHOW_ALL))
  -      m_nodeTest.initNodeTest(whatToShow);
  +      initNodeTest(whatToShow);
       else
       {
  -      m_nodeTest.initNodeTest(whatToShow, compiler.getStepNS(firstStepPos),
  +      initNodeTest(whatToShow, compiler.getStepNS(firstStepPos),
                                 compiler.getStepLocalName(firstStepPos));
       }
  +    initPredicateInfo(compiler, firstStepPos);
  +  }
  +  
  +  /**
  +   *  Get a cloned Iterator that is reset to the beginning
  +   *  of the query.
  +   * 
  +   *  @return A cloned NodeIterator set of the start of the query.
  +   * 
  +   *  @throws CloneNotSupportedException
  +   */
  +  public NodeIterator cloneWithReset() throws CloneNotSupportedException
  +  {
  +
  +    DescendantIterator clone = (DescendantIterator) super.cloneWithReset();
  +
  +    clone.resetProximityPositions();
  +
  +    return clone;
     }
   
     /**
  @@ -175,6 +192,7 @@
         else
           pos = m_context;
         m_startContext = pos;
  +      resetProximityPositions();
       }
       else
       {
  @@ -191,18 +209,10 @@
       {
         if(getSelf)
         {
  -        try
  -        {
  -          XObject score = m_nodeTest.execute(m_execContext, pos);
  -          if (NodeTest.SCORE_NONE != score)
  -          {
  -            next = pos;
  -            break;
  -          }
  -        }
  -        catch (TransformerException te)
  +        if(NodeFilter.FILTER_ACCEPT == acceptNode(pos))
           {
  -          throw new org.apache.xml.utils.WrappedRuntimeException(te);
  +          next = pos;
  +          break;
           }
         }
         else
  @@ -255,9 +265,6 @@
     
     /** The top of the subtree, may not be the same as m_context if "//foo" pattern. */ 
     transient private Node m_startContext;
  -
  -  /** The NodeTest for this iterator. */
  -  private NodeTest m_nodeTest;
   
     /** True if this is a descendants-or-self axes. */
     private boolean m_orSelf;
  
  
  
  1.21      +227 -117  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.20
  retrieving revision 1.21
  diff -u -r1.20 -r1.21
  --- LocPathIterator.java	2000/12/17 17:40:01	1.20
  +++ LocPathIterator.java	2000/12/18 08:48:20	1.21
  @@ -100,112 +100,158 @@
    * the case where the LocPathIterator is "owned" by a UnionPathIterator,
    * in which case the UnionPathIterator will cache the nodes.</p>
    */
  -public class LocPathIterator extends Expression
  -  implements Cloneable, NodeIterator, 
  -  ContextNodeList, NodeList, java.io.Serializable 
  +public class LocPathIterator extends PredicatedNodeTest
  +        implements Cloneable, NodeIterator, ContextNodeList, NodeList,
  +                   java.io.Serializable
   {
   
  -  /* The pool for cloned iterators.  Iterators need to be cloned 
  -   * because the hold running state, and thus the original iterator 
  +  /* 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.   */
  +  /**
  +   * 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.      */
  +  /** The last used step walker in the walker list. */
     protected AxesWalker m_lastUsedWalker;
   
  -  /** The head of the step walker list.     */
  +  /** The head of the step walker list. */
     protected AxesWalker m_firstWalker;
   
  -  /** This is true if nextNode returns null.  */
  +  /** This is true if nextNode returns null. */
     protected boolean m_foundLast = false;
   
  -  /** Quicker access to the DOM helper than going through the  
  -   * XPathContext object.   */
  +  /**
  +   * 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.  */
  +  /**
  +   * 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 
  +  /**
  +   * 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.  */
  +  /**
  +   * 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.    */
  +  /**
  +   * 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.   */
  +  /**
  +   * 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.
  +   *
  +   *
  +   * @param i The walker index.
  +   *
  +   * @return non-null reference to an AxesWalker.
  +   */
  +  AxesWalker getWaiting(int i)
  +  {
  +    return (AxesWalker) m_waiting.elementAt(i);
  +  }
   
  -  /** The list of "waiting" step walkers.
  -   * @see org.apache.xpath.axes.AxesWalker     */
  -  Vector m_waiting = new Vector();
  -  
  +  /**
  +   * Get the number of waiters waiting in the current expression execution.
  +   * Note that this may not be the same as the total number of waiters in
  +   * the waiting list.
  +   *
  +   *
  +   * @return the number of waiters waiting in the current expression execution.
  +   */
     int getWaitingCount()
     {
  -    return m_waiting.size() - m_waitingBottom;
  +    if(null == m_waiting)
  +      return 0;
  +    else
  +      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
  +
  +  /**
  +   * 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. 
  -   **/
  +   * 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. 
  -   **/
  +  /**
  +   * 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 
  +   * 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, 
  +   * @param nscontext The namespace context for this iterator,
      * should be OK if null.
      */
     public LocPathIterator(PrefixResolver nscontext)
     {
  +
  +    setLocPathIterator(this);
  +
       this.m_prefixResolver = nscontext;
     }
   
     /**
  -   * Create a LocPathIterator object, including creation 
  -   * of step walkers from the opcode list, and call back 
  +   * Create a LocPathIterator object, including creation
  +   * of step walkers from the opcode list, and call back
      * into the Compiler to create predicate expressions.
      *
  -   * @param compiler The Compiler which is creating 
  +   * @param compiler The Compiler which is creating
      * this expression.
  -   * @param opPos The position of this iterator in the 
  +   * @param opPos The position of this iterator in the
      * opcode list from the compiler.
      *
      * @throws javax.xml.transform.TransformerException
  @@ -217,16 +263,16 @@
     }
   
     /**
  -   * Create a LocPathIterator object, including creation 
  -   * of step walkers from the opcode list, and call back 
  +   * Create a LocPathIterator object, including creation
  +   * of step walkers from the opcode list, and call back
      * into the Compiler to create predicate expressions.
  -   * 
  -   * @param compiler The Compiler which is creating 
  +   *
  +   * @param compiler The Compiler which is creating
      * this expression.
  -   * @param opPos The position of this iterator in the 
  +   * @param opPos The position of this iterator in the
      * opcode list from the compiler.
  -   * @param shouldLoadWalkers True if walkers should be 
  -   * loaded, or false if this is a derived iterator and 
  +   * @param shouldLoadWalkers True if walkers should be
  +   * loaded, or false if this is a derived iterator and
      * it doesn't wish to load child walkers.
      *
      * @throws javax.xml.transform.TransformerException
  @@ -236,6 +282,8 @@
               throws javax.xml.transform.TransformerException
     {
   
  +    setLocPathIterator(this);
  +
       int firstStepPos = compiler.getFirstChildPos(opPos);
   
       if (shouldLoadWalkers)
  @@ -247,9 +295,9 @@
     }
   
     /**
  -   * Execute this iterator, meaning create a clone that can  
  -   * store state, and initialize it for fast execution from 
  -   * the current runtime state.  When this is called, no actual 
  +   * Execute this iterator, meaning create a clone that can
  +   * store state, and initialize it for fast execution from
  +   * the current runtime state.  When this is called, no actual
      * query from the current context node is performed.
      *
      * @param xctxt The XPath execution context.
  @@ -258,11 +306,13 @@
      *
      * @throws javax.xml.transform.TransformerException
      */
  -  public XObject execute(XPathContext xctxt) throws javax.xml.transform.TransformerException
  +  public XObject execute(XPathContext xctxt)
  +          throws javax.xml.transform.TransformerException
     {
   
       try
       {
  +
         // LocPathIterator clone = (LocPathIterator) m_pool.getInstanceIfFree();
         // if (null == clone)
         LocPathIterator clone = (LocPathIterator) this.clone();
  @@ -276,22 +326,25 @@
         throw new javax.xml.transform.TransformerException(ncse);
       }
     }
  -    
  +
     /**
      * <meta name="usage" content="advanced"/>
  -   * Set if this is an iterator at the upper level of 
  +   * Set if this is an iterator at the upper level of
      * the XPath.
  +   *
  +   * @param b true if this location path is at the top level of the
  +   *          expression.
      */
     public void setIsTopLevel(boolean b)
     {
       m_isTopLevel = b;
     }
  -  
  +
     /**
  -   * Initialize the context values for this expression 
  +   * Initialize the context values for this expression
      * after it is cloned.
      *
  -   * @param execContext The XPath runtime context for this 
  +   * @param execContext The XPath runtime context for this
      * transformation.
      */
     public void initContext(XPathContext execContext)
  @@ -302,23 +355,24 @@
       this.m_execContext = execContext;
       this.m_prefixResolver = execContext.getNamespaceContext();
       this.m_dhelper = execContext.getDOMHelper();
  -    if(m_isTopLevel)
  +
  +    if (m_isTopLevel)
       {
         VariableStack vars = execContext.getVarStack();
  +
         this.m_varStackPos = vars.getSearchStartOrTop();
         this.m_varStackContext = vars.getContextPos();
       }
     }
   
     /**
  -   * Set the next position index of this iterator. 
  +   * Set the next position index of this iterator.
      *
  -   * @param next A value greater than or equal to zero that indicates the next 
  +   * @param next A value greater than or equal to zero that indicates the next
      * node position to fetch.
      */
     protected void setNextPosition(int next)
     {
  -
       m_next = next;
     }
   
  @@ -328,7 +382,7 @@
      * you call getCurrentPos() and the return is 0, the next
      * fetch will take place at index 1.
      *
  -   * @return A value greater than or equal to zero that indicates the next 
  +   * @return A value greater than or equal to zero that indicates the next
      * node position to fetch.
      */
     public final int getCurrentPos()
  @@ -337,7 +391,7 @@
     }
   
     /**
  -   * Add one to the current node index. 
  +   * Add one to the current node index.
      */
     void incrementNextPosition()
     {
  @@ -358,7 +412,7 @@
       else
         m_cachedNodes = null;
     }
  -  
  +
     /**
      * Get cached nodes.
      *
  @@ -371,8 +425,8 @@
   
     /**
      * Set the current position in the node set.
  -   * 
  -   * @param i Must be a valid index greater 
  +   *
  +   * @param i Must be a valid index greater
      * than or equal to zero and less than m_cachedNodes.size().
      */
     public void setCurrentPos(int i)
  @@ -391,10 +445,10 @@
   
     /**
      * Get the length of the cached nodes.
  -   * 
  -   * <p>Note: for the moment at least, this only returns 
  -   * the size of the nodes that have been fetched to date, 
  -   * it doesn't attempt to run to the end to make sure we 
  +   *
  +   * <p>Note: for the moment at least, this only returns
  +   * the size of the nodes that have been fetched to date,
  +   * it doesn't attempt to run to the end to make sure we
      * have found everything.  This should be reviewed.</p>
      *
      * @return The size of the current cache list.
  @@ -490,10 +544,10 @@
      * This attribute determines which node types are presented via the
      * iterator. The available set of constants is defined in the
      * <code>NodeFilter</code> interface.
  -   * 
  -   * <p>This is somewhat useless at this time, since it doesn't 
  -   * really return information that tells what this iterator will 
  -   * show.  It is here only to fullfill the DOM NodeIterator 
  +   *
  +   * <p>This is somewhat useless at this time, since it doesn't
  +   * really return information that tells what this iterator will
  +   * show.  It is here only to fullfill the DOM NodeIterator
      * interface.</p>
      *
      * @return For now, always NodeFilter.SHOW_ALL & ~NodeFilter.SHOW_ENTITY_REFERENCE.
  @@ -507,8 +561,8 @@
     }
   
     /**
  -   *  The filter used to screen nodes.  Not used at this time, 
  -   * this is here only to fullfill the DOM NodeIterator 
  +   *  The filter used to screen nodes.  Not used at this time,
  +   * this is here only to fullfill the DOM NodeIterator
      * interface.
      *
      * @return Always null.
  @@ -522,7 +576,7 @@
     /**
      * The root node of the Iterator, as specified when it was created.
      *
  -   * @return The "root" of this iterator, which, in XPath terms, 
  +   * @return The "root" of this iterator, which, in XPath terms,
      * is the node context for this iterator.
      */
     public Node getRoot()
  @@ -542,7 +596,7 @@
      * expansion, use the whatToShow flags to show the entity reference node
      * and set expandEntityReferences to false.
      *
  -   * @return Always true, since entity reference nodes are not 
  +   * @return Always true, since entity reference nodes are not
      * visible in the XPath model.
      */
     public boolean getExpandEntityReferences()
  @@ -571,7 +625,7 @@
     }
   
     /**
  -   * Get a cloned Iterator that is reset to the beginning 
  +   * Get a cloned Iterator that is reset to the beginning
      * of the query.
      *
      * @return A cloned NodeIterator set of the start of the query.
  @@ -587,9 +641,9 @@
   
       return clone;
     }
  -  
  +
     /**
  -   * Get a cloned LocPathIterator that holds the same 
  +   * Get a cloned LocPathIterator that holds the same
      * position as this iterator.
      *
      * @return A clone of this iterator that holds the same node position.
  @@ -598,35 +652,36 @@
      */
     public Object clone() throws CloneNotSupportedException
     {
  -    
  +
       LocPathIterator clone = (LocPathIterator) super.clone();
  -//    clone.m_varStackPos = this.m_varStackPos;
  -//    clone.m_varStackContext = this.m_varStackContext;
   
  +    //    clone.m_varStackPos = this.m_varStackPos;
  +    //    clone.m_varStackContext = this.m_varStackContext;
       if (null != m_firstWalker)
       {
  -      Vector clones = new Vector(); // yuck
  +      // If we have waiting walkers, we have to check for duplicates.
  +      Vector clones = (null != m_waiting) ? new Vector() : null;
  +
         clone.m_firstWalker = m_firstWalker.cloneDeep(clone, clones);
  -      
  -      if(null != m_waiting)
  +
  +      if (null != m_waiting)
         {
  -        clone.m_waiting = (Vector)m_waiting.clone(); // or is new Vector faster?
  +        clone.m_waiting = (Vector) m_waiting.clone();  // or is new Vector faster?
  +
           int n = m_waiting.size();
  -        for (int i = 0; i < n; i++) 
  +
  +        for (int i = 0; i < n; i++)
           {
  -          AxesWalker waiting = (AxesWalker)m_waiting.elementAt(i);
  +          AxesWalker waiting = (AxesWalker) m_waiting.elementAt(i);
  +
             clone.m_waiting.setElementAt(waiting.cloneDeep(clone, clones), i);
           }
         }
  -
  -      if(null != m_lastUsedWalker)
  -        clone.m_lastUsedWalker = m_lastUsedWalker.cloneDeep(clone, clones);
       }
  -             
  +
       return clone;
     }
  -  
  -  
  +
     /**
      * Reset the iterator.
      */
  @@ -645,7 +700,8 @@
         m_lastUsedWalker = m_firstWalker;
   
         m_firstWalker.setRoot(m_context);
  -      m_waiting.removeAllElements();
  +      if(null != m_waiting)
  +        m_waiting.removeAllElements();
       }
     }
   
  @@ -673,7 +729,7 @@
   
         return next;
       }
  -    
  +
       // If the variable stack position is not -1, we'll have to 
       // set our position in the variable stack, so our variable access 
       // will be correct.  Iterators that are at the top level of the 
  @@ -682,7 +738,7 @@
       // may be much later than top-level iterators.  
       // m_varStackPos is set in initContext, which is called 
       // from the execute method.
  -    if(-1 == m_varStackPos)
  +    if (-1 == m_varStackPos)
       {
         if (null == m_firstWalker.getRoot())
         {
  @@ -691,17 +747,19 @@
   
           m_lastUsedWalker = m_firstWalker;
         }
  +
         return returnNextNode(m_firstWalker.nextNode());
       }
       else
       {
         VariableStack vars = m_execContext.getVarStack();
  -      
  +
         // These three statements need to be combined into one operation.
         int savedStart = vars.getSearchStart();
  +
         vars.setSearchStart(m_varStackPos);
         vars.pushContextPosition(m_varStackContext);
  -      
  +
         if (null == m_firstWalker.getRoot())
         {
           this.setNextPosition(0);
  @@ -711,7 +769,7 @@
         }
   
         Node n = returnNextNode(m_firstWalker.nextNode());
  -      
  +
         // These two statements need to be combined into one operation.
         vars.setSearchStart(savedStart);
         vars.popContextPosition();
  @@ -763,7 +821,7 @@
      * m_next to the index.  If the index argument is -1, this
      * signals that the iterator should be run to the end.
      *
  -   * @param index The index to run to, or -1 if the iterator 
  +   * @param index The index to run to, or -1 if the iterator
      * should run to the end.
      */
     public void runTo(int index)
  @@ -792,7 +850,7 @@
      * <meta name="usage" content="advanced"/>
      * Get the head of the walker list.
      *
  -   * @return The head of the walker list, or null 
  +   * @return The head of the walker list, or null
      * if this iterator does not implement walkers.
      */
     public final AxesWalker getFirstWalker()
  @@ -826,14 +884,19 @@
      * <meta name="usage" content="advanced"/>
      * Add a walker to the waiting list.
      *
  -   * @param walker A walker that is waiting for 
  -   * other step walkers to complete, before it can 
  +   * @param walker A walker that is waiting for
  +   * other step walkers to complete, before it can
      * continue.
  -   * 
  +   *
      * @see org.apache.xpath.axes.AxesWalker
      */
     public final void addToWaitList(AxesWalker walker)
     {
  +    if (null == m_waiting)
  +    {
  +      m_waiting = new Vector();
  +    }
  +    
       m_waiting.addElement(walker);
     }
   
  @@ -842,12 +905,13 @@
      * Remove a walker from the waiting list.
      *
      * @param walker A walker that is no longer waiting.
  -   * 
  +   *
      * @see org.apache.xpath.axes.AxesWalker
      */
     public final void removeFromWaitList(AxesWalker walker)
     {
  -    m_waiting.removeElement(walker);
  +    if(null != m_waiting) // defensive check.
  +      m_waiting.removeElement(walker);
     }
   
     /**
  @@ -874,7 +938,7 @@
     /**
      * The DOM helper for the given context;
      *
  -   * @return The DOMHelper that should be used, 
  +   * @return The DOMHelper that should be used,
      * or null if initContext has not been called.
      */
     public final DOMHelper getDOMHelper()
  @@ -923,15 +987,61 @@
     {
       return m_prefixResolver;
     }
  -  
  +
  +  /**
  +   * Get the index of the last node in the iteration.
  +   *
  +   *
  +   * @return the index of the last node in the iteration.
  +   */
     public int getLast()
     {
       return m_last;
     }
  -  
  +
  +  /**
  +   * Set the index of the last node in the iteration.
  +   *
  +   *
  +   * @param last the index of the last node in the iteration.
  +   */
     public void setLast(int last)
     {
       m_last = last;
     }
   
  +  /**
  +   * Get the index of the last node that can be itterated to.
  +   * This probably will need to be overridded by derived classes.
  +   *
  +   * @param xctxt XPath runtime context.
  +   *
  +   * @return the index of the last node that can be itterated to.
  +   */
  +  public int getLastPos(XPathContext xctxt)
  +  {
  +    int pos = getProximityPosition();
  +    LocPathIterator clone;
  +
  +    try
  +    {
  +      clone = (LocPathIterator) clone();
  +    }
  +    catch (CloneNotSupportedException cnse)
  +    {
  +      return -1;
  +    }
  +
  +    clone.setPredicateCount(clone.getPredicateCount() - 1);
  +
  +    Node next;
  +
  +    while (null != (next = clone.nextNode()))
  +    {
  +      pos++;
  +    }
  +
  +    // System.out.println("pos: "+pos);
  +    return pos;
  +  }
   }
  
  
  
  1.7       +2 -11     xml-xalan/java/src/org/apache/xpath/axes/PrecedingWalker.java
  
  Index: PrecedingWalker.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xpath/axes/PrecedingWalker.java,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- PrecedingWalker.java	2000/12/17 17:40:01	1.6
  +++ PrecedingWalker.java	2000/12/18 08:48:20	1.7
  @@ -102,16 +102,7 @@
       m_currentNode = m_doc;
       m_nextLevelAmount = root.hasChildNodes() ? 1 : 0;
   
  -    try
  -    {
  -      super.resetProximityPositions();
  -    }
  -    catch (javax.xml.transform.TransformerException se)
  -    {
  -
  -      // TODO: Fix this...
  -      throw new RuntimeException(se.getMessage());
  -    }
  +    super.resetProximityPositions();
     }
   
     /**
  @@ -119,7 +110,7 @@
      *
      * @throws javax.xml.transform.TransformerException
      */
  -  public void resetProximityPositions() throws javax.xml.transform.TransformerException{}
  +  public void resetProximityPositions(){}
   
     /**
      *  Moves to and returns the closest visible ancestor node of the current
  
  
  
  1.10      +25 -5     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.9
  retrieving revision 1.10
  diff -u -r1.9 -r1.10
  --- WalkerFactory.java	2000/12/15 02:30:39	1.9
  +++ WalkerFactory.java	2000/12/18 08:48:20	1.10
  @@ -188,13 +188,13 @@
                           + 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);
  +//    // Can't have optimized iterators at this time that have predicates.
  +//    if (BIT_PREDICATE == (analysis & BIT_PREDICATE))
  +//      return new LocPathIterator(compiler, opPos, true);
   
       if ((BIT_CHILD | 0x00000001) == (analysis & (BIT_CHILD | BITS_COUNT)))
       {
  -      if (BIT_CHILD == (analysis & BIT_NODETEST_ANY))
  +      if (BIT_CHILD == (analysis & BIT_NODETEST_ANY) && !(BIT_PREDICATE == (analysis & BIT_PREDICATE)))
         {
           if (DEBUG_ITERATOR_CREATION)
             System.out.println("ChildIterator!");
  @@ -439,6 +439,7 @@
       */
       boolean simpleInit = false;
       int totalNumberWalkers = (analysis & BITS_COUNT);
  +    boolean prevIsOneStepDown = true;
   
       switch (stepType)
       {
  @@ -446,6 +447,7 @@
       case OpCodes.OP_EXTFUNCTION :
       case OpCodes.OP_FUNCTION :
       case OpCodes.OP_GROUP :
  +      prevIsOneStepDown = false;
         ai = new FilterExprWalker(lpi);
         simpleInit = true;
         break;
  @@ -453,21 +455,32 @@
         ai = new RootWalker(lpi);
         break;
       case OpCodes.FROM_ANCESTORS :
  +      prevIsOneStepDown = false;
         ai = new AncestorWalker(lpi);
         break;
       case OpCodes.FROM_ANCESTORS_OR_SELF :
  +      prevIsOneStepDown = false;
         ai = new AncestorOrSelfWalker(lpi);
         break;
       case OpCodes.FROM_ATTRIBUTES :
         if (1 == totalNumberWalkers)
         {
  +        if (DEBUG_WALKER_CREATION)
  +          System.out.println("analysis -- AttributeWalkerOneStep: " + analysis
  +                             + ", " + compiler.toString());
   
           // TODO: We should be able to do this as long as this is 
           // the last step.
           ai = new AttributeWalkerOneStep(lpi);
         }
         else
  +      {
  +        if (DEBUG_WALKER_CREATION)
  +          System.out.println("analysis -- AttributeWalker: " + analysis
  +                             + ", " + compiler.toString());
  +                             
           ai = new AttributeWalker(lpi);
  +      }
         break;
       case OpCodes.FROM_NAMESPACE :
         ai = new NamespaceWalker(lpi);
  @@ -483,7 +496,7 @@
         }
         else
         {
  -        if (0 == ~(BIT_CHILD | BIT_PREDICATE | BITS_COUNT))
  +        if (0 == (analysis & ~(BIT_CHILD | BIT_ATTRIBUTE | BIT_NAMESPACE | BIT_PREDICATE | BITS_COUNT)))
           {
             if (DEBUG_WALKER_CREATION)
               System.out.println("analysis -- multi-step child: " + analysis
  @@ -498,24 +511,31 @@
         }
         break;
       case OpCodes.FROM_DESCENDANTS :
  +      prevIsOneStepDown = false;
         ai = new DescendantWalker(lpi);
         break;
       case OpCodes.FROM_DESCENDANTS_OR_SELF :
  +      prevIsOneStepDown = false;
         ai = new DescendantOrSelfWalker(lpi);
         break;
       case OpCodes.FROM_FOLLOWING :
  +      prevIsOneStepDown = false;
         ai = new FollowingWalker(lpi);
         break;
       case OpCodes.FROM_FOLLOWING_SIBLINGS :
  +      prevIsOneStepDown = false;
         ai = new FollowingSiblingWalker(lpi);
         break;
       case OpCodes.FROM_PRECEDING :
  +      prevIsOneStepDown = false;
         ai = new PrecedingWalker(lpi);
         break;
       case OpCodes.FROM_PRECEDING_SIBLINGS :
  +      prevIsOneStepDown = false;
         ai = new PrecedingSiblingWalker(lpi);
         break;
       case OpCodes.FROM_PARENT :
  +      prevIsOneStepDown = false;
         ai = new ParentWalker(lpi);
         break;
       case OpCodes.FROM_SELF :
  
  
  
  1.1                  xml-xalan/java/src/org/apache/xpath/axes/PredicatedNodeTest.java
  
  Index: PredicatedNodeTest.java
  ===================================================================
  package org.apache.xpath.axes;
  
  import org.apache.xpath.patterns.NodeTest;
  import org.apache.xpath.compiler.Compiler;
  import org.apache.xpath.XPathContext;
  import org.apache.xpath.objects.XObject;
  import org.apache.xpath.Expression;
  import org.apache.xpath.axes.SubContextList;
  
  import org.apache.xml.utils.PrefixResolver;
  
  import org.w3c.dom.Node;
  import org.w3c.dom.traversal.NodeFilter;
  
  
  public abstract class PredicatedNodeTest extends NodeTest implements SubContextList
  {
  
    /**
     * Construct an AxesWalker using a LocPathIterator.
     *
     * @param locPathIterator non-null reference to the parent iterator.
     */
    public PredicatedNodeTest(LocPathIterator locPathIterator)
    {
      m_lpi = locPathIterator;
    }
    
    /**
     * Construct an AxesWalker.  The location path iterator will have to be set
     * before use.
     */
    public PredicatedNodeTest()
    {
    }
    
    /**
     * Get a cloned AxesWalker.
     *
     * @return A new AxesWalker that can be used without mutating this one.
     *
     * @throws CloneNotSupportedException
     */
    public Object clone() throws CloneNotSupportedException
    {
      // Do not access the location path itterator during this operation!
      
      PredicatedNodeTest clone = (PredicatedNodeTest) super.clone();
  
      if ((null != this.m_proximityPositions)
              && (this.m_proximityPositions == clone.m_proximityPositions))
      {
        clone.m_proximityPositions = new int[this.m_proximityPositions.length];
  
        System.arraycopy(this.m_proximityPositions, 0,
                         clone.m_proximityPositions, 0,
                         this.m_proximityPositions.length);
      }
      
      if(clone.m_lpi == this)
        clone.m_lpi = (LocPathIterator)clone;
  
      return clone;
    }
  
    /**
     * Get the number of predicates that this walker has.
     *
     * @return the number of predicates that this walker has.
     */
    public int getPredicateCount()
    {
      return m_predicateCount;
    }
  
    /**
     * Set the number of predicates that this walker has.
     *
     * @param count The number of predicates.
     */
    public void setPredicateCount(int count)
    {
      m_predicateCount = count;
    }
  
    /**
     * Init predicate info.
     *
     * @param compiler The Compiler object that has information about this 
     *                 walker in the op map.
     * @param opPos The op code position of this location step.
     *
     * @throws javax.xml.transform.TransformerException
     */
    protected void initPredicateInfo(Compiler compiler, int opPos)
            throws javax.xml.transform.TransformerException
    {
  
      int pos = compiler.getFirstPredicateOpPos(opPos);
  
      m_predicates = compiler.getCompiledPredicates(pos);
      m_predicateCount = (null == m_predicates) ? 0 : m_predicates.length;
    }
  
    /**
     * Get a predicate expression at the given index.
     *
     *
     * @param index Index of the predicate.
     *
     * @return A predicate expression.
     */
    Expression getPredicate(int index)
    {
      return m_predicates[index];
    }
    
    /**
     * Get the current sub-context position.
     *
     * @return The node position of this walker in the sub-context node list.
     */
    public int getProximityPosition()
    {
  
      // System.out.println("getProximityPosition - m_predicateIndex: "+m_predicateIndex);
      return getProximityPosition(m_predicateIndex);
    }
  
    /**
     * Get the current sub-context position.
     *
     * @param xctxt The XPath runtime context.
     *
     * @return The node position of this walker in the sub-context node list.
     */
    public int getProximityPosition(XPathContext xctxt)
    {
      return getProximityPosition();
    }
    
    /**
     * Get the index of the last node that can be itterated to.
     *
     *
     * @param xctxt XPath runtime context.
     *
     * @return the index of the last node that can be itterated to.
     */
    public abstract int getLastPos(XPathContext xctxt);
  
    /**
     * Get the current sub-context position.
     *
     * @param predicateIndex The index of the predicate where the proximity 
     *                       should be taken from.
     *
     * @return The node position of this walker in the sub-context node list.
     */
    protected int getProximityPosition(int predicateIndex)
    {
      return (predicateIndex >= 0) ? m_proximityPositions[predicateIndex] : 0;
    }
  
    /**
     * Reset the proximity positions counts.
     *
     * @throws javax.xml.transform.TransformerException
     */
    public void resetProximityPositions()
    {
  
      if (m_predicateCount > 0)
      {
        if (null == m_proximityPositions)
          m_proximityPositions = new int[m_predicateCount];
  
        for (int i = 0; i < m_predicateCount; i++)
        {
          try
          {
            initProximityPosition(i);
          }
          catch(Exception e)
          {
            // TODO: Fix this...
            throw new org.apache.xml.utils.WrappedRuntimeException(e);
          }
        }
      }
    }
  
    /**
     * Init the proximity position to zero for a forward axes.
     *
     * @param i The index into the m_proximityPositions array.
     *
     * @throws javax.xml.transform.TransformerException
     */
    public void initProximityPosition(int i) throws javax.xml.transform.TransformerException
    {
      m_proximityPositions[i] = 0;
    }
  
    /**
     * Count forward one proximity position.
     *
     * @param i The index into the m_proximityPositions array, where the increment 
     *          will occur.
     */
    protected void countProximityPosition(int i)
    {
      if (i < m_proximityPositions.length)
        m_proximityPositions[i]++;
    }
  
    /**
     * Tells if this is a reverse axes.
     *
     * @return false, unless a derived class overrides.
     */
    public boolean isReverseAxes()
    {
      return false;
    }
  
    /**
     * Get which predicate is executing.
     *
     * @return The current predicate index, or -1 if no predicate is executing.
     */
    public int getPredicateIndex()
    {
      return m_predicateIndex;
    }
  
    /**
     * Process the predicates.
     *
     * @param context The current context node.
     * @param xctxt The XPath runtime context.
     *
     * @return the result of executing the predicate expressions.
     *
     * @throws javax.xml.transform.TransformerException
     */
    boolean executePredicates(Node context, XPathContext xctxt)
            throws javax.xml.transform.TransformerException
    {
  
      m_predicateIndex = 0;
  
      int nPredicates = m_predicateCount;
      // System.out.println("nPredicates: "+nPredicates);
      if (nPredicates == 0)
        return true;
  
      PrefixResolver savedResolver = xctxt.getNamespaceContext();
  
      try
      {
        xctxt.pushSubContextList(this);
        xctxt.setNamespaceContext(m_lpi.getPrefixResolver());
        xctxt.pushCurrentNode(context);
  
        for (int i = 0; i < nPredicates; i++)
        {
          // System.out.println("Executing predicate expression - waiting count: "+m_lpi.getWaitingCount());
          int savedWaitingBottom = m_lpi.m_waitingBottom;
          m_lpi.m_waitingBottom = m_lpi.getWaitingCount();
          XObject pred;
          try
          {
            pred = m_predicates[i].execute(xctxt);
          }
          finally
          {
            m_lpi.m_waitingBottom = savedWaitingBottom;
          }
          // System.out.println("\nBack from executing predicate expression - waiting count: "+m_lpi.getWaitingCount());
          // System.out.println("pred.getType(): "+pred.getType());
          if (XObject.CLASS_NUMBER == pred.getType())
          {
            if (DEBUG_PREDICATECOUNTING)
            {
              System.out.flush();
              System.out.println("\n===== start predicate count ========");
              System.out.println("m_predicateIndex: " + m_predicateIndex);
              // System.out.println("getProximityPosition(m_predicateIndex): "
              //                   + getProximityPosition(m_predicateIndex));
              System.out.println("pred.num(): " + pred.num());
              System.out.println("waiting count: "+m_lpi.getWaitingCount());
            }
  
            int proxPos = this.getProximityPosition(m_predicateIndex);
            if (proxPos != (int) pred.num())
            {
              if (DEBUG_PREDICATECOUNTING)
              {
                System.out.println("\nnode context: "+nodeToString(context));
                System.out.println("index predicate is false: "+proxPos);
                System.out.println("waiting count: "+m_lpi.getWaitingCount());
                System.out.println("\n===== end predicate count ========");
              }
              return false;
            }
            else if (DEBUG_PREDICATECOUNTING)
            {
              System.out.println("\nnode context: "+nodeToString(context));
              System.out.println("index predicate is true: "+proxPos);
              System.out.println("waiting count: "+m_lpi.getWaitingCount());
              System.out.println("\n===== end predicate count ========");
            }
          }
          else if (!pred.bool())
            return false;
  
          countProximityPosition(++m_predicateIndex);
        }
      }
      finally
      {
        xctxt.popCurrentNode();
        xctxt.setNamespaceContext(savedResolver);
        xctxt.popSubContextList();
      }
  
      m_predicateIndex = -1;
  
      return true;
    }
    
    /**
     * Diagnostics.
     *
     * @param n Node to give diagnostic information about, or null.
     *
     * @return Informative string about the argument.
     */
    protected String nodeToString(Node n)
    {
  
      try
      {
        return (null != n)
               ? n.getNodeName() + "{" + ((org.apache.xalan.stree.Child) n).getUid() + "}"
               : "null";
      }
      catch (ClassCastException cce)
      {
        return (null != n) ? n.getNodeName() : "null";
      }
    }
    
    //=============== NodeFilter Implementation ===============
  
    /**
     *  Test whether a specified node is visible in the logical view of a
     * TreeWalker or NodeIterator. This function will be called by the
     * implementation of TreeWalker and NodeIterator; it is not intended to
     * be called directly from user code.
     * @param n  The node to check to see if it passes the filter or not.
     * @return  a constant to determine whether the node is accepted,
     *   rejected, or skipped, as defined  above .
     */
    public short acceptNode(Node n)
    {
  
      XPathContext xctxt = m_lpi.getXPathContext();
  
      try
      {
        xctxt.pushCurrentNode(n);
  
        XObject score = execute(xctxt, n);
  
        // System.out.println("\n::acceptNode - score: "+score.num()+"::");
        if (score != NodeTest.SCORE_NONE)
        {
          if (m_predicateCount > 0)
          {
            countProximityPosition(0);
  
            if (!executePredicates(n, xctxt))
              return NodeFilter.FILTER_SKIP;
          }
  
          return NodeFilter.FILTER_ACCEPT;
        }
      }
      catch (javax.xml.transform.TransformerException se)
      {
  
        // TODO: Fix this.
        throw new RuntimeException(se.getMessage());
      }
      finally
      {
        xctxt.popCurrentNode();
      }
  
      return NodeFilter.FILTER_SKIP;
    }
  
    
    /**
     * Get the owning location path iterator.
     *
     * @return the owning location path iterator, which should not be null.
     */
    public LocPathIterator getLocPathIterator()
    {
      return m_lpi;
    }
  
    /**
     * Set the location path iterator owner for this walker.  Besides 
     * initialization, this function is called during cloning operations.
     *
     * @param li non-null reference to the owning location path iterator.
     */
    public void setLocPathIterator(LocPathIterator li)
    {
      m_lpi = li;
    }
    
    /**
     * Number of predicates (in effect).
     */
    protected int m_predicateCount;
    
    /** The owning location path iterator. */
    protected LocPathIterator m_lpi;
    
    /**
     * Which predicate we are executing.
     */
    int m_predicateIndex = -1;
    
    /** The list of predicate expressions. Is static and does not need 
     *  to be deep cloned. */
    private Expression[] m_predicates;
  
    /**
     * An array of counts that correspond to the number
     * of predicates the step contains.
     */
    protected int[] m_proximityPositions;
  
    /** If true, diagnostic messages about predicate execution will be posted.  */
    static final boolean DEBUG_PREDICATECOUNTING = false;
  
  }