001: /*
002: * Copyright 1999-2004 The Apache Software Foundation.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: /*
017: * $Id: Operation.java,v 1.14 2005/01/23 01:08:22 mcnamara Exp $
018: */
019: package org.apache.xpath.operations;
020:
021: import org.apache.xpath.Expression;
022: import org.apache.xpath.ExpressionOwner;
023: import org.apache.xpath.XPathContext;
024: import org.apache.xpath.XPathVisitor;
025: import org.apache.xpath.objects.XObject;
026:
027: /**
028: * The baseclass for a binary operation.
029: */
030: public class Operation extends Expression implements ExpressionOwner {
031: static final long serialVersionUID = -3037139537171050430L;
032:
033: /** The left operand expression.
034: * @serial */
035: protected Expression m_left;
036:
037: /** The right operand expression.
038: * @serial */
039: protected Expression m_right;
040:
041: /**
042: * This function is used to fixup variables from QNames to stack frame
043: * indexes at stylesheet build time.
044: * @param vars List of QNames that correspond to variables. This list
045: * should be searched backwards for the first qualified name that
046: * corresponds to the variable reference qname. The position of the
047: * QName in the vector from the start of the vector will be its position
048: * in the stack frame (but variables above the globalsTop value will need
049: * to be offset to the current stack frame).
050: */
051: public void fixupVariables(java.util.Vector vars, int globalsSize) {
052: m_left.fixupVariables(vars, globalsSize);
053: m_right.fixupVariables(vars, globalsSize);
054: }
055:
056: /**
057: * Tell if this expression or it's subexpressions can traverse outside
058: * the current subtree.
059: *
060: * @return true if traversal outside the context node's subtree can occur.
061: */
062: public boolean canTraverseOutsideSubtree() {
063:
064: if (null != m_left && m_left.canTraverseOutsideSubtree())
065: return true;
066:
067: if (null != m_right && m_right.canTraverseOutsideSubtree())
068: return true;
069:
070: return false;
071: }
072:
073: /**
074: * Set the left and right operand expressions for this operation.
075: *
076: *
077: * @param l The left expression operand.
078: * @param r The right expression operand.
079: */
080: public void setLeftRight(Expression l, Expression r) {
081: m_left = l;
082: m_right = r;
083: l.exprSetParent(this );
084: r.exprSetParent(this );
085: }
086:
087: /**
088: * Execute a binary operation by calling execute on each of the operands,
089: * and then calling the operate method on the derived class.
090: *
091: *
092: * @param xctxt The runtime execution context.
093: *
094: * @return The XObject result of the operation.
095: *
096: * @throws javax.xml.transform.TransformerException
097: */
098: public XObject execute(XPathContext xctxt)
099: throws javax.xml.transform.TransformerException {
100:
101: XObject left = m_left.execute(xctxt, true);
102: XObject right = m_right.execute(xctxt, true);
103:
104: XObject result = operate(left, right);
105: left.detach();
106: right.detach();
107: return result;
108: }
109:
110: /**
111: * Apply the operation to two operands, and return the result.
112: *
113: *
114: * @param left non-null reference to the evaluated left operand.
115: * @param right non-null reference to the evaluated right operand.
116: *
117: * @return non-null reference to the XObject that represents the result of the operation.
118: *
119: * @throws javax.xml.transform.TransformerException
120: */
121: public XObject operate(XObject left, XObject right)
122: throws javax.xml.transform.TransformerException {
123: return null; // no-op
124: }
125:
126: /** @return the left operand of binary operation, as an Expression.
127: */
128: public Expression getLeftOperand() {
129: return m_left;
130: }
131:
132: /** @return the right operand of binary operation, as an Expression.
133: */
134: public Expression getRightOperand() {
135: return m_right;
136: }
137:
138: class LeftExprOwner implements ExpressionOwner {
139: /**
140: * @see ExpressionOwner#getExpression()
141: */
142: public Expression getExpression() {
143: return m_left;
144: }
145:
146: /**
147: * @see ExpressionOwner#setExpression(Expression)
148: */
149: public void setExpression(Expression exp) {
150: exp.exprSetParent(Operation.this );
151: m_left = exp;
152: }
153: }
154:
155: /**
156: * @see org.apache.xpath.XPathVisitable#callVisitors(ExpressionOwner, XPathVisitor)
157: */
158: public void callVisitors(ExpressionOwner owner, XPathVisitor visitor) {
159: if (visitor.visitBinaryOperation(owner, this )) {
160: m_left.callVisitors(new LeftExprOwner(), visitor);
161: m_right.callVisitors(this , visitor);
162: }
163: }
164:
165: /**
166: * @see ExpressionOwner#getExpression()
167: */
168: public Expression getExpression() {
169: return m_right;
170: }
171:
172: /**
173: * @see ExpressionOwner#setExpression(Expression)
174: */
175: public void setExpression(Expression exp) {
176: exp.exprSetParent(this );
177: m_right = exp;
178: }
179:
180: /**
181: * @see Expression#deepEquals(Expression)
182: */
183: public boolean deepEquals(Expression expr) {
184: if (!isSameClass(expr))
185: return false;
186:
187: if (!m_left.deepEquals(((Operation) expr).m_left))
188: return false;
189:
190: if (!m_right.deepEquals(((Operation) expr).m_right))
191: return false;
192:
193: return true;
194: }
195: }
|