1 /** 2 * Copyright (c) 2011, University of Konstanz, Distributed Systems Group 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * * Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * * Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * * Neither the name of the University of Konstanz nor the 13 * names of its contributors may be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY 20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 package org.treetank.service.xml.xpath.operators; 29 30 import static org.treetank.service.xml.xpath.XPathAxis.XPATH_10_COMP; 31 32 import org.treetank.api.INodeReadTrx; 33 import org.treetank.axis.AbsAxis; 34 import org.treetank.exception.TTXPathException; 35 import org.treetank.node.AtomicValue; 36 import org.treetank.node.Type; 37 import org.treetank.node.interfaces.IValNode; 38 import org.treetank.service.xml.xpath.expr.LiteralExpr; 39 import org.treetank.utils.NamePageHash; 40 41 /** 42 * <h1>AbstractOpAxis</h1> 43 * <p> 44 * Abstract axis for all operators performing an arithmetic operation. 45 * </p> 46 */ 47 public abstract class AbsObAxis extends AbsAxis { 48 49 /** First arithmetic operand. */ 50 private final AbsAxis mOperand1; 51 52 /** Second arithmetic operand. */ 53 private final AbsAxis mOperand2; 54 55 /** True, if axis has not been evaluated yet. */ 56 private boolean mIsFirst; 57 58 /** 59 * Constructor. Initializes the internal state. 60 * 61 * @param rtx 62 * Exclusive (immutable) trx to iterate with. 63 * @param mOp1 64 * First value of the operation 65 * @param mOp2 66 * Second value of the operation 67 */ 68 public AbsObAxis(final INodeReadTrx rtx, final AbsAxis mOp1, final AbsAxis mOp2) { 69 70 super(rtx); 71 mOperand1 = mOp1; 72 mOperand2 = mOp2; 73 mIsFirst = true; 74 75 } 76 77 /** 78 * {@inheritDoc} 79 */ 80 @Override 81 public final void reset(final long mNodeKey) { 82 83 super.reset(mNodeKey); 84 mIsFirst = true; 85 if (mOperand1 != null) { 86 mOperand1.reset(mNodeKey); 87 } 88 89 if (mOperand2 != null) { 90 mOperand2.reset(mNodeKey); 91 } 92 } 93 94 /** 95 * {@inheritDoc} 96 */ 97 @Override 98 public boolean hasNext() { 99 100 resetToLastKey(); 101 102 if (mIsFirst) { 103 mIsFirst = false; 104 try { 105 106 AtomicValue mItem1 = null; 107 if (mOperand1 instanceof LiteralExpr) { 108 mItem1 = ((LiteralExpr)mOperand1).evaluate(); 109 } else if (mOperand1.hasNext()) { 110 // atomize operand 111 mItem1 = atomize(mOperand1); 112 113 } 114 115 if (mItem1 != null) { 116 117 AtomicValue mItem2 = null; 118 if (mOperand2 instanceof LiteralExpr) { 119 mItem2 = ((LiteralExpr)mOperand2).evaluate(); 120 } else if (mOperand2.hasNext()) { 121 // atomize operand 122 mItem2 = atomize(mOperand2); 123 } 124 125 if (mItem2 != null) { 126 final AtomicValue result = operate(mItem1, mItem2); 127 // add retrieved AtomicValue to item list 128 final int itemKey = getItemList().addItem(result); 129 moveTo(itemKey); 130 return true; 131 132 } 133 } 134 } catch (TTXPathException e) { 135 throw new RuntimeException(e); 136 } 137 } 138 // either not the first call, or empty sequence 139 resetToStartKey(); 140 return false; 141 142 } 143 144 /** 145 * Atomizes an operand according to the rules specified in the XPath 146 * specification. 147 * 148 * @param mOperand 149 * the operand to atomize 150 * @return the atomized operand. (always an atomic value) 151 */ 152 private AtomicValue atomize(final AbsAxis mOperand) { 153 154 int type = getNode().getTypeKey(); 155 AtomicValue atom; 156 157 if (XPATH_10_COMP) { 158 159 atom = new AtomicValue(((IValNode)getNode()).getRawValue(), getNode().getTypeKey()); 160 } else { 161 // unatomicType is cast to double 162 if (type == NamePageHash.generateHashForString("xs:untypedAtomic")) { 163 type = NamePageHash.generateHashForString("xs:double"); 164 // TODO: throw error, of cast fails 165 } 166 167 atom = new AtomicValue(((IValNode)getNode()).getRawValue(), getNode().getTypeKey()); 168 } 169 170 // if (!XPATH_10_COMP && operand.hasNext()) { 171 // throw new XPathError(ErrorType.XPTY0004); 172 // } 173 174 return atom; 175 } 176 177 /** 178 * Performs the operation on the two input operands. First checks if the 179 * types of the operands are a valid combination for the operation and if so 180 * computed the result. Otherwise an XPathError is thrown. 181 * 182 * @param mOperand1 183 * first input operand 184 * @param mOperand2 185 * second input operand 186 * @return result of the operation 187 * @throws TTXPathException 188 * if the operations fails 189 */ 190 protected abstract AtomicValue operate(final AtomicValue mOperand1, final AtomicValue mOperand2) 191 throws TTXPathException; 192 193 /** 194 * Checks if the types of the operands are a valid combination for the 195 * operation and if so returns the corresponding result type. Otherwise an 196 * XPathError is thrown. This typed check is done according to the <a 197 * href="http://www.w3.org/TR/xpath20/#mapping">Operator Mapping</a>. 198 * 199 * @param mOp1 200 * first operand's type key 201 * @param mOp2 202 * second operand's type key 203 * @return return type of the arithmetic function according to the operand 204 * type combination. 205 * @throws TTXPathException 206 * if type is not specified 207 */ 208 protected abstract Type getReturnType(final int mOp1, final int mOp2) throws TTXPathException; 209 210 }