19f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson/*
29f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Licensed to the Apache Software Foundation (ASF) under one
39f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * or more contributor license agreements. See the NOTICE file
49f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * distributed with this work for additional information
59f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * regarding copyright ownership. The ASF licenses this file
69f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * to you under the Apache License, Version 2.0 (the  "License");
79f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * you may not use this file except in compliance with the License.
89f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * You may obtain a copy of the License at
99f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson *
109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson *     http://www.apache.org/licenses/LICENSE-2.0
119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson *
129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Unless required by applicable law or agreed to in writing, software
139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * distributed under the License is distributed on an "AS IS" BASIS,
149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * See the License for the specific language governing permissions and
169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * limitations under the License.
179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */
189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson/*
199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * $Id: UnionPathIterator.java 469314 2006-10-30 23:31:59Z minchau $
209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */
219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonpackage org.apache.xpath.axes;
229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport org.apache.xml.dtm.Axis;
249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport org.apache.xml.dtm.DTM;
259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport org.apache.xml.dtm.DTMIterator;
269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport org.apache.xpath.Expression;
279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport org.apache.xpath.ExpressionOwner;
289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport org.apache.xpath.XPathVisitor;
299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport org.apache.xpath.compiler.Compiler;
309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport org.apache.xpath.compiler.OpCodes;
319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport org.apache.xpath.compiler.OpMap;
329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson/**
349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * This class extends NodeSetDTM, which implements DTMIterator,
359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * and fetches nodes one at a time in document order based on a XPath
369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * <a href="http://www.w3.org/TR/xpath#NT-UnionExpr">UnionExpr</a>.
379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * As each node is iterated via nextNode(), the node is also stored
389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * in the NodeVector, so that previousNode() can easily be done.
399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @xsl.usage advanced
409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */
419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonpublic class UnionPathIterator extends LocPathIterator
429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        implements Cloneable, DTMIterator, java.io.Serializable, PathComponent
439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson{
449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    static final long serialVersionUID = -3910351546843826781L;
459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Constructor to create an instance which you can add location paths to.
489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  public UnionPathIterator()
509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    super();
539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // m_mutable = false;
559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // m_cacheNodes = false;
569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    m_iterators = null;
579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    m_exprs = null;
589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Initialize the context values for this expression
629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * after it is cloned.
639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param context The XPath runtime context for this
659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * transformation.
669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  public void setRoot(int context, Object environment)
689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    super.setRoot(context, environment);
709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    try
729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      if (null != m_exprs)
749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      {
759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        int n = m_exprs.length;
769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        DTMIterator newIters[] = new DTMIterator[n];
779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        for (int i = 0; i < n; i++)
799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        {
809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          DTMIterator iter = m_exprs[i].asIterator(m_execContext, context);
819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          newIters[i] = iter;
829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          iter.nextNode();
839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        }
849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        m_iterators = newIters;
859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      }
869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    catch(Exception e)
889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      throw new org.apache.xml.utils.WrappedRuntimeException(e);
909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Add an iterator to the union list.
959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param expr non-null reference to a location path iterator.
979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  public void addIterator(DTMIterator expr)
999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
1009f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1019f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // Increase array size by only 1 at a time.  Fix this
1029f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // if it looks to be a problem.
1039f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if (null == m_iterators)
1049f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
1059f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      m_iterators = new DTMIterator[1];
1069f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      m_iterators[0] = expr;
1079f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
1089f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    else
1099f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
1109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      DTMIterator[] exprs = m_iterators;
1119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      int len = m_iterators.length;
1129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      m_iterators = new DTMIterator[len + 1];
1149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      System.arraycopy(exprs, 0, m_iterators, 0, len);
1169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      m_iterators[len] = expr;
1189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
1199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    expr.nextNode();
1209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if(expr instanceof Expression)
1219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    	((Expression)expr).exprSetParent(this);
1229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
1239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
1259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *  Detaches the iterator from the set which it iterated over, releasing
1269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * any computational resources and placing the iterator in the INVALID
1279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * state. After<code>detach</code> has been invoked, calls to
1289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * <code>nextNode</code> or<code>previousNode</code> will raise the
1299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * exception INVALID_STATE_ERR.
1309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
1319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  public void detach()
1329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
1339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          if(m_allowDetach && null != m_iterators){
1349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                  int n = m_iterators.length;
1359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                  for(int i = 0; i < n; i++)
1369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                  {
1379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                          m_iterators[i].detach();
1389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                  }
1399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                  m_iterators = null;
1409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          }
1419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
1429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
1459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Create a UnionPathIterator object, including creation
1469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * of location path iterators from the opcode list, and call back
1479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * into the Compiler to create predicate expressions.
1489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
1499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param compiler The Compiler which is creating
1509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * this expression.
1519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param opPos The position of this iterator in the
1529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * opcode list from the compiler.
1539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
1549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @throws javax.xml.transform.TransformerException
1559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
1569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  public UnionPathIterator(Compiler compiler, int opPos)
1579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          throws javax.xml.transform.TransformerException
1589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
1599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    super();
1619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    opPos = OpMap.getFirstChildPos(opPos);
1639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    loadLocationPaths(compiler, opPos, 0);
1659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
1669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
1689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * This will return an iterator capable of handling the union of paths given.
1699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
1709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param compiler The Compiler which is creating
1719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * this expression.
1729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param opPos The position of this iterator in the
1739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * opcode list from the compiler.
1749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
1759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @return Object that is derived from LocPathIterator.
1769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
1779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @throws javax.xml.transform.TransformerException
1789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
1799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  public static LocPathIterator createUnionIterator(Compiler compiler, int opPos)
1809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          throws javax.xml.transform.TransformerException
1819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
1829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  	// For the moment, I'm going to first create a full UnionPathIterator, and
1839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  	// then see if I can reduce it to a UnionChildIterator.  It would obviously
1849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  	// be more effecient to just test for the conditions for a UnionChildIterator,
1859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  	// and then create that directly.
1869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  	UnionPathIterator upi = new UnionPathIterator(compiler, opPos);
1879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  	int nPaths = upi.m_exprs.length;
1889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  	boolean isAllChildIterators = true;
1899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  	for(int i = 0; i < nPaths; i++)
1909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  	{
1919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  		LocPathIterator lpi = upi.m_exprs[i];
1929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  		if(lpi.getAxis() != Axis.CHILD)
1949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  		{
1959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  			isAllChildIterators = false;
1969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  			break;
1979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  		}
1989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  		else
1999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  		{
2009f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  			// check for positional predicates or position function, which won't work.
2019f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  			if(HasPositionalPredChecker.check(lpi))
2029f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  			{
2039f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  				isAllChildIterators = false;
2049f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  				break;
2059f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  			}
2069f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  		}
2079f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  	}
2089f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  	if(isAllChildIterators)
2099f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  	{
2109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  		UnionChildIterator uci = new UnionChildIterator();
2119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson	  	for(int i = 0; i < nPaths; i++)
2139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson	  	{
2149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson	  		PredicatedNodeTest lpi = upi.m_exprs[i];
2159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson	  		// I could strip the lpi down to a pure PredicatedNodeTest, but
2169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson	  		// I don't think it's worth it.  Note that the test can be used
2179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson	  		// as a static object... so it doesn't have to be cloned.
2189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson	  		uci.addNodeTest(lpi);
2199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson	  	}
2209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson	  	return uci;
2219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  	}
2239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  	else
2249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  		return upi;
2259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
2269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
2289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Get the analysis bits for this walker, as defined in the WalkerFactory.
2299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @return One of WalkerFactory#BIT_DESCENDANT, etc.
2309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
2319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  public int getAnalysisBits()
2329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
2339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    int bits = 0;
2349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if (m_exprs != null)
2369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
2379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      int n = m_exprs.length;
2389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      for (int i = 0; i < n; i++)
2409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      {
2419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      	int bit = m_exprs[i].getAnalysisBits();
2429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        bits |= bit;
2439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      }
2449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
2459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return bits;
2479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
2489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
2509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Read the object from a serialization stream.
2519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
2529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param stream Input stream to read from
2539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
2549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @throws java.io.IOException
2559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @throws javax.xml.transform.TransformerException
2569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
2579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  private void readObject(java.io.ObjectInputStream stream)
2589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          throws java.io.IOException, javax.xml.transform.TransformerException
2599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
2609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    try
2619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
2629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      stream.defaultReadObject();
2639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      m_clones =  new IteratorPool(this);
2649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
2659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    catch (ClassNotFoundException cnfe)
2669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
2679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      throw new javax.xml.transform.TransformerException(cnfe);
2689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
2699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
2709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
2729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Get a cloned LocPathIterator that holds the same
2739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * position as this iterator.
2749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
2759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @return A clone of this iterator that holds the same node position.
2769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
2779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @throws CloneNotSupportedException
2789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
2799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  public Object clone() throws CloneNotSupportedException
2809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
2819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    UnionPathIterator clone = (UnionPathIterator) super.clone();
2839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if (m_iterators != null)
2849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
2859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      int n = m_iterators.length;
2869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      clone.m_iterators = new DTMIterator[n];
2889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      for (int i = 0; i < n; i++)
2909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      {
2919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        clone.m_iterators[i] = (DTMIterator)m_iterators[i].clone();
2929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      }
2939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
2949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return clone;
2969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
2979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
3009f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Create a new location path iterator.
3019f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
3029f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param compiler The Compiler which is creating
3039f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * this expression.
3049f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param opPos The position of this iterator in the
3059f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
3069f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @return New location path iterator.
3079f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
3089f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @throws javax.xml.transform.TransformerException
3099f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
3109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  protected LocPathIterator createDTMIterator(
3119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          Compiler compiler, int opPos) throws javax.xml.transform.TransformerException
3129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
3139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    LocPathIterator lpi = (LocPathIterator)WalkerFactory.newDTMIterator(compiler, opPos,
3149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                                      (compiler.getLocationPathDepth() <= 0));
3159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return lpi;
3169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
3179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
3189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
3199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Initialize the location path iterators.  Recursive.
3209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
3219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param compiler The Compiler which is creating
3229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * this expression.
3239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param opPos The position of this iterator in the
3249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * opcode list from the compiler.
3259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param count The insert position of the iterator.
3269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
3279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @throws javax.xml.transform.TransformerException
3289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
3299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  protected void loadLocationPaths(Compiler compiler, int opPos, int count)
3309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          throws javax.xml.transform.TransformerException
3319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
3329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
3339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // TODO: Handle unwrapped FilterExpr
3349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    int steptype = compiler.getOp(opPos);
3359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
3369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if (steptype == OpCodes.OP_LOCATIONPATH)
3379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
3389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      loadLocationPaths(compiler, compiler.getNextOpPos(opPos), count + 1);
3399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
3409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      m_exprs[count] = createDTMIterator(compiler, opPos);
3419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      m_exprs[count].exprSetParent(this);
3429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
3439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    else
3449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
3459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
3469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      // Have to check for unwrapped functions, which the LocPathIterator
3479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      // doesn't handle.
3489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      switch (steptype)
3499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      {
3509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      case OpCodes.OP_VARIABLE :
3519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      case OpCodes.OP_EXTFUNCTION :
3529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      case OpCodes.OP_FUNCTION :
3539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      case OpCodes.OP_GROUP :
3549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        loadLocationPaths(compiler, compiler.getNextOpPos(opPos), count + 1);
3559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
3569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        WalkingIterator iter =
3579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          new WalkingIterator(compiler.getNamespaceContext());
3589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        iter.exprSetParent(this);
3599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
3609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        if(compiler.getLocationPathDepth() <= 0)
3619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          iter.setIsTopLevel(true);
3629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
3639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        iter.m_firstWalker = new org.apache.xpath.axes.FilterExprWalker(iter);
3649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
3659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        iter.m_firstWalker.init(compiler, opPos, steptype);
3669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
3679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        m_exprs[count] = iter;
3689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        break;
3699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      default :
3709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        m_exprs = new LocPathIterator[count];
3719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      }
3729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
3739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
3749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
3759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
3769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *  Returns the next node in the set and advances the position of the
3779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * iterator in the set. After a DTMIterator is created, the first call
3789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * to nextNode() returns the first node in the set.
3799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @return  The next <code>Node</code> in the set being iterated over, or
3809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *   <code>null</code> if there are no more members in that set.
3819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
3829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  public int nextNode()
3839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
3849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  	if(m_foundLast)
3859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  		return DTM.NULL;
3869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
3879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // Loop through the iterators getting the current fetched
3889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // node, and get the earliest occuring in document order
3899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    int earliestNode = DTM.NULL;
3909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
3919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if (null != m_iterators)
3929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
3939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      int n = m_iterators.length;
3949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      int iteratorUsed = -1;
3959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
3969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      for (int i = 0; i < n; i++)
3979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      {
3989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        int node = m_iterators[i].getCurrentNode();
3999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
4009f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        if (DTM.NULL == node)
4019f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          continue;
4029f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        else if (DTM.NULL == earliestNode)
4039f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        {
4049f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          iteratorUsed = i;
4059f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          earliestNode = node;
4069f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        }
4079f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        else
4089f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        {
4099f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          if (node == earliestNode)
4109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          {
4119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
4129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            // Found a duplicate, so skip past it.
4139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            m_iterators[i].nextNode();
4149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          }
4159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          else
4169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          {
4179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            DTM dtm = getDTM(node);
4189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
4199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            if (dtm.isNodeAfter(node, earliestNode))
4209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            {
4219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson              iteratorUsed = i;
4229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson              earliestNode = node;
4239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            }
4249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          }
4259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        }
4269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      }
4279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
4289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      if (DTM.NULL != earliestNode)
4299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      {
4309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        m_iterators[iteratorUsed].nextNode();
4319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
4329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        incrementCurrentPos();
4339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      }
4349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      else
4359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        m_foundLast = true;
4369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
4379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
4389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    m_lastFetched = earliestNode;
4399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
4409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return earliestNode;
4419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
4429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
4439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
4449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * This function is used to fixup variables from QNames to stack frame
4459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * indexes at stylesheet build time.
4469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param vars List of QNames that correspond to variables.  This list
4479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * should be searched backwards for the first qualified name that
4489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * corresponds to the variable reference qname.  The position of the
4499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * QName in the vector from the start of the vector will be its position
4509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * in the stack frame (but variables above the globalsTop value will need
4519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * to be offset to the current stack frame).
4529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
4539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  public void fixupVariables(java.util.Vector vars, int globalsSize)
4549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
4559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    for (int i = 0; i < m_exprs.length; i++)
4569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
4579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      m_exprs[i].fixupVariables(vars, globalsSize);
4589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
4599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
4609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
4619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
4629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
4639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * The location path iterators, one for each
4649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * <a href="http://www.w3.org/TR/xpath#NT-LocationPath">location
4659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * path</a> contained in the union expression.
4669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @serial
4679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
4689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  protected LocPathIterator[] m_exprs;
4699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
4709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
4719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
4729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * The location path iterators, one for each
4739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * <a href="http://www.w3.org/TR/xpath#NT-LocationPath">location
4749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * path</a> contained in the union expression.
4759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @serial
4769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
4779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  protected DTMIterator[] m_iterators;
4789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
4799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
4809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Returns the axis being iterated, if it is known.
4819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
4829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @return Axis.CHILD, etc., or -1 if the axis is not known or is of multiple
4839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * types.
4849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
4859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  public int getAxis()
4869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
4879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // Could be smarter.
4889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return -1;
4899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
4909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
4919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  class iterOwner implements ExpressionOwner
4929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
4939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  	int m_index;
4949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
4959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  	iterOwner(int index)
4969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  	{
4979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  		m_index = index;
4989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  	}
4999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
5009f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    /**
5019f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     * @see ExpressionOwner#getExpression()
5029f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     */
5039f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    public Expression getExpression()
5049f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
5059f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      return m_exprs[m_index];
5069f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
5079f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
5089f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    /**
5099f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     * @see ExpressionOwner#setExpression(Expression)
5109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     */
5119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    public void setExpression(Expression exp)
5129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
5139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
5149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    	if(!(exp instanceof LocPathIterator))
5159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    	{
5169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    		// Yuck.  Need FilterExprIter.  Or make it so m_exprs can be just
5179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    		// plain expressions?
5189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    		WalkingIterator wi = new WalkingIterator(getPrefixResolver());
5199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    		FilterExprWalker few = new FilterExprWalker(wi);
5209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    		wi.setFirstWalker(few);
5219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    		few.setInnerExpression(exp);
5229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    		wi.exprSetParent(UnionPathIterator.this);
5239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    		few.exprSetParent(wi);
5249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    		exp.exprSetParent(few);
5259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    		exp = wi;
5269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    	}
5279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    	else
5289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    		exp.exprSetParent(UnionPathIterator.this);
5299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    	m_exprs[m_index] = (LocPathIterator)exp;
5309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
5319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
5329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
5339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
5349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
5359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @see org.apache.xpath.XPathVisitable#callVisitors(ExpressionOwner, XPathVisitor)
5369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
5379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  public void callVisitors(ExpressionOwner owner, XPathVisitor visitor)
5389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
5399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  	 	if(visitor.visitUnionPath(owner, this))
5409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  	 	{
5419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  	 		if(null != m_exprs)
5429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  	 		{
5439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  	 			int n = m_exprs.length;
5449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  	 			for(int i = 0; i < n; i++)
5459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  	 			{
5469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  	 				m_exprs[i].callVisitors(new iterOwner(i), visitor);
5479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  	 			}
5489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  	 		}
5499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  	 	}
5509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
5519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
5529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    /**
5539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     * @see Expression#deepEquals(Expression)
5549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     */
5559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    public boolean deepEquals(Expression expr)
5569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
5579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      if (!super.deepEquals(expr))
5589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            return false;
5599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
5609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      UnionPathIterator upi = (UnionPathIterator) expr;
5619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
5629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      if (null != m_exprs)
5639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      {
5649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        int n = m_exprs.length;
5659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
5669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        if((null == upi.m_exprs) || (upi.m_exprs.length != n))
5679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        	return false;
5689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
5699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        for (int i = 0; i < n; i++)
5709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        {
5719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          if(!m_exprs[i].deepEquals(upi.m_exprs[i]))
5729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          	return false;
5739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        }
5749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      }
5759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      else if (null != upi.m_exprs)
5769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      {
5779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          return false;
5789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      }
5799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
5809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      return true;
5819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
5829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
5839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
5849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson}
585