/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you 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: StepPattern.java 468655 2006-10-28 07:12:06Z minchau $
 */
package org.apache.xpath.patterns;

import org.apache.xml.dtm.Axis;
import org.apache.xml.dtm.DTM;
import org.apache.xml.dtm.DTMAxisTraverser;
import org.apache.xml.dtm.DTMFilter;
import org.apache.xpath.Expression;
import org.apache.xpath.ExpressionOwner;
import org.apache.xpath.XPathContext;
import org.apache.xpath.XPathVisitor;
import org.apache.xpath.axes.SubContextList;
import org.apache.xpath.compiler.PsuedoNames;
import org.apache.xpath.objects.XObject;

This class represents a single pattern match step.
@xsl.usageadvanced
/** * This class represents a single pattern match step. * @xsl.usage advanced */
public class StepPattern extends NodeTest implements SubContextList, ExpressionOwner { static final long serialVersionUID = 9071668960168152644L;
The axis for this test.
/** The axis for this test. */
protected int m_axis;
Construct a StepPattern that tests for namespaces and node names.
Params:
  • whatToShow – Bit set defined mainly by NodeFilter.
  • namespace – The namespace to be tested.
  • name – The local name to be tested.
  • axis – The Axis for this test, one of of Axes.ANCESTORORSELF, etc.
  • axisForPredicate – No longer used.
/** * Construct a StepPattern that tests for namespaces and node names. * * * @param whatToShow Bit set defined mainly by {@link org.w3c.dom.traversal.NodeFilter}. * @param namespace The namespace to be tested. * @param name The local name to be tested. * @param axis The Axis for this test, one of of Axes.ANCESTORORSELF, etc. * @param axisForPredicate No longer used. */
public StepPattern(int whatToShow, String namespace, String name, int axis, int axisForPredicate) { super(whatToShow, namespace, name); m_axis = axis; }
Construct a StepPattern that doesn't test for node names.
Params:
  • whatToShow – Bit set defined mainly by NodeFilter.
  • axis – The Axis for this test, one of of Axes.ANCESTORORSELF, etc.
  • axisForPredicate – No longer used.
/** * Construct a StepPattern that doesn't test for node names. * * * @param whatToShow Bit set defined mainly by {@link org.w3c.dom.traversal.NodeFilter}. * @param axis The Axis for this test, one of of Axes.ANCESTORORSELF, etc. * @param axisForPredicate No longer used. */
public StepPattern(int whatToShow, int axis, int axisForPredicate) { super(whatToShow); m_axis = axis; }
The target local name or psuedo name, for hash table lookup optimization. @serial
/** * The target local name or psuedo name, for hash table lookup optimization. * @serial */
String m_targetString; // only calculate on head
Calculate the local name or psuedo name of the node that this pattern will test, for hash table lookup optimization.
See Also:
  • PsuedoNames
/** * Calculate the local name or psuedo name of the node that this pattern will test, * for hash table lookup optimization. * * @see org.apache.xpath.compiler.PsuedoNames */
public void calcTargetString() { int whatToShow = getWhatToShow(); switch (whatToShow) { case DTMFilter.SHOW_COMMENT : m_targetString = PsuedoNames.PSEUDONAME_COMMENT; break; case DTMFilter.SHOW_TEXT : case DTMFilter.SHOW_CDATA_SECTION : case (DTMFilter.SHOW_TEXT | DTMFilter.SHOW_CDATA_SECTION) : m_targetString = PsuedoNames.PSEUDONAME_TEXT; break; case DTMFilter.SHOW_ALL : m_targetString = PsuedoNames.PSEUDONAME_ANY; break; case DTMFilter.SHOW_DOCUMENT : case DTMFilter.SHOW_DOCUMENT | DTMFilter.SHOW_DOCUMENT_FRAGMENT : m_targetString = PsuedoNames.PSEUDONAME_ROOT; break; case DTMFilter.SHOW_ELEMENT : if (this.WILD == m_name) m_targetString = PsuedoNames.PSEUDONAME_ANY; else m_targetString = m_name; break; default : m_targetString = PsuedoNames.PSEUDONAME_ANY; break; } }
Get the local name or psuedo name of the node that this pattern will test, for hash table lookup optimization.
See Also:
Returns:local name or psuedo name of the node.
/** * Get the local name or psuedo name of the node that this pattern will test, * for hash table lookup optimization. * * * @return local name or psuedo name of the node. * @see org.apache.xpath.compiler.PsuedoNames */
public String getTargetString() { return m_targetString; }
Reference to nodetest and predicate for parent or ancestor.
@serial
/** * Reference to nodetest and predicate for * parent or ancestor. * @serial */
StepPattern m_relativePathPattern;
This function is used to fixup variables from QNames to stack frame indexes at stylesheet build time.
Params:
  • 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).
  • globalsSize – The number of variables in the global variable area.
