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 }