1. /*
  2. * The Apache Software License, Version 1.1
  3. *
  4. *
  5. * Copyright (c) 1999 The Apache Software Foundation. All rights
  6. * reserved.
  7. *
  8. * Redistribution and use in source and binary forms, with or without
  9. * modification, are permitted provided that the following conditions
  10. * are met:
  11. *
  12. * 1. Redistributions of source code must retain the above copyright
  13. * notice, this list of conditions and the following disclaimer.
  14. *
  15. * 2. Redistributions in binary form must reproduce the above copyright
  16. * notice, this list of conditions and the following disclaimer in
  17. * the documentation and/or other materials provided with the
  18. * distribution.
  19. *
  20. * 3. The end-user documentation included with the redistribution,
  21. * if any, must include the following acknowledgment:
  22. * "This product includes software developed by the
  23. * Apache Software Foundation (http://www.apache.org/)."
  24. * Alternately, this acknowledgment may appear in the software itself,
  25. * if and wherever such third-party acknowledgments normally appear.
  26. *
  27. * 4. The names "Xalan" and "Apache Software Foundation" must
  28. * not be used to endorse or promote products derived from this
  29. * software without prior written permission. For written
  30. * permission, please contact apache@apache.org.
  31. *
  32. * 5. Products derived from this software may not be called "Apache",
  33. * nor may "Apache" appear in their name, without prior written
  34. * permission of the Apache Software Foundation.
  35. *
  36. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  37. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  38. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  39. * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
  40. * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  41. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  42. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  43. * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  44. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  45. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  46. * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  47. * SUCH DAMAGE.
  48. * ====================================================================
  49. *
  50. * This software consists of voluntary contributions made by many
  51. * individuals on behalf of the Apache Software Foundation and was
  52. * originally based on software copyright (c) 1999, Lotus
  53. * Development Corporation., http://www.lotus.com. For more
  54. * information on the Apache Software Foundation, please see
  55. * <http://www.apache.org/>.
  56. */
  57. package org.apache.xpath.patterns;
  58. import java.util.Vector;
  59. import javax.xml.transform.TransformerException;
  60. import org.apache.xml.dtm.DTM;
  61. import org.apache.xml.dtm.DTMIterator;
  62. import org.apache.xpath.Expression;
  63. import org.apache.xpath.ExpressionOwner;
  64. import org.apache.xpath.XPathContext;
  65. import org.apache.xpath.XPathVisitor;
  66. import org.apache.xpath.objects.XNumber;
  67. import org.apache.xpath.objects.XObject;
  68. import org.apache.xpath.patterns.StepPattern.PredOwner;
  69. /**
  70. * <meta name="usage" content="advanced"/>
  71. * Match pattern step that contains a function.
  72. */
  73. public class FunctionPattern extends StepPattern
  74. {
  75. /**
  76. * Construct a FunctionPattern from a
  77. * {@link org.apache.xpath.functions.Function expression}.
  78. *
  79. *
  80. * @param a should be a {@link org.apache.xpath.functions.Function expression}.
  81. *
  82. * NEEDSDOC @param expr
  83. */
  84. public FunctionPattern(Expression expr, int axis, int predaxis)
  85. {
  86. super(0, null, null, axis, predaxis);
  87. m_functionExpr = expr;
  88. }
  89. /**
  90. * Static calc of match score.
  91. */
  92. public final void calcScore()
  93. {
  94. m_score = SCORE_OTHER;
  95. if (null == m_targetString)
  96. calcTargetString();
  97. }
  98. /**
  99. * Should be a {@link org.apache.xpath.functions.Function expression}.
  100. * @serial
  101. */
  102. Expression m_functionExpr;
  103. /**
  104. * This function is used to fixup variables from QNames to stack frame
  105. * indexes at stylesheet build time.
  106. * @param vars List of QNames that correspond to variables. This list
  107. * should be searched backwards for the first qualified name that
  108. * corresponds to the variable reference qname. The position of the
  109. * QName in the vector from the start of the vector will be its position
  110. * in the stack frame (but variables above the globalsTop value will need
  111. * to be offset to the current stack frame).
  112. */
  113. public void fixupVariables(java.util.Vector vars, int globalsSize)
  114. {
  115. super.fixupVariables(vars, globalsSize);
  116. m_functionExpr.fixupVariables(vars, globalsSize);
  117. }
  118. /**
  119. * Test a node to see if it matches the given node test.
  120. *
  121. * @param xctxt XPath runtime context.
  122. *
  123. * @return {@link org.apache.xpath.patterns.NodeTest#SCORE_NODETEST},
  124. * {@link org.apache.xpath.patterns.NodeTest#SCORE_NONE},
  125. * {@link org.apache.xpath.patterns.NodeTest#SCORE_NSWILD},
  126. * {@link org.apache.xpath.patterns.NodeTest#SCORE_QNAME}, or
  127. * {@link org.apache.xpath.patterns.NodeTest#SCORE_OTHER}.
  128. *
  129. * @throws javax.xml.transform.TransformerException
  130. */
  131. public XObject execute(XPathContext xctxt, int context)
  132. throws javax.xml.transform.TransformerException
  133. {
  134. DTMIterator nl = m_functionExpr.asIterator(xctxt, context);
  135. XNumber score = SCORE_NONE;
  136. if (null != nl)
  137. {
  138. int n;
  139. while (DTM.NULL != (n = nl.nextNode()))
  140. {
  141. score = (n == context) ? SCORE_OTHER : SCORE_NONE;
  142. if (score == SCORE_OTHER)
  143. {
  144. context = n;
  145. break;
  146. }
  147. }
  148. // nl.detach();
  149. }
  150. nl.detach();
  151. return score;
  152. }
  153. /**
  154. * Test a node to see if it matches the given node test.
  155. *
  156. * @param xctxt XPath runtime context.
  157. *
  158. * @return {@link org.apache.xpath.patterns.NodeTest#SCORE_NODETEST},
  159. * {@link org.apache.xpath.patterns.NodeTest#SCORE_NONE},
  160. * {@link org.apache.xpath.patterns.NodeTest#SCORE_NSWILD},
  161. * {@link org.apache.xpath.patterns.NodeTest#SCORE_QNAME}, or
  162. * {@link org.apache.xpath.patterns.NodeTest#SCORE_OTHER}.
  163. *
  164. * @throws javax.xml.transform.TransformerException
  165. */
  166. public XObject execute(XPathContext xctxt, int context,
  167. DTM dtm, int expType)
  168. throws javax.xml.transform.TransformerException
  169. {
  170. DTMIterator nl = m_functionExpr.asIterator(xctxt, context);
  171. XNumber score = SCORE_NONE;
  172. if (null != nl)
  173. {
  174. int n;
  175. while (DTM.NULL != (n = nl.nextNode()))
  176. {
  177. score = (n == context) ? SCORE_OTHER : SCORE_NONE;
  178. if (score == SCORE_OTHER)
  179. {
  180. context = n;
  181. break;
  182. }
  183. }
  184. nl.detach();
  185. }
  186. return score;
  187. }
  188. /**
  189. * Test a node to see if it matches the given node test.
  190. *
  191. * @param xctxt XPath runtime context.
  192. *
  193. * @return {@link org.apache.xpath.patterns.NodeTest#SCORE_NODETEST},
  194. * {@link org.apache.xpath.patterns.NodeTest#SCORE_NONE},
  195. * {@link org.apache.xpath.patterns.NodeTest#SCORE_NSWILD},
  196. * {@link org.apache.xpath.patterns.NodeTest#SCORE_QNAME}, or
  197. * {@link org.apache.xpath.patterns.NodeTest#SCORE_OTHER}.
  198. *
  199. * @throws javax.xml.transform.TransformerException
  200. */
  201. public XObject execute(XPathContext xctxt)
  202. throws javax.xml.transform.TransformerException
  203. {
  204. int context = xctxt.getCurrentNode();
  205. DTMIterator nl = m_functionExpr.asIterator(xctxt, context);
  206. XNumber score = SCORE_NONE;
  207. if (null != nl)
  208. {
  209. int n;
  210. while (DTM.NULL != (n = nl.nextNode()))
  211. {
  212. score = (n == context) ? SCORE_OTHER : SCORE_NONE;
  213. if (score == SCORE_OTHER)
  214. {
  215. context = n;
  216. break;
  217. }
  218. }
  219. nl.detach();
  220. }
  221. return score;
  222. }
  223. class FunctionOwner implements ExpressionOwner
  224. {
  225. /**
  226. * @see ExpressionOwner#getExpression()
  227. */
  228. public Expression getExpression()
  229. {
  230. return m_functionExpr;
  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. * Call the visitor for the function.
  243. */
  244. protected void callSubtreeVisitors(XPathVisitor visitor)
  245. {
  246. m_functionExpr.callVisitors(new FunctionOwner(), visitor);
  247. super.callSubtreeVisitors(visitor);
  248. }
  249. }