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    }