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: Function3Args.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 three arguments.
030     * @xsl.usage advanced
031     */
032    public class Function3Args extends Function2Args
033    {
034        static final long serialVersionUID = 7915240747161506646L;
035    
036      /** The third argument passed to the function (at index 2).
037       *  @serial  */
038      Expression m_arg2;
039    
040      /**
041       * Return the third argument passed to the function (at index 2).
042       *
043       * @return An expression that represents the third argument passed to the 
044       *         function.
045       */
046      public Expression getArg2()
047      {
048        return m_arg2;
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_arg2)
065          m_arg2.fixupVariables(vars, globalsSize);
066      }
067    
068      /**
069       * Set an argument expression for a function.  This method is called by the 
070       * XPath compiler.
071       *
072       * @param arg non-null expression that represents the argument.
073       * @param argNum The argument number index.
074       *
075       * @throws WrongNumberArgsException If the argNum parameter is greater than 2.
076       */
077      public void setArg(Expression arg, int argNum)
078              throws WrongNumberArgsException
079      {
080    
081        if (argNum < 2)
082          super.setArg(arg, argNum);
083        else if (2 == argNum)
084        {
085          m_arg2 = arg;
086          arg.exprSetParent(this);
087        }
088        else
089                      reportWrongNumberArgs();
090      }
091    
092      /**
093       * Check that the number of arguments passed to this function is correct. 
094       *
095       *
096       * @param argNum The number of arguments that is being passed to the function.
097       *
098       * @throws WrongNumberArgsException
099       */
100      public void checkNumberArgs(int argNum) throws WrongNumberArgsException
101      {
102        if (argNum != 3)
103          reportWrongNumberArgs();
104      }
105    
106      /**
107       * Constructs and throws a WrongNumberArgException with the appropriate
108       * message for this function object.
109       *
110       * @throws WrongNumberArgsException
111       */
112      protected void reportWrongNumberArgs() throws WrongNumberArgsException {
113          throw new WrongNumberArgsException(XSLMessages.createXPATHMessage("three", null));
114      }
115      
116      /**
117       * Tell if this expression or it's subexpressions can traverse outside 
118       * the current subtree.
119       * 
120       * @return true if traversal outside the context node's subtree can occur.
121       */
122       public boolean canTraverseOutsideSubtree()
123       {
124        return super.canTraverseOutsideSubtree() 
125        ? true : m_arg2.canTraverseOutsideSubtree();
126       }
127       
128      class Arg2Owner implements ExpressionOwner
129      {
130        /**
131         * @see ExpressionOwner#getExpression()
132         */
133        public Expression getExpression()
134        {
135          return m_arg2;
136        }
137    
138    
139        /**
140         * @see ExpressionOwner#setExpression(Expression)
141         */
142        public void setExpression(Expression exp)
143        {
144            exp.exprSetParent(Function3Args.this);
145            m_arg2 = exp;
146        }
147      }
148    
149       
150      /**
151       * @see org.apache.xpath.XPathVisitable#callVisitors(ExpressionOwner, XPathVisitor)
152       */
153      public void callArgVisitors(XPathVisitor visitor)
154      {
155            super.callArgVisitors(visitor);
156            if(null != m_arg2)
157                    m_arg2.callVisitors(new Arg2Owner(), visitor);
158      }
159    
160      /**
161       * @see Expression#deepEquals(Expression)
162       */
163      public boolean deepEquals(Expression expr)
164      {
165            if(!super.deepEquals(expr))
166                    return false;
167                    
168            if(null != m_arg2)
169            {
170                    if(null == ((Function3Args)expr).m_arg2)
171                            return false;
172    
173                    if(!m_arg2.deepEquals(((Function3Args)expr).m_arg2))
174                            return false;
175            }
176            else if (null != ((Function3Args)expr).m_arg2)
177                    return false;
178                    
179            return true;
180      }
181    
182    
183    }