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