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