/** * 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). * @param globalsSize The number of variables in the global variable area. */
public void fixupVariables(java.util.Vector vars, int globalsSize) { super.fixupVariables(vars, globalsSize); if (null != m_predicates) { for (int i = 0; i < m_predicates.length; i++) { m_predicates[i].fixupVariables(vars, globalsSize); } } if (null != m_relativePathPattern) { m_relativePathPattern.fixupVariables(vars, globalsSize); } }
Set the reference to nodetest and predicate for parent or ancestor.
Params:
  • expr – The relative pattern expression.
/** * Set the reference to nodetest and predicate for * parent or ancestor. * * * @param expr The relative pattern expression. */
public void setRelativePathPattern(StepPattern expr) { m_relativePathPattern = expr; expr.exprSetParent(this); calcScore(); }
Get the reference to nodetest and predicate for parent or ancestor.
Returns:The relative pattern expression.
/** * Get the reference to nodetest and predicate for * parent or ancestor. * * * @return The relative pattern expression. */
public StepPattern getRelativePathPattern() { return m_relativePathPattern; } // /** // * Set the list of predicate expressions for this pattern step. // * @param predicates List of expression objects. // */ // public void setPredicates(Expression[] predicates) // { // m_predicates = predicates; // }
Set the list of predicate expressions for this pattern step.
Returns:List of expression objects.
/** * Set the list of predicate expressions for this pattern step. * @return List of expression objects. */
public Expression[] getPredicates() { return m_predicates; }
The list of predicate expressions for this pattern step. @serial
/** * The list of predicate expressions for this pattern step. * @serial */
Expression[] m_predicates;
Tell if this expression or it's subexpressions can traverse outside the current subtree. NOTE: Ancestors tests with predicates are problematic, and will require special treatment.
Returns:true if traversal outside the context node's subtree can occur.
/** * Tell if this expression or it's subexpressions can traverse outside * the current subtree. * * NOTE: Ancestors tests with predicates are problematic, and will require * special treatment. * * @return true if traversal outside the context node's subtree can occur. */
public boolean canTraverseOutsideSubtree() { int n = getPredicateCount(); for (int i = 0; i < n; i++) { if (getPredicate(i).canTraverseOutsideSubtree()) return true; } return false; }
Get a predicate expression.
Params:
  • i – The index of the predicate.
Returns:A predicate expression.
/** * Get a predicate expression. * * * @param i The index of the predicate. * * @return A predicate expression. */
public Expression getPredicate(int i) { return m_predicates[i]; }
Get the number of predicates for this match pattern step.
Returns:the number of predicates for this match pattern step.
/** * Get the number of predicates for this match pattern step. * * * @return the number of predicates for this match pattern step. */
public final int getPredicateCount() { return (null == m_predicates) ? 0 : m_predicates.length; }
Set the predicates for this match pattern step.
Params:
  • predicates – An array of expressions that define predicates for this step.
