1 /* 2 * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. 3 */ 4 /* 5 * Licensed to the Apache Software Foundation (ASF) under one or more 6 * contributor license agreements. See the NOTICE file distributed with 7 * this work for additional information regarding copyright ownership. 8 * The ASF licenses this file to You under the Apache License, Version 2.0 9 * (the "License"); you may not use this file except in compliance with 10 * the License. You may obtain a copy of the License at 11 * 12 * http://www.apache.org/licenses/LICENSE-2.0 13 * 14 * Unless required by applicable law or agreed to in writing, software 15 * distributed under the License is distributed on an "AS IS" BASIS, 16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 * See the License for the specific language governing permissions and 18 * limitations under the License. 19 */ 20 21 package com.sun.org.apache.xpath.internal.operations; 22 23 import com.sun.org.apache.xml.internal.utils.QName; 24 import com.sun.org.apache.xpath.internal.Expression; 25 import com.sun.org.apache.xpath.internal.ExpressionOwner; 26 import com.sun.org.apache.xpath.internal.XPathContext; 27 import com.sun.org.apache.xpath.internal.XPathVisitor; 28 import com.sun.org.apache.xpath.internal.objects.XObject; 29 import java.util.List; 30 31 /** 32 * The baseclass for a binary operation. 33 * 34 * @LastModified: Oct 2017 35 */ 36 public class Operation extends Expression implements ExpressionOwner 37 { 38 static final long serialVersionUID = -3037139537171050430L; 39 40 /** The left operand expression. 41 * @serial */ 42 protected Expression m_left; 43 44 /** The right operand expression. 45 * @serial */ 46 protected Expression m_right; 47 48 /** 49 * This function is used to fixup variables from QNames to stack frame 50 * indexes at stylesheet build time. 51 * @param vars List of QNames that correspond to variables. This list 52 * should be searched backwards for the first qualified name that 53 * corresponds to the variable reference qname. The position of the 54 * QName in the vector from the start of the vector will be its position 55 * in the stack frame (but variables above the globalsTop value will need 56 * to be offset to the current stack frame). 57 */ 58 public void fixupVariables(List<QName> vars, int globalsSize) 59 { 60 m_left.fixupVariables(vars, globalsSize); 61 m_right.fixupVariables(vars, globalsSize); 62 } 63 64 65 /** 66 * Tell if this expression or it's subexpressions can traverse outside 67 * the current subtree. 68 * 69 * @return true if traversal outside the context node's subtree can occur. 70 */ 71 public boolean canTraverseOutsideSubtree() 72 { 73 74 if (null != m_left && m_left.canTraverseOutsideSubtree()) 75 return true; 76 77 if (null != m_right && m_right.canTraverseOutsideSubtree()) 78 return true; 79 80 return false; 81 } 82 83 /** 84 * Set the left and right operand expressions for this operation. 85 * 86 * 87 * @param l The left expression operand. 88 * @param r The right expression operand. 89 */ 90 public void setLeftRight(Expression l, Expression r) 91 { 92 m_left = l; 93 m_right = r; 94 l.exprSetParent(this); 95 r.exprSetParent(this); 96 } 97 98 /** 99 * Execute a binary operation by calling execute on each of the operands, 100 * and then calling the operate method on the derived class. 101 * 102 * 103 * @param xctxt The runtime execution context. 104 * 105 * @return The XObject result of the operation. 106 * 107 * @throws javax.xml.transform.TransformerException 108 */ 109 public XObject execute(XPathContext xctxt) 110 throws javax.xml.transform.TransformerException 111 { 112 113 XObject left = m_left.execute(xctxt, true); 114 XObject right = m_right.execute(xctxt, true); 115 116 XObject result = operate(left, right); 117 left.detach(); 118 right.detach(); 119 return result; 120 } 121 122 /** 123 * Apply the operation to two operands, and return the result. 124 * 125 * 126 * @param left non-null reference to the evaluated left operand. 127 * @param right non-null reference to the evaluated right operand. 128 * 129 * @return non-null reference to the XObject that represents the result of the operation. 130 * 131 * @throws javax.xml.transform.TransformerException 132 */ 133 public XObject operate(XObject left, XObject right) 134 throws javax.xml.transform.TransformerException 135 { 136 return null; // no-op 137 } 138 139 /** @return the left operand of binary operation, as an Expression. 140 */ 141 public Expression getLeftOperand(){ 142 return m_left; 143 } 144 145 /** @return the right operand of binary operation, as an Expression. 146 */ 147 public Expression getRightOperand(){ 148 return m_right; 149 } 150 151 class LeftExprOwner implements ExpressionOwner 152 { 153 /** 154 * @see ExpressionOwner#getExpression() 155 */ 156 public Expression getExpression() 157 { 158 return m_left; 159 } 160 161 /** 162 * @see ExpressionOwner#setExpression(Expression) 163 */ 164 public void setExpression(Expression exp) 165 { 166 exp.exprSetParent(Operation.this); 167 m_left = exp; 168 } 169 } 170 171 /** 172 * @see com.sun.org.apache.xpath.internal.XPathVisitable#callVisitors(ExpressionOwner, XPathVisitor) 173 */ 174 public void callVisitors(ExpressionOwner owner, XPathVisitor visitor) 175 { 176 if(visitor.visitBinaryOperation(owner, this)) 177 { 178 m_left.callVisitors(new LeftExprOwner(), visitor); 179 m_right.callVisitors(this, visitor); 180 } 181 } 182 183 /** 184 * @see ExpressionOwner#getExpression() 185 */ 186 public Expression getExpression() 187 { 188 return m_right; 189 } 190 191 /** 192 * @see ExpressionOwner#setExpression(Expression) 193 */ 194 public void setExpression(Expression exp) 195 { 196 exp.exprSetParent(this); 197 m_right = exp; 198 } 199 200 /** 201 * @see Expression#deepEquals(Expression) 202 */ 203 public boolean deepEquals(Expression expr) 204 { 205 if(!isSameClass(expr)) 206 return false; 207 208 if(!m_left.deepEquals(((Operation)expr).m_left)) 209 return false; 210 211 if(!m_right.deepEquals(((Operation)expr).m_right)) 212 return false; 213 214 return true; 215 } 216 }