14c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson/*
24c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * Licensed to the Apache Software Foundation (ASF) under one
34c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * or more contributor license agreements. See the NOTICE file
44c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * distributed with this work for additional information
54c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * regarding copyright ownership. The ASF licenses this file
64c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * to you under the Apache License, Version 2.0 (the  "License");
74c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * you may not use this file except in compliance with the License.
84c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * You may obtain a copy of the License at
94c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson *
104c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson *     http://www.apache.org/licenses/LICENSE-2.0
114c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson *
124c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * Unless required by applicable law or agreed to in writing, software
134c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * distributed under the License is distributed on an "AS IS" BASIS,
144c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
154c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * See the License for the specific language governing permissions and
164c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * limitations under the License.
174c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson */
184c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson/*
194c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * $Id: FilterExprWalker.java 469367 2006-10-31 04:41:08Z minchau $
204c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson */
214c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonpackage org.apache.xpath.axes;
224c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
234c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonimport org.apache.xml.dtm.Axis;
244c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonimport org.apache.xml.dtm.DTM;
254c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonimport org.apache.xml.dtm.DTMIterator;
264c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonimport org.apache.xpath.Expression;
274c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonimport org.apache.xpath.ExpressionOwner;
284c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonimport org.apache.xpath.XPathContext;
294c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonimport org.apache.xpath.XPathVisitor;
304c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonimport org.apache.xpath.compiler.Compiler;
314c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonimport org.apache.xpath.compiler.OpCodes;
324c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonimport org.apache.xpath.objects.XNodeSet;
334c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
344c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson/**
354c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * Walker for the OP_VARIABLE, or OP_EXTFUNCTION, or OP_FUNCTION, or OP_GROUP,
364c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * op codes.
374c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * @see <a href="http://www.w3.org/TR/xpath#NT-FilterExpr">XPath FilterExpr descriptions</a>
384c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson */
394c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonpublic class FilterExprWalker extends AxesWalker
404c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson{
414c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    static final long serialVersionUID = 5457182471424488375L;
424c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
434c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
444c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Construct a FilterExprWalker using a LocPathIterator.
454c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *
464c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @param locPathIterator non-null reference to the parent iterator.
474c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
484c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public FilterExprWalker(WalkingIterator locPathIterator)
494c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
504c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    super(locPathIterator, Axis.FILTEREDLIST);
514c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
524c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
534c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
544c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Init a FilterExprWalker.
554c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *
564c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @param compiler non-null reference to the Compiler that is constructing.
574c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @param opPos positive opcode position for this step.
584c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @param stepType The type of step.
594c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *
604c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @throws javax.xml.transform.TransformerException
614c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
624c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public void init(Compiler compiler, int opPos, int stepType)
634c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson          throws javax.xml.transform.TransformerException
644c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
654c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
664c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    super.init(compiler, opPos, stepType);
674c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
684c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    // Smooth over an anomily in the opcode map...
694c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    switch (stepType)
704c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    {
714c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    case OpCodes.OP_FUNCTION :
724c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    case OpCodes.OP_EXTFUNCTION :
734c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    	m_mustHardReset = true;
744c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    case OpCodes.OP_GROUP :
754c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    case OpCodes.OP_VARIABLE :
764c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      m_expr = compiler.compile(opPos);
774c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      m_expr.exprSetParent(this);
784c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      //if((OpCodes.OP_FUNCTION == stepType) && (m_expr instanceof org.apache.xalan.templates.FuncKey))
794c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      if(m_expr instanceof org.apache.xpath.operations.Variable)
804c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      {
814c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      	// hack/temp workaround
824c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      	m_canDetachNodeset = false;
834c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      }
844c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      break;
854c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    default :
864c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      m_expr = compiler.compile(opPos + 2);
874c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      m_expr.exprSetParent(this);
884c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    }
894c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson//    if(m_expr instanceof WalkingIterator)
904c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson//    {
914c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson//      WalkingIterator wi = (WalkingIterator)m_expr;
924c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson//      if(wi.getFirstWalker() instanceof FilterExprWalker)
934c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson//      {
944c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson//      	FilterExprWalker fw = (FilterExprWalker)wi.getFirstWalker();
954c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson//      	if(null == fw.getNextWalker())
964c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson//      	{
974c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson//      		m_expr = fw.m_expr;
984c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson//      		m_expr.exprSetParent(this);
994c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson//      	}
1004c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson//      }
1014c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson//
1024c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson//    }
1034c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
1044c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
1054c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
1064c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Detaches the walker from the set which it iterated over, releasing
1074c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * any computational resources and placing the iterator in the INVALID
1084c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * state.
1094c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
1104c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public void detach()
1114c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
1124c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  	super.detach();
1134c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  	if (m_canDetachNodeset)
1144c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  	{
1154c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  	  m_exprObj.detach();
1164c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  	}
1174c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  	m_exprObj = null;
1184c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
1194c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
1204c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
1214c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *  Set the root node of the TreeWalker.
1224c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *
1234c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @param root non-null reference to the root, or starting point of
1244c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *        the query.
1254c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
1264c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public void setRoot(int root)
1274c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
1284c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
1294c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    super.setRoot(root);
1304c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
1314c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  	m_exprObj = FilterExprIteratorSimple.executeFilterExpr(root,
1324c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  	                  m_lpi.getXPathContext(), m_lpi.getPrefixResolver(),
1334c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  	                  m_lpi.getIsTopLevel(), m_lpi.m_stackFrame, m_expr);
1344c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
1354c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
1364c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
1374c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
1384c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Get a cloned FilterExprWalker.
1394c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *
1404c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @return A new FilterExprWalker that can be used without mutating this one.
1414c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *
1424c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @throws CloneNotSupportedException
1434c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
1444c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public Object clone() throws CloneNotSupportedException
1454c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
1464c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
1474c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    FilterExprWalker clone = (FilterExprWalker) super.clone();
1484c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
1494c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    if (null != m_exprObj)
1504c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      clone.m_exprObj = (XNodeSet) m_exprObj.clone();
1514c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
1524c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    return clone;
1534c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
1544c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
1554c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
1564c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * This method needs to override AxesWalker.acceptNode because FilterExprWalkers
1574c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * don't need to, and shouldn't, do a node test.
1584c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @param n  The node to check to see if it passes the filter or not.
1594c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @return  a constant to determine whether the node is accepted,
1604c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *   rejected, or skipped, as defined  above .
1614c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
1624c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public short acceptNode(int n)
1634c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
1644c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
1654c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    try
1664c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    {
1674c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      if (getPredicateCount() > 0)
1684c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      {
1694c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson        countProximityPosition(0);
1704c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
1714c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson        if (!executePredicates(n, m_lpi.getXPathContext()))
1724c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson          return DTMIterator.FILTER_SKIP;
1734c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      }
1744c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
1754c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      return DTMIterator.FILTER_ACCEPT;
1764c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    }
1774c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    catch (javax.xml.transform.TransformerException se)
1784c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    {
1794c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      throw new RuntimeException(se.getMessage());
1804c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    }
1814c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
1824c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
1834c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
1844c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *  Moves the <code>TreeWalker</code> to the next visible node in document
1854c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * order relative to the current node, and returns the new node. If the
1864c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * current node has no next node,  or if the search for nextNode attempts
1874c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * to step upward from the TreeWalker's root node, returns
1884c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * <code>null</code> , and retains the current node.
1894c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @return  The new node, or <code>null</code> if the current node has no
1904c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *   next node  in the TreeWalker's logical view.
1914c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
1924c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public int getNextNode()
1934c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
1944c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
1954c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    if (null != m_exprObj)
1964c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    {
1974c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson       int next = m_exprObj.nextNode();
1984c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson       return next;
1994c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    }
2004c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    else
2014c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      return DTM.NULL;
2024c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
2034c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
2044c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
2054c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Get the index of the last node that can be itterated to.
2064c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *
2074c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *
2084c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @param xctxt XPath runtime context.
2094c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *
2104c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @return the index of the last node that can be itterated to.
2114c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
2124c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public int getLastPos(XPathContext xctxt)
2134c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
2144c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    return m_exprObj.getLength();
2154c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
2164c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
2174c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /** The contained expression. Should be non-null.
2184c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *  @serial   */
2194c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  private Expression m_expr;
2204c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
2214c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /** The result of executing m_expr.  Needs to be deep cloned on clone op.  */
2224c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  transient private XNodeSet m_exprObj;
2234c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
2244c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  private boolean m_mustHardReset = false;
2254c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  private boolean m_canDetachNodeset = true;
2264c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
2274c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
2284c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * This function is used to fixup variables from QNames to stack frame
2294c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * indexes at stylesheet build time.
2304c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @param vars List of QNames that correspond to variables.  This list
2314c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * should be searched backwards for the first qualified name that
2324c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * corresponds to the variable reference qname.  The position of the
2334c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * QName in the vector from the start of the vector will be its position
2344c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * in the stack frame (but variables above the globalsTop value will need
2354c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * to be offset to the current stack frame).
2364c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
2374c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public void fixupVariables(java.util.Vector vars, int globalsSize)
2384c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
2394c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    super.fixupVariables(vars, globalsSize);
2404c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    m_expr.fixupVariables(vars, globalsSize);
2414c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
2424c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
2434c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
2444c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Get the inner contained expression of this filter.
2454c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
2464c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public Expression getInnerExpression()
2474c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
2484c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  	return m_expr;
2494c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
2504c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
2514c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
2524c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Set the inner contained expression of this filter.
2534c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
2544c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public void setInnerExpression(Expression expr)
2554c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
2564c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  	expr.exprSetParent(this);
2574c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  	m_expr = expr;
2584c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
2594c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
2604c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
2614c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
2624c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Get the analysis bits for this walker, as defined in the WalkerFactory.
2634c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @return One of WalkerFactory#BIT_DESCENDANT, etc.
2644c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
2654c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public int getAnalysisBits()
2664c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
2674c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      if (null != m_expr && m_expr instanceof PathComponent)
2684c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      {
2694c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson        return ((PathComponent) m_expr).getAnalysisBits();
2704c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      }
2714c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      return WalkerFactory.BIT_FILTER;
2724c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
2734c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
2744c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
2754c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Returns true if all the nodes in the iteration well be returned in document
2764c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * order.
2774c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Warning: This can only be called after setRoot has been called!
2784c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *
2794c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @return true as a default.
2804c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
2814c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public boolean isDocOrdered()
2824c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
2834c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    return m_exprObj.isDocOrdered();
2844c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
2854c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
2864c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
2874c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Returns the axis being iterated, if it is known.
2884c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *
2894c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @return Axis.CHILD, etc., or -1 if the axis is not known or is of multiple
2904c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * types.
2914c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
2924c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public int getAxis()
2934c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
2944c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    return m_exprObj.getAxis();
2954c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
2964c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
2974c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  class filterExprOwner implements ExpressionOwner
2984c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
2994c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      /**
3004c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson     * @see ExpressionOwner#getExpression()
3014c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson     */
3024c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    public Expression getExpression()
3034c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    {
3044c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      return m_expr;
3054c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    }
3064c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
3074c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    /**
3084c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson     * @see ExpressionOwner#setExpression(Expression)
3094c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson     */
3104c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    public void setExpression(Expression exp)
3114c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    {
3124c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    	exp.exprSetParent(FilterExprWalker.this);
3134c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    	m_expr = exp;
3144c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    }
3154c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
3164c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
3174c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson	/**
3184c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson	 * This will traverse the heararchy, calling the visitor for
3194c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson	 * each member.  If the called visitor method returns
3204c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson	 * false, the subtree should not be called.
3214c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson	 *
3224c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson	 * @param visitor The visitor whose appropriate method will be called.
3234c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson	 */
3244c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson	public void callPredicateVisitors(XPathVisitor visitor)
3254c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson	{
3264c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson	  m_expr.callVisitors(new filterExprOwner(), visitor);
3274c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
3284c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson	  super.callPredicateVisitors(visitor);
3294c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson	}
3304c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
3314c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
3324c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    /**
3334c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson     * @see Expression#deepEquals(Expression)
3344c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson     */
3354c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    public boolean deepEquals(Expression expr)
3364c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    {
3374c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      if (!super.deepEquals(expr))
3384c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson                return false;
3394c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
3404c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      FilterExprWalker walker = (FilterExprWalker)expr;
3414c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      if(!m_expr.deepEquals(walker.m_expr))
3424c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      	return false;
3434c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
3444c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      return true;
3454c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    }
3464c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
3474c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
3484c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
3494c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson}
350