/** * Set the predicates for this match pattern step. * * * @param predicates An array of expressions that define predicates * for this step. */
public void setPredicates(Expression[] predicates) { m_predicates = predicates; if(null != predicates) { for(int i = 0; i < predicates.length; i++) { predicates[i].exprSetParent(this); } } calcScore(); }
Static calc of match score.
/** * Static calc of match score. */
public void calcScore() { if ((getPredicateCount() > 0) || (null != m_relativePathPattern)) { m_score = SCORE_OTHER; } else super.calcScore(); if (null == m_targetString) calcTargetString(); }
Execute this pattern step, including predicates.
Params:
  • xctxt – XPath runtime context.
  • currentNode – The current node context.
Throws:
Returns:NodeTest.SCORE_NODETEST, NodeTest.SCORE_NONE, NodeTest.SCORE_NSWILD, NodeTest.SCORE_QNAME, or NodeTest.SCORE_OTHER.
/** * Execute this pattern step, including predicates. * * * @param xctxt XPath runtime context. * @param currentNode The current node context. * * @return {@link org.apache.xpath.patterns.NodeTest#SCORE_NODETEST}, * {@link org.apache.xpath.patterns.NodeTest#SCORE_NONE}, * {@link org.apache.xpath.patterns.NodeTest#SCORE_NSWILD}, * {@link org.apache.xpath.patterns.NodeTest#SCORE_QNAME}, or * {@link org.apache.xpath.patterns.NodeTest#SCORE_OTHER}. * * @throws javax.xml.transform.TransformerException */
public XObject execute(XPathContext xctxt, int currentNode) throws javax.xml.transform.TransformerException { DTM dtm = xctxt.getDTM(currentNode); if (dtm != null) { int expType = dtm.getExpandedTypeID(currentNode); return execute(xctxt, currentNode, dtm, expType); } return NodeTest.SCORE_NONE; }
Execute this pattern step, including predicates.
Params:
  • xctxt – XPath runtime context.
Throws:
Returns:NodeTest.SCORE_NODETEST, NodeTest.SCORE_NONE, NodeTest.SCORE_NSWILD, NodeTest.SCORE_QNAME, or NodeTest.SCORE_OTHER.
/** * Execute this pattern step, including predicates. * * * @param xctxt XPath runtime context. * * @return {@link org.apache.xpath.patterns.NodeTest#SCORE_NODETEST}, * {@link org.apache.xpath.patterns.NodeTest#SCORE_NONE}, * {@link org.apache.xpath.patterns.NodeTest#SCORE_NSWILD}, * {@link org.apache.xpath.patterns.NodeTest#SCORE_QNAME}, or * {@link org.apache.xpath.patterns.NodeTest#SCORE_OTHER}. * * @throws javax.xml.transform.TransformerException */
public XObject execute(XPathContext xctxt) throws javax.xml.transform.TransformerException { return execute(xctxt, xctxt.getCurrentNode()); }
Execute an expression in the XPath runtime context, and return the result of the expression.
Params:
  • xctxt – The XPath runtime context.
  • currentNode – The currentNode.
  • dtm – The DTM of the current node.
  • expType – The expanded type ID of the current node.
