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: FunctionMultiArgs.java,v 1.14 2004/02/17 04:34:01 minchau Exp $
  18. */
  19. package com.sun.org.apache.xpath.internal.functions;
  20. import com.sun.org.apache.xalan.internal.res.XSLMessages;
  21. import com.sun.org.apache.xpath.internal.Expression;
  22. import com.sun.org.apache.xpath.internal.ExpressionOwner;
  23. import com.sun.org.apache.xpath.internal.XPathVisitor;
  24. import com.sun.org.apache.xpath.internal.res.XPATHErrorResources;
  25. /**
  26. * Base class for functions that accept an undetermined number of multiple
  27. * arguments.
  28. * @xsl.usage advanced
  29. */
  30. public class FunctionMultiArgs extends Function3Args
  31. {
  32. /** Argument expressions that are at index 3 or greater.
  33. * @serial */
  34. Expression[] m_args;
  35. /**
  36. * Return an expression array containing arguments at index 3 or greater.
  37. *
  38. * @return An array that contains the arguments at index 3 or greater.
  39. */
  40. public Expression[] getArgs()
  41. {
  42. return m_args;
  43. }
  44. /**
  45. * Set an argument expression for a function. This method is called by the
  46. * XPath compiler.
  47. *
  48. * @param arg non-null expression that represents the argument.
  49. * @param argNum The argument number index.
  50. *
  51. * @throws WrongNumberArgsException If a derived class determines that the
  52. * number of arguments is incorrect.
  53. */
  54. public void setArg(Expression arg, int argNum)
  55. throws WrongNumberArgsException
  56. {
  57. if (argNum < 3)
  58. super.setArg(arg, argNum);
  59. else
  60. {
  61. if (null == m_args)
  62. {
  63. m_args = new Expression[1];
  64. m_args[0] = arg;
  65. }
  66. else
  67. {
  68. // Slow but space conservative.
  69. Expression[] args = new Expression[m_args.length + 1];
  70. System.arraycopy(m_args, 0, args, 0, m_args.length);
  71. args[m_args.length] = arg;
  72. m_args = args;
  73. }
  74. arg.exprSetParent(this);
  75. }
  76. }
  77. /**
  78. * This function is used to fixup variables from QNames to stack frame
  79. * indexes at stylesheet build time.
  80. * @param vars List of QNames that correspond to variables. This list
  81. * should be searched backwards for the first qualified name that
  82. * corresponds to the variable reference qname. The position of the
  83. * QName in the vector from the start of the vector will be its position
  84. * in the stack frame (but variables above the globalsTop value will need
  85. * to be offset to the current stack frame).
  86. */
  87. public void fixupVariables(java.util.Vector vars, int globalsSize)
  88. {
  89. super.fixupVariables(vars, globalsSize);
  90. if(null != m_args)
  91. {
  92. for (int i = 0; i < m_args.length; i++)
  93. {
  94. m_args[i].fixupVariables(vars, globalsSize);
  95. }
  96. }
  97. }
  98. /**
  99. * Check that the number of arguments passed to this function is correct.
  100. *
  101. *
  102. * @param argNum The number of arguments that is being passed to the function.
  103. *
  104. * @throws WrongNumberArgsException
  105. */
  106. public void checkNumberArgs(int argNum) throws WrongNumberArgsException{}
  107. /**
  108. * Constructs and throws a WrongNumberArgException with the appropriate
  109. * message for this function object. This class supports an arbitrary
  110. * number of arguments, so this method must never be called.
  111. *
  112. * @throws WrongNumberArgsException
  113. */
  114. protected void reportWrongNumberArgs() throws WrongNumberArgsException {
  115. String fMsg = XSLMessages.createXPATHMessage(
  116. XPATHErrorResources.ER_INCORRECT_PROGRAMMER_ASSERTION,
  117. new Object[]{ "Programmer's assertion: the method FunctionMultiArgs.reportWrongNumberArgs() should never be called." });
  118. throw new RuntimeException(fMsg);
  119. }
  120. /**
  121. * Tell if this expression or it's subexpressions can traverse outside
  122. * the current subtree.
  123. *
  124. * @return true if traversal outside the context node's subtree can occur.
  125. */
  126. public boolean canTraverseOutsideSubtree()
  127. {
  128. if (super.canTraverseOutsideSubtree())
  129. return true;
  130. else
  131. {
  132. int n = m_args.length;
  133. for (int i = 0; i < n; i++)
  134. {
  135. if (m_args[i].canTraverseOutsideSubtree())
  136. return true;
  137. }
  138. return false;
  139. }
  140. }
  141. class ArgMultiOwner implements ExpressionOwner
  142. {
  143. int m_argIndex;
  144. ArgMultiOwner(int index)
  145. {
  146. m_argIndex = index;
  147. }
  148. /**
  149. * @see ExpressionOwner#getExpression()
  150. */
  151. public Expression getExpression()
  152. {
  153. return m_args[m_argIndex];
  154. }
  155. /**
  156. * @see ExpressionOwner#setExpression(Expression)
  157. */
  158. public void setExpression(Expression exp)
  159. {
  160. exp.exprSetParent(FunctionMultiArgs.this);
  161. m_args[m_argIndex] = exp;
  162. }
  163. }
  164. /**
  165. * @see XPathVisitable#callVisitors(ExpressionOwner, XPathVisitor)
  166. */
  167. public void callArgVisitors(XPathVisitor visitor)
  168. {
  169. super.callArgVisitors(visitor);
  170. if (null != m_args)
  171. {
  172. int n = m_args.length;
  173. for (int i = 0; i < n; i++)
  174. {
  175. m_args[i].callVisitors(new ArgMultiOwner(i), visitor);
  176. }
  177. }
  178. }
  179. /**
  180. * @see Expression#deepEquals(Expression)
  181. */
  182. public boolean deepEquals(Expression expr)
  183. {
  184. if (!super.deepEquals(expr))
  185. return false;
  186. FunctionMultiArgs fma = (FunctionMultiArgs) expr;
  187. if (null != m_args)
  188. {
  189. int n = m_args.length;
  190. if ((null == fma) || (fma.m_args.length != n))
  191. return false;
  192. for (int i = 0; i < n; i++)
  193. {
  194. if (!m_args[i].deepEquals(fma.m_args[i]))
  195. return false;
  196. }
  197. }
  198. else if (null != fma.m_args)
  199. {
  200. return false;
  201. }
  202. return true;
  203. }
  204. }