Home | History | Annotate | Download | only in patterns
      1 /*
      2  * Licensed to the Apache Software Foundation (ASF) under one
      3  * or more contributor license agreements. See the NOTICE file
      4  * distributed with this work for additional information
      5  * regarding copyright ownership. The ASF licenses this file
      6  * to you under the Apache License, Version 2.0 (the  "License");
      7  * you may not use this file except in compliance with the License.
      8  * You may obtain a copy of the License at
      9  *
     10  *     http://www.apache.org/licenses/LICENSE-2.0
     11  *
     12  * Unless required by applicable law or agreed to in writing, software
     13  * distributed under the License is distributed on an "AS IS" BASIS,
     14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     15  * See the License for the specific language governing permissions and
     16  * limitations under the License.
     17  */
     18 /*
     19  * $Id: FunctionPattern.java 468655 2006-10-28 07:12:06Z minchau $
     20  */
     21 package org.apache.xpath.patterns;
     22 
     23 import org.apache.xml.dtm.DTM;
     24 import org.apache.xml.dtm.DTMIterator;
     25 import org.apache.xpath.Expression;
     26 import org.apache.xpath.ExpressionOwner;
     27 import org.apache.xpath.XPathContext;
     28 import org.apache.xpath.XPathVisitor;
     29 import org.apache.xpath.objects.XNumber;
     30 import org.apache.xpath.objects.XObject;
     31 
     32 /**
     33  * Match pattern step that contains a function.
     34  * @xsl.usage advanced
     35  */
     36 public class FunctionPattern extends StepPattern
     37 {
     38     static final long serialVersionUID = -5426793413091209944L;
     39 
     40   /**
     41    * Construct a FunctionPattern from a
     42    * {@link org.apache.xpath.functions.Function expression}.
     43    *
     44    * NEEDSDOC @param expr
     45    */
     46   public FunctionPattern(Expression expr, int axis, int predaxis)
     47   {
     48 
     49     super(0, null, null, axis, predaxis);
     50 
     51     m_functionExpr = expr;
     52   }
     53 
     54   /**
     55    * Static calc of match score.
     56    */
     57   public final void calcScore()
     58   {
     59 
     60     m_score = SCORE_OTHER;
     61 
     62     if (null == m_targetString)
     63       calcTargetString();
     64   }
     65 
     66   /**
     67    * Should be a {@link org.apache.xpath.functions.Function expression}.
     68    *  @serial
     69    */
     70   Expression m_functionExpr;
     71 
     72   /**
     73    * This function is used to fixup variables from QNames to stack frame
     74    * indexes at stylesheet build time.
     75    * @param vars List of QNames that correspond to variables.  This list
     76    * should be searched backwards for the first qualified name that
     77    * corresponds to the variable reference qname.  The position of the
     78    * QName in the vector from the start of the vector will be its position
     79    * in the stack frame (but variables above the globalsTop value will need
     80    * to be offset to the current stack frame).
     81    */
     82   public void fixupVariables(java.util.Vector vars, int globalsSize)
     83   {
     84     super.fixupVariables(vars, globalsSize);
     85     m_functionExpr.fixupVariables(vars, globalsSize);
     86   }
     87 
     88 
     89   /**
     90    * Test a node to see if it matches the given node test.
     91    *
     92    * @param xctxt XPath runtime context.
     93    *
     94    * @return {@link org.apache.xpath.patterns.NodeTest#SCORE_NODETEST},
     95    *         {@link org.apache.xpath.patterns.NodeTest#SCORE_NONE},
     96    *         {@link org.apache.xpath.patterns.NodeTest#SCORE_NSWILD},
     97    *         {@link org.apache.xpath.patterns.NodeTest#SCORE_QNAME}, or
     98    *         {@link org.apache.xpath.patterns.NodeTest#SCORE_OTHER}.
     99    *
    100    * @throws javax.xml.transform.TransformerException
    101    */
    102   public XObject execute(XPathContext xctxt, int context)
    103           throws javax.xml.transform.TransformerException
    104   {
    105 
    106     DTMIterator nl = m_functionExpr.asIterator(xctxt, context);
    107     XNumber score = SCORE_NONE;
    108 
    109     if (null != nl)
    110     {
    111       int n;
    112 
    113       while (DTM.NULL != (n = nl.nextNode()))
    114       {
    115         score = (n == context) ? SCORE_OTHER : SCORE_NONE;
    116 
    117         if (score == SCORE_OTHER)
    118         {
    119           context = n;
    120 
    121           break;
    122         }
    123       }
    124 
    125       // nl.detach();
    126     }
    127     nl.detach();
    128 
    129     return score;
    130   }
    131 
    132   /**
    133    * Test a node to see if it matches the given node test.
    134    *
    135    * @param xctxt XPath runtime context.
    136    *
    137    * @return {@link org.apache.xpath.patterns.NodeTest#SCORE_NODETEST},
    138    *         {@link org.apache.xpath.patterns.NodeTest#SCORE_NONE},
    139    *         {@link org.apache.xpath.patterns.NodeTest#SCORE_NSWILD},
    140    *         {@link org.apache.xpath.patterns.NodeTest#SCORE_QNAME}, or
    141    *         {@link org.apache.xpath.patterns.NodeTest#SCORE_OTHER}.
    142    *
    143    * @throws javax.xml.transform.TransformerException
    144    */
    145   public XObject execute(XPathContext xctxt, int context,
    146                          DTM dtm, int expType)
    147           throws javax.xml.transform.TransformerException
    148   {
    149 
    150     DTMIterator nl = m_functionExpr.asIterator(xctxt, context);
    151     XNumber score = SCORE_NONE;
    152 
    153     if (null != nl)
    154     {
    155       int n;
    156 
    157       while (DTM.NULL != (n = nl.nextNode()))
    158       {
    159         score = (n == context) ? SCORE_OTHER : SCORE_NONE;
    160 
    161         if (score == SCORE_OTHER)
    162         {
    163           context = n;
    164 
    165           break;
    166         }
    167       }
    168 
    169       nl.detach();
    170     }
    171 
    172     return score;
    173   }
    174 
    175   /**
    176    * Test a node to see if it matches the given node test.
    177    *
    178    * @param xctxt XPath runtime context.
    179    *
    180    * @return {@link org.apache.xpath.patterns.NodeTest#SCORE_NODETEST},
    181    *         {@link org.apache.xpath.patterns.NodeTest#SCORE_NONE},
    182    *         {@link org.apache.xpath.patterns.NodeTest#SCORE_NSWILD},
    183    *         {@link org.apache.xpath.patterns.NodeTest#SCORE_QNAME}, or
    184    *         {@link org.apache.xpath.patterns.NodeTest#SCORE_OTHER}.
    185    *
    186    * @throws javax.xml.transform.TransformerException
    187    */
    188   public XObject execute(XPathContext xctxt)
    189           throws javax.xml.transform.TransformerException
    190   {
    191 
    192     int context = xctxt.getCurrentNode();
    193     DTMIterator nl = m_functionExpr.asIterator(xctxt, context);
    194     XNumber score = SCORE_NONE;
    195 
    196     if (null != nl)
    197     {
    198       int n;
    199 
    200       while (DTM.NULL != (n = nl.nextNode()))
    201       {
    202         score = (n == context) ? SCORE_OTHER : SCORE_NONE;
    203 
    204         if (score == SCORE_OTHER)
    205         {
    206           context = n;
    207 
    208           break;
    209         }
    210       }
    211 
    212       nl.detach();
    213     }
    214 
    215     return score;
    216   }
    217 
    218   class FunctionOwner implements ExpressionOwner
    219   {
    220     /**
    221      * @see ExpressionOwner#getExpression()
    222      */
    223     public Expression getExpression()
    224     {
    225       return m_functionExpr;
    226     }
    227 
    228 
    229     /**
    230      * @see ExpressionOwner#setExpression(Expression)
    231      */
    232     public void setExpression(Expression exp)
    233     {
    234     	exp.exprSetParent(FunctionPattern.this);
    235     	m_functionExpr = exp;
    236     }
    237   }
    238 
    239   /**
    240    * Call the visitor for the function.
    241    */
    242   protected void callSubtreeVisitors(XPathVisitor visitor)
    243   {
    244     m_functionExpr.callVisitors(new FunctionOwner(), visitor);
    245     super.callSubtreeVisitors(visitor);
    246   }
    247 
    248 }
    249