Throws:
Returns:The result of the expression in the form of a XObject.
/** * Execute an expression in the XPath runtime context, and return the * result of the expression. * * * @param xctxt The XPath runtime context. * @param currentNode The currentNode. * @param dtm The DTM of the current node. * @param expType The expanded type ID of the current node. * * @return The result of the expression in the form of a <code>XObject</code>. * * @throws javax.xml.transform.TransformerException if a runtime exception * occurs. */
public XObject execute( XPathContext xctxt, int currentNode, DTM dtm, int expType) throws javax.xml.transform.TransformerException { if (m_whatToShow == NodeTest.SHOW_BYFUNCTION) { if (null != m_relativePathPattern) { return m_relativePathPattern.execute(xctxt); } else return NodeTest.SCORE_NONE; } XObject score; score = super.execute(xctxt, currentNode, dtm, expType); if (score == NodeTest.SCORE_NONE) return NodeTest.SCORE_NONE; if (getPredicateCount() != 0) { if (!executePredicates(xctxt, dtm, currentNode)) return NodeTest.SCORE_NONE; } if (null != m_relativePathPattern) return m_relativePathPattern.executeRelativePathPattern(xctxt, dtm, currentNode); return score; }
New Method to check whether the current node satisfies a position predicate
Params:
  • xctxt – The XPath runtime context.
  • predPos – Which predicate we're evaluating of foo[1][2][3].
  • dtm – The DTM of the current node.
  • context – The currentNode.
  • pos – The position being requested, i.e. the value returned by m_predicates[predPos].execute(xctxt).
