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