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    */
fixupVariables(java.util.Vector vars, int globalsSize)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    */
canTraverseOutsideSubtree()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    */
setLeftRight(Expression l, Expression r)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    */
execute(XPathContext xctxt)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    */
operate(XObject left, XObject right)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    */
getLeftOperand()137   public Expression getLeftOperand(){
138     return m_left;
139   }
140 
141   /** @return the right operand of binary operation, as an Expression.
142    */
getRightOperand()143   public Expression getRightOperand(){
144     return m_right;
145   }
146 
147   class LeftExprOwner implements ExpressionOwner
148   {
149     /**
150      * @see ExpressionOwner#getExpression()
151      */
getExpression()152     public Expression getExpression()
153     {
154       return m_left;
155     }
156 
157     /**
158      * @see ExpressionOwner#setExpression(Expression)
159      */
setExpression(Expression exp)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    */
callVisitors(ExpressionOwner owner, XPathVisitor visitor)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    */
getExpression()182   public Expression getExpression()
183   {
184     return m_right;
185   }
186 
187   /**
188    * @see ExpressionOwner#setExpression(Expression)
189    */
setExpression(Expression exp)190   public void setExpression(Expression exp)
191   {
192   	exp.exprSetParent(this);
193   	m_right = exp;
194   }
195 
196   /**
197    * @see Expression#deepEquals(Expression)
198    */
deepEquals(Expression expr)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