Returns:true of the position of the context matches pos, false otherwise.
/** * New Method to check whether the current node satisfies a position predicate * * @param xctxt The XPath runtime context. * @param predPos Which predicate we're evaluating of foo[1][2][3]. * @param dtm The DTM of the current node. * @param context The currentNode. * @param pos The position being requested, i.e. the value returned by * m_predicates[predPos].execute(xctxt). * * @return true of the position of the context matches pos, false otherwise. */
private final boolean checkProximityPosition(XPathContext xctxt, int predPos, DTM dtm, int context, int pos) { try { DTMAxisTraverser traverser = dtm.getAxisTraverser(Axis.PRECEDINGSIBLING); for (int child = traverser.first(context); DTM.NULL != child; child = traverser.next(context, child)) { try { xctxt.pushCurrentNode(child); if (NodeTest.SCORE_NONE != super.execute(xctxt, child)) { boolean pass = true; try { xctxt.pushSubContextList(this); for (int i = 0; i < predPos; i++) { xctxt.pushPredicatePos(i); try { XObject pred = m_predicates[i].execute(xctxt); try { if (XObject.CLASS_NUMBER == pred.getType()) { throw new Error("Why: Should never have been called"); } else if (!pred.boolWithSideEffects()) { pass = false; break; } } finally { pred.detach(); } } finally { xctxt.popPredicatePos(); } } } finally { xctxt.popSubContextList(); } if (pass) pos--; if (pos < 1) return false; } } finally { xctxt.popCurrentNode(); } } } catch (javax.xml.transform.TransformerException se) { // TODO: should keep throw sax exception... throw new java.lang.RuntimeException(se.getMessage()); } return (pos == 1); }
Get the proximity position index of the current node based on this node test.
Params:
  • xctxt – XPath runtime context.
  • predPos – Which predicate we're evaluating of foo[1][2][3].
  • findLast – If true, don't terminate when the context node is found.
Returns:the proximity position index of the current node based on the node test.
/** * Get the proximity position index of the current node based on this * node test. * * * @param xctxt XPath runtime context. * @param predPos Which predicate we're evaluating of foo[1][2][3]. * @param findLast If true, don't terminate when the context node is found. * * @return the proximity position index of the current node based on the * node test. */
private final int getProximityPosition(XPathContext xctxt, int predPos, boolean findLast) { int pos = 0; int context = xctxt.getCurrentNode(); DTM dtm = xctxt.getDTM(context); int parent = dtm.getParent(context); try { DTMAxisTraverser traverser = dtm.getAxisTraverser(Axis.CHILD); for (int child = traverser.first(parent); DTM.NULL != child; child = traverser.next(parent, child)) { try { xctxt.pushCurrentNode(child); if (NodeTest.SCORE_NONE != super.execute(xctxt, child)) { boolean pass = true; try { xctxt.pushSubContextList(this); for (int i = 0; i < predPos; i++) { xctxt.pushPredicatePos(i); try { XObject pred = m_predicates[i].execute(xctxt); try { if (XObject.CLASS_NUMBER == pred.getType()) { if ((pos + 1) != (int) pred.numWithSideEffects()) { pass = false; break; } } else if (!pred.boolWithSideEffects()) { pass = false; break; } } finally { pred.detach(); } } finally { xctxt.popPredicatePos(); } } } finally { xctxt.popSubContextList(); } if (pass) pos++; if (!findLast && child == context) { return pos; } } } finally { xctxt.popCurrentNode(); } } } catch (javax.xml.transform.TransformerException se) { // TODO: should keep throw sax exception... throw new java.lang.RuntimeException(se.getMessage()); } return pos; }
Get the proximity position index of the current node based on this node test.
Params:
  • xctxt – XPath runtime context.
Returns:the proximity position index of the current node based on the node test.
/** * Get the proximity position index of the current node based on this * node test. * * * @param xctxt XPath runtime context. * * @return the proximity position index of the current node based on the * node test. */
public int getProximityPosition(XPathContext xctxt) { return getProximityPosition(xctxt, xctxt.getPredicatePos(), false); }
Get the count of the nodes that match the test, which is the proximity position of the last node that can pass this test in the sub context selection. In XSLT 1-based indexing, this count is the index of the last node.
Params:
  • xctxt – XPath runtime context.
Returns:the count of the nodes that match the test.
/** * Get the count of the nodes that match the test, which is the proximity * position of the last node that can pass this test in the sub context * selection. In XSLT 1-based indexing, this count is the index of the last * node. * * * @param xctxt XPath runtime context. * * @return the count of the nodes that match the test. */
public int getLastPos(XPathContext xctxt) { return getProximityPosition(xctxt, xctxt.getPredicatePos(), true); }
Execute the match pattern step relative to another step.
Params:
  • xctxt – The XPath runtime context.
  • dtm – The DTM of the current node.
  • currentNode – The current node context.
Throws:
Returns:NodeTest.SCORE_NODETEST, NodeTest.SCORE_NONE, NodeTest.SCORE_NSWILD, NodeTest.SCORE_QNAME, or NodeTest.SCORE_OTHER.
/** * Execute the match pattern step relative to another step. * * * @param xctxt The XPath runtime context. * @param dtm The DTM of the current node. * @param currentNode The current node context. * * @return {@link org.apache.xpath.patterns.NodeTest#SCORE_NODETEST}, * {@link org.apache.xpath.patterns.NodeTest#SCORE_NONE}, * {@link org.apache.xpath.patterns.NodeTest#SCORE_NSWILD}, * {@link org.apache.xpath.patterns.NodeTest#SCORE_QNAME}, or * {@link org.apache.xpath.patterns.NodeTest#SCORE_OTHER}. * * @throws javax.xml.transform.TransformerException */
protected final XObject executeRelativePathPattern( XPathContext xctxt, DTM dtm, int currentNode) throws javax.xml.transform.TransformerException { XObject score = NodeTest.SCORE_NONE; int context = currentNode; DTMAxisTraverser traverser; traverser = dtm.getAxisTraverser(m_axis); for (int relative = traverser.first(context); DTM.NULL != relative; relative = traverser.next(context, relative)) { try { xctxt.pushCurrentNode(relative); score = execute(xctxt); if (score != NodeTest.SCORE_NONE) break; } finally { xctxt.popCurrentNode(); } } return score; }
Execute the predicates on this step to determine if the current node should be filtered or accepted.
Params:
  • xctxt – The XPath runtime context.
  • dtm – The DTM of the current node.
  • currentNode – The current node context.
Throws:
Returns:true if the node should be accepted, false otherwise.
/** * Execute the predicates on this step to determine if the current node * should be filtered or accepted. * * @param xctxt The XPath runtime context. * @param dtm The DTM of the current node. * @param currentNode The current node context. * * @return true if the node should be accepted, false otherwise. * * @throws javax.xml.transform.TransformerException */
protected final boolean executePredicates( XPathContext xctxt, DTM dtm, int currentNode) throws javax.xml.transform.TransformerException { boolean result = true; boolean positionAlreadySeen = false; int n = getPredicateCount(); try { xctxt.pushSubContextList(this); for (int i = 0; i < n; i++) { xctxt.pushPredicatePos(i); try { XObject pred = m_predicates[i].execute(xctxt); try { if (XObject.CLASS_NUMBER == pred.getType()) { int pos = (int) pred.num(); if (positionAlreadySeen) { result = (pos == 1); break; } else { positionAlreadySeen = true; if (!checkProximityPosition(xctxt, i, dtm, currentNode, pos)) { result = false; break; } } } else if (!pred.boolWithSideEffects()) { result = false; break; } } finally { pred.detach(); } } finally { xctxt.popPredicatePos(); } } } finally { xctxt.popSubContextList(); } return result; }
Get the string represenentation of this step for diagnostic purposes.
Returns:A string representation of this step, built by reverse-engineering the contained info.
/** * Get the string represenentation of this step for diagnostic purposes. * * * @return A string representation of this step, built by reverse-engineering * the contained info. */
public String toString() { StringBuffer buf = new StringBuffer(); for (StepPattern pat = this; pat != null; pat = pat.m_relativePathPattern) { if (pat != this) buf.append("/"); buf.append(Axis.getNames(pat.m_axis)); buf.append("::"); if (0x000005000 == pat.m_whatToShow) { buf.append("doc()"); } else if (DTMFilter.SHOW_BYFUNCTION == pat.m_whatToShow) { buf.append("function()"); } else if (DTMFilter.SHOW_ALL == pat.m_whatToShow) { buf.append("node()"); } else if (DTMFilter.SHOW_TEXT == pat.m_whatToShow) { buf.append("text()"); } else if (DTMFilter.SHOW_PROCESSING_INSTRUCTION == pat.m_whatToShow) { buf.append("processing-instruction("); if (null != pat.m_name) { buf.append(pat.m_name); } buf.append(")"); } else if (DTMFilter.SHOW_COMMENT == pat.m_whatToShow) { buf.append("comment()"); } else if (null != pat.m_name) { if (DTMFilter.SHOW_ATTRIBUTE == pat.m_whatToShow) { buf.append("@"); } if (null != pat.m_namespace) { buf.append("{"); buf.append(pat.m_namespace); buf.append("}"); } buf.append(pat.m_name); } else if (DTMFilter.SHOW_ATTRIBUTE == pat.m_whatToShow) { buf.append("@"); } else if ((DTMFilter.SHOW_DOCUMENT | DTMFilter.SHOW_DOCUMENT_FRAGMENT) == pat.m_whatToShow) { buf.append("doc-root()"); } else { buf.append("?" + Integer.toHexString(pat.m_whatToShow)); } if (null != pat.m_predicates) { for (int i = 0; i < pat.m_predicates.length; i++) { buf.append("["); buf.append(pat.m_predicates[i]); buf.append("]"); } } } return buf.toString(); }
Set to true to send diagnostics about pattern matches to the consol.
/** Set to true to send diagnostics about pattern matches to the consol. */
private static final boolean DEBUG_MATCHES = false;
Get the match score of the given node.
Params:
  • xctxt – The XPath runtime context.
  • context – The node to be tested.
Throws:
Returns:NodeTest.SCORE_NODETEST, NodeTest.SCORE_NONE, NodeTest.SCORE_NSWILD, NodeTest.SCORE_QNAME, or NodeTest.SCORE_OTHER.
/** * Get the match score of the given node. * * @param xctxt The XPath runtime context. * @param context The node to be tested. * * @return {@link org.apache.xpath.patterns.NodeTest#SCORE_NODETEST}, * {@link org.apache.xpath.patterns.NodeTest#SCORE_NONE}, * {@link org.apache.xpath.patterns.NodeTest#SCORE_NSWILD}, * {@link org.apache.xpath.patterns.NodeTest#SCORE_QNAME}, or * {@link org.apache.xpath.patterns.NodeTest#SCORE_OTHER}. * * @throws javax.xml.transform.TransformerException */
public double getMatchScore(XPathContext xctxt, int context) throws javax.xml.transform.TransformerException { xctxt.pushCurrentNode(context); xctxt.pushCurrentExpressionNode(context); try { XObject score = execute(xctxt); return score.num(); } finally { xctxt.popCurrentNode(); xctxt.popCurrentExpressionNode(); } // return XPath.MATCH_SCORE_NONE; }
Set the axis that this step should follow.
Params:
  • axis – The Axis for this test, one of of Axes.ANCESTORORSELF, etc.
/** * Set the axis that this step should follow. * * * @param axis The Axis for this test, one of of Axes.ANCESTORORSELF, etc. */
public void setAxis(int axis) { m_axis = axis; }
Get the axis that this step follows.
Returns:The Axis for this test, one of of Axes.ANCESTORORSELF, etc.
/** * Get the axis that this step follows. * * * @return The Axis for this test, one of of Axes.ANCESTORORSELF, etc. */
public int getAxis() { return m_axis; } class PredOwner implements ExpressionOwner { int m_index; PredOwner(int index) { m_index = index; }
See Also:
  • getExpression.getExpression()
/** * @see ExpressionOwner#getExpression() */
public Expression getExpression() { return m_predicates[m_index]; }
See Also:
  • setExpression.setExpression(Expression)
/** * @see ExpressionOwner#setExpression(Expression) */
public void setExpression(Expression exp) { exp.exprSetParent(StepPattern.this); m_predicates[m_index] = exp; } }
See Also:
  • callVisitors.callVisitors(ExpressionOwner, XPathVisitor)
/** * @see org.apache.xpath.XPathVisitable#callVisitors(ExpressionOwner, XPathVisitor) */
public void callVisitors(ExpressionOwner owner, XPathVisitor visitor) { if(visitor.visitMatchPattern(owner, this)) { callSubtreeVisitors(visitor); } }
Call the visitors on the subtree. Factored out from callVisitors so it may be called by derived classes.
/** * Call the visitors on the subtree. Factored out from callVisitors * so it may be called by derived classes. */
protected void callSubtreeVisitors(XPathVisitor visitor) { if (null != m_predicates) { int n = m_predicates.length; for (int i = 0; i < n; i++) { ExpressionOwner predOwner = new PredOwner(i); if (visitor.visitPredicate(predOwner, m_predicates[i])) { m_predicates[i].callVisitors(predOwner, visitor); } } } if (null != m_relativePathPattern) { m_relativePathPattern.callVisitors(this, visitor); } }
See Also:
  • getExpression.getExpression()
/** * @see ExpressionOwner#getExpression() */
public Expression getExpression() { return m_relativePathPattern; }
See Also:
  • setExpression.setExpression(Expression)
/** * @see ExpressionOwner#setExpression(Expression) */
public void setExpression(Expression exp) { exp.exprSetParent(this); m_relativePathPattern = (StepPattern)exp; }
See Also:
  • deepEquals.deepEquals(Expression)
/** * @see Expression#deepEquals(Expression) */
public boolean deepEquals(Expression expr) { if(!super.deepEquals(expr)) return false; StepPattern sp = (StepPattern)expr; if (null != m_predicates) { int n = m_predicates.length; if ((null == sp.m_predicates) || (sp.m_predicates.length != n)) return false; for (int i = 0; i < n; i++) { if (!m_predicates[i].deepEquals(sp.m_predicates[i])) return false; } } else if (null != sp.m_predicates) return false; if(null != m_relativePathPattern) { if(!m_relativePathPattern.deepEquals(sp.m_relativePathPattern)) return false; } else if(sp.m_relativePathPattern != null) return false; return true; } }