001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the "License"); 007 * you may not use this file except in compliance with the License. 008 * You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018 /* 019 * $Id: FunctionPattern.java 468655 2006-10-28 07:12:06Z minchau $ 020 */ 021 package org.apache.xpath.patterns; 022 023 import org.apache.xml.dtm.DTM; 024 import org.apache.xml.dtm.DTMIterator; 025 import org.apache.xpath.Expression; 026 import org.apache.xpath.ExpressionOwner; 027 import org.apache.xpath.XPathContext; 028 import org.apache.xpath.XPathVisitor; 029 import org.apache.xpath.objects.XNumber; 030 import org.apache.xpath.objects.XObject; 031 032 /** 033 * Match pattern step that contains a function. 034 * @xsl.usage advanced 035 */ 036 public class FunctionPattern extends StepPattern 037 { 038 static final long serialVersionUID = -5426793413091209944L; 039 040 /** 041 * Construct a FunctionPattern from a 042 * {@link org.apache.xpath.functions.Function expression}. 043 * 044 * NEEDSDOC @param expr 045 */ 046 public FunctionPattern(Expression expr, int axis, int predaxis) 047 { 048 049 super(0, null, null, axis, predaxis); 050 051 m_functionExpr = expr; 052 } 053 054 /** 055 * Static calc of match score. 056 */ 057 public final void calcScore() 058 { 059 060 m_score = SCORE_OTHER; 061 062 if (null == m_targetString) 063 calcTargetString(); 064 } 065 066 /** 067 * Should be a {@link org.apache.xpath.functions.Function expression}. 068 * @serial 069 */ 070 Expression m_functionExpr; 071 072 /** 073 * This function is used to fixup variables from QNames to stack frame 074 * indexes at stylesheet build time. 075 * @param vars List of QNames that correspond to variables. This list 076 * should be searched backwards for the first qualified name that 077 * corresponds to the variable reference qname. The position of the 078 * QName in the vector from the start of the vector will be its position 079 * in the stack frame (but variables above the globalsTop value will need 080 * to be offset to the current stack frame). 081 */ 082 public void fixupVariables(java.util.Vector vars, int globalsSize) 083 { 084 super.fixupVariables(vars, globalsSize); 085 m_functionExpr.fixupVariables(vars, globalsSize); 086 } 087 088 089 /** 090 * Test a node to see if it matches the given node test. 091 * 092 * @param xctxt XPath runtime context. 093 * 094 * @return {@link org.apache.xpath.patterns.NodeTest#SCORE_NODETEST}, 095 * {@link org.apache.xpath.patterns.NodeTest#SCORE_NONE}, 096 * {@link org.apache.xpath.patterns.NodeTest#SCORE_NSWILD}, 097 * {@link org.apache.xpath.patterns.NodeTest#SCORE_QNAME}, or 098 * {@link org.apache.xpath.patterns.NodeTest#SCORE_OTHER}. 099 * 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 }