Home | History | Annotate | Download | only in operations
      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: Operation.java 468655 2006-10-28 07:12:06Z minchau $
     20  */
     21 package org.apache.xpath.operations;
     22 
     23 import org.apache.xpath.Expression;
     24 import org.apache.xpath.ExpressionOwner;
     25 import org.apache.xpath.XPathContext;
     26 import org.apache.xpath.XPathVisitor;
     27 import org.apache.xpath.objects.XObject;
     28 
     29 /**
     30  * The baseclass for a binary operation.
     31  */
     32 public class Operation extends Expression implements ExpressionOwner
     33 {
     34     static final long serialVersionUID = -3037139537171050430L;
     35 
     36   /** The left operand expression.
     37    *  @serial */
     38   protected Expression m_left;
     39 
     40   /** The right operand expression.
     41    *  @serial */
     42   protected Expression m_right;
     43 
     44   /**
     45    * This function is used to fixup variables from QNames to stack frame
     46    * indexes at stylesheet build time.
     47    * @param vars List of QNames that correspond to variables.  This list
     48    * should be searched backwards for the first qualified name that
     49    * corresponds to the variable reference qname.  The position of the
     50    * QName in the vector from the start of the vector will be its position
     51    * in the stack frame (but variables above the globalsTop value will need
     52    * to be offset to the current stack frame).
     53    */
     54   public void fixupVariables(java.util.Vector vars, int globalsSize)
     55   {
     56     m_left.fixupVariables(vars, globalsSize);
     57     m_right.fixupVariables(vars, globalsSize);
     58   }
     59 
     60 
     61   /**
     62    * Tell if this expression or it's subexpressions can traverse outside
     63    * the current subtree.
     64    *
     65    * @return true if traversal outside the context node's subtree can occur.
     66    */
     67   public boolean canTraverseOutsideSubtree()
     68   {
     69 
     70     if (null != m_left && m_left.canTraverseOutsideSubtree())
     71       return true;
     72 
     73     if (null != m_right && m_right.canTraverseOutsideSubtree())
     74       return true;
     75 
     76     return false;
     77   }
     78 
     79   /**
     80    * Set the left and right operand expressions for this operation.
     81    *
     82    *
     83    * @param l The left expression operand.
     84    * @param r The right expression operand.
     85    */
     86   public void setLeftRight(Expression l, Expression r)
     87   {
     88     m_left = l;
     89     m_right = r;
     90     l.exprSetParent(this);
     91     r.exprSetParent(this);
     92   }
     93 
     94   /**
     95    * Execute a binary operation by calling execute on each of the operands,
     96    * and then calling the operate method on the derived class.
     97    *
     98    *
     99    * @param xctxt The runtime execution context.
    100    *
    101    * @return The XObject result of the operation.
    102    *
    103    * @throws javax.xml.transform.TransformerException
    104    */
    105   public XObject execute(XPathContext xctxt)
    106           throws javax.xml.transform.TransformerException
    107   {
    108 
    109     XObject left = m_left.execute(xctxt, true);
    110     XObject right = m_right.execute(xctxt, true);
    111 
    112     XObject result = operate(left, right);
    113     left.detach();
    114     right.detach();
    115     return result;
    116   }
    117 
    118   /**
    119    * Apply the operation to two operands, and return the result.
    120    *
    121    *
    122    * @param left non-null reference to the evaluated left operand.
    123    * @param right non-null reference to the evaluated right operand.
    124    *
    125    * @return non-null reference to the XObject that represents the result of the operation.
    126    *
    127    * @throws javax.xml.transform.TransformerException
    128    */
    129   public XObject operate(XObject left, XObject right)
    130           throws javax.xml.transform.TransformerException
    131   {
    132     return null;  // no-op
    133   }
    134 
    135   /** @return the left operand of binary operation, as an Expression.
    136    */
    137   public Expression getLeftOperand(){
    138     return m_left;
    139   }
    140 
    141   /** @return the right operand of binary operation, as an Expression.
    142    */
    143   public Expression getRightOperand(){
    144     return m_right;
    145   }
    146 
    147   class LeftExprOwner implements ExpressionOwner
    148   {
    149     /**
    150      * @see ExpressionOwner#getExpression()
    151      */
    152     public Expression getExpression()
    153     {
    154       return m_left;
    155     }
    156 
    157     /**
    158      * @see ExpressionOwner#setExpression(Expression)
    159      */
    160     public void setExpression(Expression exp)
    161     {
    162     	exp.exprSetParent(Operation.this);
    163     	m_left = exp;
    164     }
    165   }
    166 
    167   /**
    168    * @see org.apache.xpath.XPathVisitable#callVisitors(ExpressionOwner, XPathVisitor)
    169    */
    170   public void callVisitors(ExpressionOwner owner, XPathVisitor visitor)
    171   {
    172   	if(visitor.visitBinaryOperation(owner, this))
    173   	{
    174   		m_left.callVisitors(new LeftExprOwner(), visitor);
    175   		m_right.callVisitors(this, visitor);
    176   	}
    177   }
    178 
    179   /**
    180    * @see ExpressionOwner#getExpression()
    181    */
    182   public Expression getExpression()
    183   {
    184     return m_right;
    185   }
    186 
    187   /**
    188    * @see ExpressionOwner#setExpression(Expression)
    189    */
    190   public void setExpression(Expression exp)
    191   {
    192   	exp.exprSetParent(this);
    193   	m_right = exp;
    194   }
    195 
    196   /**
    197    * @see Expression#deepEquals(Expression)
    198    */
    199   public boolean deepEquals(Expression expr)
    200   {
    201   	if(!isSameClass(expr))
    202   		return false;
    203 
    204   	if(!m_left.deepEquals(((Operation)expr).m_left))
    205   		return false;
    206 
    207   	if(!m_right.deepEquals(((Operation)expr).m_right))
    208   		return false;
    209 
    210   	return true;
    211   }
    212 }
    213