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 */ FunctionPattern(Expression expr, int axis, int predaxis)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 */ calcScore()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 */ fixupVariables(java.util.Vector vars, int globalsSize)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 */ execute(XPathContext xctxt, int context)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 */ execute(XPathContext xctxt, int context, DTM dtm, int expType)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 */ execute(XPathContext xctxt)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 */ getExpression()223 public Expression getExpression() 224 { 225 return m_functionExpr; 226 } 227 228 229 /** 230 * @see ExpressionOwner#setExpression(Expression) 231 */ setExpression(Expression exp)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 */ callSubtreeVisitors(XPathVisitor visitor)242 protected void callSubtreeVisitors(XPathVisitor visitor) 243 { 244 m_functionExpr.callVisitors(new FunctionOwner(), visitor); 245 super.callSubtreeVisitors(visitor); 246 } 247 248 } 249