1/*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the  "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 *     http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18/*
19 * $Id: Function2Args.java 468655 2006-10-28 07:12:06Z minchau $
20 */
21package org.apache.xpath.functions;
22
23import org.apache.xalan.res.XSLMessages;
24import org.apache.xpath.Expression;
25import org.apache.xpath.ExpressionOwner;
26import org.apache.xpath.XPathVisitor;
27
28/**
29 * Base class for functions that accept two arguments.
30 * @xsl.usage advanced
31 */
32public class Function2Args extends FunctionOneArg
33{
34    static final long serialVersionUID = 5574294996842710641L;
35
36  /** The second argument passed to the function (at index 1).
37   *  @serial  */
38  Expression m_arg1;
39
40  /**
41   * Return the second argument passed to the function (at index 1).
42   *
43   * @return An expression that represents the second argument passed to the
44   *         function.
45   */
46  public Expression getArg1()
47  {
48    return m_arg1;
49  }
50
51  /**
52   * This function is used to fixup variables from QNames to stack frame
53   * indexes at stylesheet build time.
54   * @param vars List of QNames that correspond to variables.  This list
55   * should be searched backwards for the first qualified name that
56   * corresponds to the variable reference qname.  The position of the
57   * QName in the vector from the start of the vector will be its position
58   * in the stack frame (but variables above the globalsTop value will need
59   * to be offset to the current stack frame).
60   */
61  public void fixupVariables(java.util.Vector vars, int globalsSize)
62  {
63    super.fixupVariables(vars, globalsSize);
64    if(null != m_arg1)
65      m_arg1.fixupVariables(vars, globalsSize);
66  }
67
68
69  /**
70   * Set an argument expression for a function.  This method is called by the
71   * XPath compiler.
72   *
73   * @param arg non-null expression that represents the argument.
74   * @param argNum The argument number index.
75   *
76   * @throws WrongNumberArgsException If the argNum parameter is greater than 1.
77   */
78  public void setArg(Expression arg, int argNum)
79          throws WrongNumberArgsException
80  {
81
82    // System.out.println("argNum: "+argNum);
83    if (argNum == 0)
84      super.setArg(arg, argNum);
85    else if (1 == argNum)
86    {
87      m_arg1 = arg;
88      arg.exprSetParent(this);
89    }
90    else
91		  reportWrongNumberArgs();
92  }
93
94  /**
95   * Check that the number of arguments passed to this function is correct.
96   *
97   *
98   * @param argNum The number of arguments that is being passed to the function.
99   *
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}
185