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: FilterExprIterator.java 468655 2006-10-28 07:12:06Z minchau $
204c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson */
214c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonpackage org.apache.xpath.axes;
224c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
234c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonimport org.apache.xml.dtm.DTM;
244c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonimport org.apache.xpath.Expression;
254c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonimport org.apache.xpath.ExpressionOwner;
264c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonimport org.apache.xpath.XPathVisitor;
274c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonimport org.apache.xpath.objects.XNodeSet;
284c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
294c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonpublic class FilterExprIterator extends BasicTestIterator
304c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson{
314c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    static final long serialVersionUID = 2552176105165737614L;
324c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /** The contained expression. Should be non-null.
334c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *  @serial   */
344c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  private Expression m_expr;
354c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
364c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /** The result of executing m_expr.  Needs to be deep cloned on clone op.  */
374c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  transient private XNodeSet m_exprObj;
384c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
394c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  private boolean m_mustHardReset = false;
404c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  private boolean m_canDetachNodeset = true;
414c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
424c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
434c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Create a FilterExprIterator object.
444c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *
454c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
464c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public FilterExprIterator()
474c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
484c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    super(null);
494c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
504c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
514c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
524c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Create a FilterExprIterator object.
534c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *
544c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
554c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public FilterExprIterator(Expression expr)
564c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
574c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    super(null);
584c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    m_expr = expr;
594c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
604c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
614c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
624c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Initialize the context values for this expression
634c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * after it is cloned.
644c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *
654c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @param context The XPath runtime context for this
664c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * transformation.
674c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
684c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public void setRoot(int context, Object environment)
694c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
704c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  	super.setRoot(context, environment);
714c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
724c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  	m_exprObj = FilterExprIteratorSimple.executeFilterExpr(context,
734c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  	                  m_execContext, getPrefixResolver(),
744c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  	                  getIsTopLevel(), m_stackFrame, m_expr);
754c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   }
764c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
774c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
784c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
794c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Get the next node via getNextXXX.  Bottlenecked for derived class override.
804c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @return The next node on the axis, or DTM.NULL.
814c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
824c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  protected int getNextNode()
834c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
844c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    if (null != m_exprObj)
854c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    {
864c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      m_lastFetched = m_exprObj.nextNode();
874c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    }
884c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    else
894c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      m_lastFetched = DTM.NULL;
904c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
914c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    return m_lastFetched;
924c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
934c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
944c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
954c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Detaches the walker from the set which it iterated over, releasing
964c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * any computational resources and placing the iterator in the INVALID
974c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * state.
984c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
994c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public void detach()
1004c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
1014c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  	super.detach();
1024c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  	m_exprObj.detach();
1034c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  	m_exprObj = null;
1044c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
1054c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
1064c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
1074c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * This function is used to fixup variables from QNames to stack frame
1084c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * indexes at stylesheet build time.
1094c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @param vars List of QNames that correspond to variables.  This list
1104c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * should be searched backwards for the first qualified name that
1114c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * corresponds to the variable reference qname.  The position of the
1124c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * QName in the vector from the start of the vector will be its position
1134c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * in the stack frame (but variables above the globalsTop value will need
1144c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * to be offset to the current stack frame).
1154c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
1164c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public void fixupVariables(java.util.Vector vars, int globalsSize)
1174c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
1184c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    super.fixupVariables(vars, globalsSize);
1194c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    m_expr.fixupVariables(vars, globalsSize);
1204c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
1214c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
1224c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
1234c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Get the inner contained expression of this filter.
1244c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
1254c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public Expression getInnerExpression()
1264c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
1274c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    return m_expr;
1284c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
1294c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
1304c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
1314c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Set the inner contained expression of this filter.
1324c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
1334c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public void setInnerExpression(Expression expr)
1344c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
1354c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    expr.exprSetParent(this);
1364c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    m_expr = expr;
1374c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
1384c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
1394c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
1404c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Get the analysis bits for this walker, as defined in the WalkerFactory.
1414c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @return One of WalkerFactory#BIT_DESCENDANT, etc.
1424c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
1434c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public int getAnalysisBits()
1444c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
1454c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    if (null != m_expr && m_expr instanceof PathComponent)
1464c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    {
1474c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      return ((PathComponent) m_expr).getAnalysisBits();
1484c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    }
1494c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    return WalkerFactory.BIT_FILTER;
1504c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
1514c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
1524c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
1534c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Returns true if all the nodes in the iteration well be returned in document
1544c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * order.
1554c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Warning: This can only be called after setRoot has been called!
1564c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *
1574c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @return true as a default.
1584c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
1594c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public boolean isDocOrdered()
1604c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
1614c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    return m_exprObj.isDocOrdered();
1624c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
1634c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
1644c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  class filterExprOwner implements ExpressionOwner
1654c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
1664c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    /**
1674c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    * @see ExpressionOwner#getExpression()
1684c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    */
1694c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    public Expression getExpression()
1704c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    {
1714c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      return m_expr;
1724c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    }
1734c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
1744c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    /**
1754c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson     * @see ExpressionOwner#setExpression(Expression)
1764c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson     */
1774c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    public void setExpression(Expression exp)
1784c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    {
1794c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      exp.exprSetParent(FilterExprIterator.this);
1804c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      m_expr = exp;
1814c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    }
1824c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
1834c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
1844c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
1854c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
1864c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * This will traverse the heararchy, calling the visitor for
1874c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * each member.  If the called visitor method returns
1884c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * false, the subtree should not be called.
1894c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *
1904c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @param visitor The visitor whose appropriate method will be called.
1914c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
1924c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public void callPredicateVisitors(XPathVisitor visitor)
1934c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
1944c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    m_expr.callVisitors(new filterExprOwner(), visitor);
1954c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
1964c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    super.callPredicateVisitors(visitor);
1974c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
1984c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
1994c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
2004c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @see Expression#deepEquals(Expression)
2014c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
2024c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public boolean deepEquals(Expression expr)
2034c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
2044c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    if (!super.deepEquals(expr))
2054c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      return false;
2064c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
2074c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    FilterExprIterator fet = (FilterExprIterator) expr;
2084c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    if (!m_expr.deepEquals(fet.m_expr))
2094c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      return false;
2104c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
2114c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    return true;
2124c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
2134c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
2144c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson}
215