1/* 2 * reserved comment block 3 * DO NOT REMOVE OR ALTER! 4 */ 5/* 6 * Licensed to the Apache Software Foundation (ASF) under one or more 7 * contributor license agreements. See the NOTICE file distributed with 8 * this work for additional information regarding copyright ownership. 9 * The ASF licenses this file to You under the Apache License, Version 2.0 10 * (the "License"); you may not use this file except in compliance with 11 * the License. You may obtain a copy of the License at 12 * 13 * http://www.apache.org/licenses/LICENSE-2.0 14 * 15 * Unless required by applicable law or agreed to in writing, software 16 * distributed under the License is distributed on an "AS IS" BASIS, 17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 * See the License for the specific language governing permissions and 19 * limitations under the License. 20 */ 21 22package com.sun.org.apache.xpath.internal.functions; 23 24import com.sun.org.apache.xalan.internal.res.XSLMessages; 25import com.sun.org.apache.xpath.internal.Expression; 26import com.sun.org.apache.xpath.internal.ExpressionOwner; 27import com.sun.org.apache.xpath.internal.XPathVisitor; 28import com.sun.org.apache.xpath.internal.res.XPATHErrorResources; 29 30/** 31 * Base class for functions that accept an undetermined number of multiple 32 * arguments. 33 * @xsl.usage advanced 34 */ 35public class FunctionMultiArgs extends Function3Args 36{ 37 static final long serialVersionUID = 7117257746138417181L; 38 39 /** Argument expressions that are at index 3 or greater. 40 * @serial */ 41 Expression[] m_args; 42 43 /** 44 * Return an expression array containing arguments at index 3 or greater. 45 * 46 * @return An array that contains the arguments at index 3 or greater. 47 */ 48 public Expression[] getArgs() 49 { 50 return m_args; 51 } 52 53 /** 54 * Set an argument expression for a function. This method is called by the 55 * XPath compiler. 56 * 57 * @param arg non-null expression that represents the argument. 58 * @param argNum The argument number index. 59 * 60 * @throws WrongNumberArgsException If a derived class determines that the 61 * number of arguments is incorrect. 62 */ 63 public void setArg(Expression arg, int argNum) 64 throws WrongNumberArgsException 65 { 66 67 if (argNum < 3) 68 super.setArg(arg, argNum); 69 else 70 { 71 if (null == m_args) 72 { 73 m_args = new Expression[1]; 74 m_args[0] = arg; 75 } 76 else 77 { 78 79 // Slow but space conservative. 80 Expression[] args = new Expression[m_args.length + 1]; 81 82 System.arraycopy(m_args, 0, args, 0, m_args.length); 83 84 args[m_args.length] = arg; 85 m_args = args; 86 } 87 arg.exprSetParent(this); 88 } 89 } 90 91 /** 92 * This function is used to fixup variables from QNames to stack frame 93 * indexes at stylesheet build time. 94 * @param vars List of QNames that correspond to variables. This list 95 * should be searched backwards for the first qualified name that 96 * corresponds to the variable reference qname. The position of the 97 * QName in the vector from the start of the vector will be its position 98 * in the stack frame (but variables above the globalsTop value will need 99 * to be offset to the current stack frame). 100 */ 101 public void fixupVariables(java.util.Vector vars, int globalsSize) 102 { 103 super.fixupVariables(vars, globalsSize); 104 if(null != m_args) 105 { 106 for (int i = 0; i < m_args.length; i++) 107 { 108 m_args[i].fixupVariables(vars, globalsSize); 109 } 110 } 111 } 112 113 /** 114 * Check that the number of arguments passed to this function is correct. 115 * 116 * 117 * @param argNum The number of arguments that is being passed to the function. 118 * 119 * @throws WrongNumberArgsException 120 */ 121 public void checkNumberArgs(int argNum) throws WrongNumberArgsException{} 122 123 /** 124 * Constructs and throws a WrongNumberArgException with the appropriate 125 * message for this function object. This class supports an arbitrary 126 * number of arguments, so this method must never be called. 127 * 128 * @throws WrongNumberArgsException 129 */ 130 protected void reportWrongNumberArgs() throws WrongNumberArgsException { 131 String fMsg = XSLMessages.createXPATHMessage( 132 XPATHErrorResources.ER_INCORRECT_PROGRAMMER_ASSERTION, 133 new Object[]{ "Programmer's assertion: the method FunctionMultiArgs.reportWrongNumberArgs() should never be called." }); 134 135 throw new RuntimeException(fMsg); 136 } 137 138 /** 139 * Tell if this expression or it's subexpressions can traverse outside 140 * the current subtree. 141 * 142 * @return true if traversal outside the context node's subtree can occur. 143 */ 144 public boolean canTraverseOutsideSubtree() 145 { 146 147 if (super.canTraverseOutsideSubtree()) 148 return true; 149 else 150 { 151 int n = m_args.length; 152 153 for (int i = 0; i < n; i++) 154 { 155 if (m_args[i].canTraverseOutsideSubtree()) 156 return true; 157 } 158 159 return false; 160 } 161 } 162 163 class ArgMultiOwner implements ExpressionOwner 164 { 165 int m_argIndex; 166 167 ArgMultiOwner(int index) 168 { 169 m_argIndex = index; 170 } 171 172 /** 173 * @see ExpressionOwner#getExpression() 174 */ 175 public Expression getExpression() 176 { 177 return m_args[m_argIndex]; 178 } 179 180 181 /** 182 * @see ExpressionOwner#setExpression(Expression) 183 */ 184 public void setExpression(Expression exp) 185 { 186 exp.exprSetParent(FunctionMultiArgs.this); 187 m_args[m_argIndex] = exp; 188 } 189 } 190 191 192 /** 193 * @see com.sun.org.apache.xpath.internal.XPathVisitable#callVisitors(ExpressionOwner, XPathVisitor) 194 */ 195 public void callArgVisitors(XPathVisitor visitor) 196 { 197 super.callArgVisitors(visitor); 198 if (null != m_args) 199 { 200 int n = m_args.length; 201 for (int i = 0; i < n; i++) 202 { 203 m_args[i].callVisitors(new ArgMultiOwner(i), visitor); 204 } 205 } 206 } 207 208 /** 209 * @see Expression#deepEquals(Expression) 210 */ 211 public boolean deepEquals(Expression expr) 212 { 213 if (!super.deepEquals(expr)) 214 return false; 215 216 FunctionMultiArgs fma = (FunctionMultiArgs) expr; 217 if (null != m_args) 218 { 219 int n = m_args.length; 220 if ((null == fma) || (fma.m_args.length != n)) 221 return false; 222 223 for (int i = 0; i < n; i++) 224 { 225 if (!m_args[i].deepEquals(fma.m_args[i])) 226 return false; 227 } 228 229 } 230 else if (null != fma.m_args) 231 { 232 return false; 233 } 234 235 return true; 236 } 237} 238