- /*
- * Copyright 1999-2004 The Apache Software Foundation.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /*
- * $Id: FilterExprWalker.java,v 1.24 2004/02/17 04:32:08 minchau Exp $
- */
- package com.sun.org.apache.xpath.internal.axes;
-
- import com.sun.org.apache.xml.internal.dtm.Axis;
- import com.sun.org.apache.xml.internal.dtm.DTM;
- import com.sun.org.apache.xml.internal.dtm.DTMIterator;
- import com.sun.org.apache.xpath.internal.Expression;
- import com.sun.org.apache.xpath.internal.ExpressionOwner;
- import com.sun.org.apache.xpath.internal.XPathContext;
- import com.sun.org.apache.xpath.internal.XPathVisitor;
- import com.sun.org.apache.xpath.internal.compiler.Compiler;
- import com.sun.org.apache.xpath.internal.compiler.OpCodes;
- import com.sun.org.apache.xpath.internal.objects.XNodeSet;
-
- /**
- * Walker for the OP_VARIABLE, or OP_EXTFUNCTION, or OP_FUNCTION, or OP_GROUP,
- * op codes.
- * @see <a href="http://www.w3.org/TR/xpath#NT-FilterExpr">XPath FilterExpr descriptions</a>
- */
- public class FilterExprWalker extends AxesWalker
- {
-
- /**
- * Construct a FilterExprWalker using a LocPathIterator.
- *
- * @param locPathIterator non-null reference to the parent iterator.
- */
- public FilterExprWalker(WalkingIterator locPathIterator)
- {
- super(locPathIterator, Axis.FILTEREDLIST);
- }
-
- /**
- * Init a FilterExprWalker.
- *
- * @param compiler non-null reference to the Compiler that is constructing.
- * @param opPos positive opcode position for this step.
- * @param stepType The type of step.
- *
- * @throws javax.xml.transform.TransformerException
- */
- public void init(Compiler compiler, int opPos, int stepType)
- throws javax.xml.transform.TransformerException
- {
-
- super.init(compiler, opPos, stepType);
-
- // Smooth over an anomily in the opcode map...
- switch (stepType)
- {
- case OpCodes.OP_FUNCTION :
- case OpCodes.OP_EXTFUNCTION :
- m_mustHardReset = true;
- case OpCodes.OP_GROUP :
- case OpCodes.OP_VARIABLE :
- m_expr = compiler.compile(opPos);
- m_expr.exprSetParent(this);
- //if((OpCodes.OP_FUNCTION == stepType) && (m_expr instanceof com.sun.org.apache.xalan.internal.templates.FuncKey))
- if(m_expr instanceof com.sun.org.apache.xpath.internal.operations.Variable)
- {
- // hack/temp workaround
- m_canDetachNodeset = false;
- }
- break;
- default :
- m_expr = compiler.compile(opPos + 2);
- m_expr.exprSetParent(this);
- }
- // if(m_expr instanceof WalkingIterator)
- // {
- // WalkingIterator wi = (WalkingIterator)m_expr;
- // if(wi.getFirstWalker() instanceof FilterExprWalker)
- // {
- // FilterExprWalker fw = (FilterExprWalker)wi.getFirstWalker();
- // if(null == fw.getNextWalker())
- // {
- // m_expr = fw.m_expr;
- // m_expr.exprSetParent(this);
- // }
- // }
- //
- // }
- }
-
- /**
- * Detaches the walker from the set which it iterated over, releasing
- * any computational resources and placing the iterator in the INVALID
- * state.
- */
- public void detach()
- {
- super.detach();
- if (m_canDetachNodeset)
- {
- m_exprObj.detach();
- }
- m_exprObj = null;
- }
-
- /**
- * Set the root node of the TreeWalker.
- *
- * @param root non-null reference to the root, or starting point of
- * the query.
- */
- public void setRoot(int root)
- {
-
- super.setRoot(root);
-
- m_exprObj = FilterExprIteratorSimple.executeFilterExpr(root,
- m_lpi.getXPathContext(), m_lpi.getPrefixResolver(),
- m_lpi.getIsTopLevel(), m_lpi.m_stackFrame, m_expr);
-
- }
-
- /**
- * Get a cloned FilterExprWalker.
- *
- * @return A new FilterExprWalker that can be used without mutating this one.
- *
- * @throws CloneNotSupportedException
- */
- public Object clone() throws CloneNotSupportedException
- {
-
- FilterExprWalker clone = (FilterExprWalker) super.clone();
-
- // clone.m_expr = (Expression)((Expression)m_expr).clone();
- if (null != m_exprObj)
- clone.m_exprObj = (XNodeSet) m_exprObj.clone();
-
- return clone;
- }
-
- /**
- * This method needs to override AxesWalker.acceptNode because FilterExprWalkers
- * don't need to, and shouldn't, do a node test.
- * @param n The node to check to see if it passes the filter or not.
- * @return a constant to determine whether the node is accepted,
- * rejected, or skipped, as defined above .
- */
- public short acceptNode(int n)
- {
-
- try
- {
- if (getPredicateCount() > 0)
- {
- countProximityPosition(0);
-
- if (!executePredicates(n, m_lpi.getXPathContext()))
- return DTMIterator.FILTER_SKIP;
- }
-
- return DTMIterator.FILTER_ACCEPT;
- }
- catch (javax.xml.transform.TransformerException se)
- {
- throw new RuntimeException(se.getMessage());
- }
- }
-
- /**
- * Moves the <code>TreeWalker</code> to the next visible node in document
- * order relative to the current node, and returns the new node. If the
- * current node has no next node, or if the search for nextNode attempts
- * to step upward from the TreeWalker's root node, returns
- * <code>null</code> , and retains the current node.
- * @return The new node, or <code>null</code> if the current node has no
- * next node in the TreeWalker's logical view.
- */
- public int getNextNode()
- {
-
- if (null != m_exprObj)
- {
- int next = m_exprObj.nextNode();
- return next;
- }
- else
- return DTM.NULL;
- }
-
- /**
- * Get the index of the last node that can be itterated to.
- *
- *
- * @param xctxt XPath runtime context.
- *
- * @return the index of the last node that can be itterated to.
- */
- public int getLastPos(XPathContext xctxt)
- {
- return m_exprObj.getLength();
- }
-
- /** The contained expression. Should be non-null.
- * @serial */
- private Expression m_expr;
-
- /** The result of executing m_expr. Needs to be deep cloned on clone op. */
- transient private XNodeSet m_exprObj;
-
- private boolean m_mustHardReset = false;
- private boolean m_canDetachNodeset = true;
-
- /**
- * This function is used to fixup variables from QNames to stack frame
- * indexes at stylesheet build time.
- * @param vars List of QNames that correspond to variables. This list
- * should be searched backwards for the first qualified name that
- * corresponds to the variable reference qname. The position of the
- * QName in the vector from the start of the vector will be its position
- * in the stack frame (but variables above the globalsTop value will need
- * to be offset to the current stack frame).
- */
- public void fixupVariables(java.util.Vector vars, int globalsSize)
- {
- super.fixupVariables(vars, globalsSize);
- m_expr.fixupVariables(vars, globalsSize);
- }
-
- /**
- * Get the inner contained expression of this filter.
- */
- public Expression getInnerExpression()
- {
- return m_expr;
- }
-
- /**
- * Set the inner contained expression of this filter.
- */
- public void setInnerExpression(Expression expr)
- {
- expr.exprSetParent(this);
- m_expr = expr;
- }
-
-
- /**
- * Get the analysis bits for this walker, as defined in the WalkerFactory.
- * @return One of WalkerFactory#BIT_DESCENDANT, etc.
- */
- public int getAnalysisBits()
- {
- if (null != m_expr && m_expr instanceof PathComponent)
- {
- return ((PathComponent) m_expr).getAnalysisBits();
- }
- return WalkerFactory.BIT_FILTER;
- }
-
- /**
- * Returns true if all the nodes in the iteration well be returned in document
- * order.
- * Warning: This can only be called after setRoot has been called!
- *
- * @return true as a default.
- */
- public boolean isDocOrdered()
- {
- return m_exprObj.isDocOrdered();
- }
-
- /**
- * Returns the axis being iterated, if it is known.
- *
- * @return Axis.CHILD, etc., or -1 if the axis is not known or is of multiple
- * types.
- */
- public int getAxis()
- {
- return m_exprObj.getAxis();
- }
-
- class filterExprOwner implements ExpressionOwner
- {
- /**
- * @see ExpressionOwner#getExpression()
- */
- public Expression getExpression()
- {
- return m_expr;
- }
-
- /**
- * @see ExpressionOwner#setExpression(Expression)
- */
- public void setExpression(Expression exp)
- {
- exp.exprSetParent(FilterExprWalker.this);
- m_expr = exp;
- }
- }
-
- /**
- * This will traverse the heararchy, calling the visitor for
- * each member. If the called visitor method returns
- * false, the subtree should not be called.
- *
- * @param owner The owner of the visitor, where that path may be
- * rewritten if needed.
- * @param visitor The visitor whose appropriate method will be called.
- */
- public void callPredicateVisitors(XPathVisitor visitor)
- {
- m_expr.callVisitors(new filterExprOwner(), visitor);
-
- super.callPredicateVisitors(visitor);
- }
-
-
- /**
- * @see Expression#deepEquals(Expression)
- */
- public boolean deepEquals(Expression expr)
- {
- if (!super.deepEquals(expr))
- return false;
-
- FilterExprWalker walker = (FilterExprWalker)expr;
- if(!m_expr.deepEquals(walker.m_expr))
- return false;
-
- return true;
- }
-
-
-
- }