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 three arguments.
  33  * @xsl.usage advanced
  34  */
  35 public class Function3Args extends Function2Args
  36 {
  37     static final long serialVersionUID = 7915240747161506646L;
  38 
  39   /** The third argument passed to the function (at index 2).
  40    *  @serial  */
  41   Expression m_arg2;
  42 
  43   /**
  44    * Return the third argument passed to the function (at index 2).
  45    *
  46    * @return An expression that represents the third argument passed to the
  47    *         function.
  48    */
  49   public Expression getArg2()
  50   {
  51     return m_arg2;
  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_arg2)
  68       m_arg2.fixupVariables(vars, globalsSize);
  69   }
  70 
  71   /**
  72    * Set an argument expression for a function.  This method is called by the
  73    * XPath compiler.
  74    *
  75    * @param arg non-null expression that represents the argument.
  76    * @param argNum The argument number index.
  77    *
  78    * @throws WrongNumberArgsException If the argNum parameter is greater than 2.
  79    */
  80   public void setArg(Expression arg, int argNum)
  81           throws WrongNumberArgsException
  82   {
  83 
  84     if (argNum < 2)
  85       super.setArg(arg, argNum);
  86     else if (2 == argNum)
  87     {
  88       m_arg2 = arg;
  89       arg.exprSetParent(this);
  90     }
  91     else
  92                   reportWrongNumberArgs();
  93   }
  94 
  95   /**
  96    * Check that the number of arguments passed to this function is correct.
  97    *
  98    *
  99    * @param argNum The number of arguments that is being passed to the function.
 100    *
 101    * @throws WrongNumberArgsException
 102    */
 103   public void checkNumberArgs(int argNum) throws WrongNumberArgsException
 104   {
 105     if (argNum != 3)
 106       reportWrongNumberArgs();
 107   }
 108 
 109   /**
 110    * Constructs and throws a WrongNumberArgException with the appropriate
 111    * message for this function object.
 112    *
 113    * @throws WrongNumberArgsException
 114    */
 115   protected void reportWrongNumberArgs() throws WrongNumberArgsException {
 116       throw new WrongNumberArgsException(XSLMessages.createXPATHMessage("three", null));
 117   }
 118 
 119   /**
 120    * Tell if this expression or it's subexpressions can traverse outside
 121    * the current subtree.
 122    *
 123    * @return true if traversal outside the context node's subtree can occur.
 124    */
 125    public boolean canTraverseOutsideSubtree()
 126    {
 127     return super.canTraverseOutsideSubtree()
 128     ? true : m_arg2.canTraverseOutsideSubtree();
 129    }
 130 
 131   class Arg2Owner implements ExpressionOwner
 132   {
 133     /**
 134      * @see ExpressionOwner#getExpression()
 135      */
 136     public Expression getExpression()
 137     {
 138       return m_arg2;
 139     }
 140 
 141 
 142     /**
 143      * @see ExpressionOwner#setExpression(Expression)
 144      */
 145     public void setExpression(Expression exp)
 146     {
 147         exp.exprSetParent(Function3Args.this);
 148         m_arg2 = exp;
 149     }
 150   }
 151 
 152 
 153   /**
 154    * @see com.sun.org.apache.xpath.internal.XPathVisitable#callVisitors(ExpressionOwner, XPathVisitor)
 155    */
 156   public void callArgVisitors(XPathVisitor visitor)
 157   {
 158         super.callArgVisitors(visitor);
 159         if(null != m_arg2)
 160                 m_arg2.callVisitors(new Arg2Owner(), visitor);
 161   }
 162 
 163   /**
 164    * @see Expression#deepEquals(Expression)
 165    */
 166   public boolean deepEquals(Expression expr)
 167   {
 168         if(!super.deepEquals(expr))
 169                 return false;
 170 
 171         if(null != m_arg2)
 172         {
 173                 if(null == ((Function3Args)expr).m_arg2)
 174                         return false;
 175 
 176                 if(!m_arg2.deepEquals(((Function3Args)expr).m_arg2))
 177                         return false;
 178         }
 179         else if (null != ((Function3Args)expr).m_arg2)
 180                 return false;
 181 
 182         return true;
 183   }
 184 
 185 
 186 }