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