001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements. See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership. The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the "License");
007 * you may not use this file except in compliance with the License.
008 * You may obtain a copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018 /*
019 * $Id: Function2Args.java 468655 2006-10-28 07:12:06Z minchau $
020 */
021 package org.apache.xpath.functions;
022
023 import org.apache.xalan.res.XSLMessages;
024 import org.apache.xpath.Expression;
025 import org.apache.xpath.ExpressionOwner;
026 import org.apache.xpath.XPathVisitor;
027
028 /**
029 * Base class for functions that accept two arguments.
030 * @xsl.usage advanced
031 */
032 public class Function2Args extends FunctionOneArg
033 {
034 static final long serialVersionUID = 5574294996842710641L;
035
036 /** The second argument passed to the function (at index 1).
037 * @serial */
038 Expression m_arg1;
039
040 /**
041 * Return the second argument passed to the function (at index 1).
042 *
043 * @return An expression that represents the second argument passed to the
044 * function.
045 */
046 public Expression getArg1()
047 {
048 return m_arg1;
049 }
050
051 /**
052 * This function is used to fixup variables from QNames to stack frame
053 * indexes at stylesheet build time.
054 * @param vars List of QNames that correspond to variables. This list
055 * should be searched backwards for the first qualified name that
056 * corresponds to the variable reference qname. The position of the
057 * QName in the vector from the start of the vector will be its position
058 * in the stack frame (but variables above the globalsTop value will need
059 * to be offset to the current stack frame).
060 */
061 public void fixupVariables(java.util.Vector vars, int globalsSize)
062 {
063 super.fixupVariables(vars, globalsSize);
064 if(null != m_arg1)
065 m_arg1.fixupVariables(vars, globalsSize);
066 }
067
068
069 /**
070 * Set an argument expression for a function. This method is called by the
071 * XPath compiler.
072 *
073 * @param arg non-null expression that represents the argument.
074 * @param argNum The argument number index.
075 *
076 * @throws WrongNumberArgsException If the argNum parameter is greater than 1.
077 */
078 public void setArg(Expression arg, int argNum)
079 throws WrongNumberArgsException
080 {
081
082 // System.out.println("argNum: "+argNum);
083 if (argNum == 0)
084 super.setArg(arg, argNum);
085 else if (1 == argNum)
086 {
087 m_arg1 = arg;
088 arg.exprSetParent(this);
089 }
090 else
091 reportWrongNumberArgs();
092 }
093
094 /**
095 * Check that the number of arguments passed to this function is correct.
096 *
097 *
098 * @param argNum The number of arguments that is being passed to the function.
099 *
100 * @throws WrongNumberArgsException
101 */
102 public void checkNumberArgs(int argNum) throws WrongNumberArgsException
103 {
104 if (argNum != 2)
105 reportWrongNumberArgs();
106 }
107
108 /**
109 * Constructs and throws a WrongNumberArgException with the appropriate
110 * message for this function object.
111 *
112 * @throws WrongNumberArgsException
113 */
114 protected void reportWrongNumberArgs() throws WrongNumberArgsException {
115 throw new WrongNumberArgsException(XSLMessages.createXPATHMessage("two", null));
116 }
117
118 /**
119 * Tell if this expression or it's subexpressions can traverse outside
120 * the current subtree.
121 *
122 * @return true if traversal outside the context node's subtree can occur.
123 */
124 public boolean canTraverseOutsideSubtree()
125 {
126 return super.canTraverseOutsideSubtree()
127 ? true : m_arg1.canTraverseOutsideSubtree();
128 }
129
130 class Arg1Owner implements ExpressionOwner
131 {
132 /**
133 * @see ExpressionOwner#getExpression()
134 */
135 public Expression getExpression()
136 {
137 return m_arg1;
138 }
139
140
141 /**
142 * @see ExpressionOwner#setExpression(Expression)
143 */
144 public void setExpression(Expression exp)
145 {
146 exp.exprSetParent(Function2Args.this);
147 m_arg1 = exp;
148 }
149 }
150
151
152 /**
153 * @see org.apache.xpath.XPathVisitable#callVisitors(ExpressionOwner, XPathVisitor)
154 */
155 public void callArgVisitors(XPathVisitor visitor)
156 {
157 super.callArgVisitors(visitor);
158 if(null != m_arg1)
159 m_arg1.callVisitors(new Arg1Owner(), visitor);
160 }
161
162 /**
163 * @see Expression#deepEquals(Expression)
164 */
165 public boolean deepEquals(Expression expr)
166 {
167 if(!super.deepEquals(expr))
168 return false;
169
170 if(null != m_arg1)
171 {
172 if(null == ((Function2Args)expr).m_arg1)
173 return false;
174
175 if(!m_arg1.deepEquals(((Function2Args)expr).m_arg1))
176 return false;
177 }
178 else if(null != ((Function2Args)expr).m_arg1)
179 return false;
180
181 return true;
182 }
183
184 }