steppattern.java

来自「java jdk 1.4的源码」· Java 代码 · 共 1,092 行 · 第 1/2 页

JAVA
1,092
字号
/* * The Apache Software License, Version 1.1 * * * Copyright (c) 1999 The Apache Software Foundation.  All rights  * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer.  * * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in *    the documentation and/or other materials provided with the *    distribution. * * 3. The end-user documentation included with the redistribution, *    if any, must include the following acknowledgment:   *       "This product includes software developed by the *        Apache Software Foundation (http://www.apache.org/)." *    Alternately, this acknowledgment may appear in the software itself, *    if and wherever such third-party acknowledgments normally appear. * * 4. The names "Xalan" and "Apache Software Foundation" must *    not be used to endorse or promote products derived from this *    software without prior written permission. For written  *    permission, please contact apache@apache.org. * * 5. Products derived from this software may not be called "Apache", *    nor may "Apache" appear in their name, without prior written *    permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation and was * originally based on software copyright (c) 1999, Lotus * Development Corporation., http://www.lotus.com.  For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. */package org.apache.xpath.patterns;import java.util.Vector;import javax.xml.transform.TransformerException;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;/** * <meta name="usage" content="advanced"/> * This class represents a single pattern match step. */public class StepPattern extends NodeTest implements SubContextList, ExpressionOwner{  /** 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 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.   *   *   * @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   */  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 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.   *   *   * @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.   *   *   * @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);

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?