📄 steppattern.java
字号:
/* * 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: StepPattern.java,v 1.2.4.2 2005/09/15 00:21:16 jeffsuttor Exp $ */package com.sun.org.apache.xpath.internal.patterns;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.DTMAxisTraverser;import com.sun.org.apache.xml.internal.dtm.DTMFilter;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.axes.SubContextList;import com.sun.org.apache.xpath.internal.compiler.PsuedoNames;import com.sun.org.apache.xpath.internal.objects.XObject;/** * 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. */ protected int m_axis; /** * 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. * * * @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 */ 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 com.sun.org.apache.xpath.internal.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. * * * @return local name or psuedo name of the node. * @see com.sun.org.apache.xpath.internal.compiler.PsuedoNames */ public String getTargetString() { return m_targetString; } /** * 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. * @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. * * * @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. * * * @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. * @return List of expression objects. */ public Expression[] getPredicates() { return m_predicates; } /** * 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. * * @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. * * * @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. * * * @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. * * * @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. */ 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. * * * @param xctxt XPath runtime context. * @param currentNode The current node context. * * @return {@link com.sun.org.apache.xpath.internal.patterns.NodeTest#SCORE_NODETEST}, * {@link com.sun.org.apache.xpath.internal.patterns.NodeTest#SCORE_NONE}, * {@link com.sun.org.apache.xpath.internal.patterns.NodeTest#SCORE_NSWILD}, * {@link com.sun.org.apache.xpath.internal.patterns.NodeTest#SCORE_QNAME}, or * {@link com.sun.org.apache.xpath.internal.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. * * * @param xctxt XPath runtime context. * * @return {@link com.sun.org.apache.xpath.internal.patterns.NodeTest#SCORE_NODETEST}, * {@link com.sun.org.apache.xpath.internal.patterns.NodeTest#SCORE_NONE}, * {@link com.sun.org.apache.xpath.internal.patterns.NodeTest#SCORE_NSWILD}, * {@link com.sun.org.apache.xpath.internal.patterns.NodeTest#SCORE_QNAME}, or * {@link com.sun.org.apache.xpath.internal.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. * * * @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 * * @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. * * * @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();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -