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 java.util.List;
  30 
  31 /**
  32  * Base class for functions that accept two arguments.
  33  * @xsl.usage advanced
  34  */
  35 public class Function2Args extends FunctionOneArg
  36 {
  37     static final long serialVersionUID = 5574294996842710641L;
  38 
  39   /** The second argument passed to the function (at index 1).
  40    *  @serial  */
  41   Expression m_arg1;
  42 
  43   /**
  44    * Return the second argument passed to the function (at index 1).
  45    *
  46    * @return An expression that represents the second argument passed to the
  47    *         function.
  48    */
  49   public Expression getArg1()
  50   {
  51     return m_arg1;
  52   }
  53 
  54   /**
  55    * This function is used to fixup variables from QNames to stack frame
  56    * indexes at stylesheet build time.
  57    * @param vars List of QNames that correspond to variables.  This list
  58    * should be searched backwards for the first qualified name that
  59    * corresponds to the variable reference qname.  The position of the
  60    * QName in the vector from the start of the vector will be its position
  61    * in the stack frame (but variables above the globalsTop value will need
  62    * to be offset to the current stack frame).
  63    */
  64   public void fixupVariables(List<QName> vars, int globalsSize)
  65   {
  66     super.fixupVariables(vars, globalsSize);
  67     if(null != m_arg1)
  68       m_arg1.fixupVariables(vars, globalsSize);
  69   }
  70 
  71 
  72   /**
  73    * Set an argument expression for a function.  This method is called by the
  74    * XPath compiler.
  75    *
  76    * @param arg non-null expression that represents the argument.
  77    * @param argNum The argument number index.
  78    *
  79    * @throws WrongNumberArgsException If the argNum parameter is greater than 1.
  80    */
  81   public void setArg(Expression arg, int argNum)
  82           throws WrongNumberArgsException
  83   {
  84 
  85     // System.out.println("argNum: "+argNum);
  86     if (argNum == 0)
  87       super.setArg(arg, argNum);
  88     else if (1 == argNum)
  89     {
  90       m_arg1 = arg;
  91       arg.exprSetParent(this);
  92     }
  93     else
  94                   reportWrongNumberArgs();
  95   }
  96 
  97   /**
  98    * Check that the number of arguments passed to this function is correct.
  99    *
 100    *
 101    * @param argNum The number of arguments that is being passed to the function.
 102    *
 103    * @throws WrongNumberArgsException
 104    */
 105   public void checkNumberArgs(int argNum) throws WrongNumberArgsException
 106   {
 107     if (argNum != 2)
 108       reportWrongNumberArgs();
 109   }
 110 
 111   /**
 112    * Constructs and throws a WrongNumberArgException with the appropriate
 113    * message for this function object.
 114    *
 115    * @throws WrongNumberArgsException
 116    */
 117   protected void reportWrongNumberArgs() throws WrongNumberArgsException {
 118       throw new WrongNumberArgsException(XSLMessages.createXPATHMessage("two", null));
 119   }
 120 
 121   /**
 122    * Tell if this expression or it's subexpressions can traverse outside
 123    * the current subtree.
 124    *
 125    * @return true if traversal outside the context node's subtree can occur.
 126    */
 127    public boolean canTraverseOutsideSubtree()
 128    {
 129     return super.canTraverseOutsideSubtree()
 130     ? true : m_arg1.canTraverseOutsideSubtree();
 131    }
 132 
 133   class Arg1Owner implements ExpressionOwner
 134   {
 135     /**
 136      * @see ExpressionOwner#getExpression()
 137      */
 138     public Expression getExpression()
 139     {
 140       return m_arg1;
 141     }
 142 
 143 
 144     /**
 145      * @see ExpressionOwner#setExpression(Expression)
 146      */
 147     public void setExpression(Expression exp)
 148     {
 149         exp.exprSetParent(Function2Args.this);
 150         m_arg1 = exp;
 151     }
 152   }
 153 
 154 
 155   /**
 156    * @see com.sun.org.apache.xpath.internal.XPathVisitable#callVisitors(ExpressionOwner, XPathVisitor)
 157    */
 158   public void callArgVisitors(XPathVisitor visitor)
 159   {
 160         super.callArgVisitors(visitor);
 161         if(null != m_arg1)
 162                 m_arg1.callVisitors(new Arg1Owner(), visitor);
 163   }
 164 
 165   /**
 166    * @see Expression#deepEquals(Expression)
 167    */
 168   public boolean deepEquals(Expression expr)
 169   {
 170         if(!super.deepEquals(expr))
 171                 return false;
 172 
 173         if(null != m_arg1)
 174         {
 175                 if(null == ((Function2Args)expr).m_arg1)
 176                         return false;
 177 
 178                 if(!m_arg1.deepEquals(((Function2Args)expr).m_arg1))
 179                         return false;
 180         }
 181         else if(null != ((Function2Args)expr).m_arg1)
 182                 return false;
 183 
 184         return true;
 185   }
 186 
 187 }