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