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