View Javadoc

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 org.treetank.api.INodeReadTrx;
31  import org.treetank.axis.AbsAxis;
32  import org.treetank.exception.TTXPathException;
33  import org.treetank.node.AtomicValue;
34  import org.treetank.node.Type;
35  import org.treetank.service.xml.xpath.XPathError;
36  import org.treetank.service.xml.xpath.XPathError.ErrorType;
37  import org.treetank.utils.NamePageHash;
38  import org.treetank.utils.TypedValue;
39  
40  /**
41   * <h1>AddOpAxis</h1>
42   * <p>
43   * Performs an arithmetic subtraction on two input operators.
44   * </p>
45   */
46  public class SubOpAxis extends AbsObAxis {
47  
48      /**
49       * Constructor. Initializes the internal state.
50       * 
51       * @param rtx
52       *            Exclusive (immutable) trx to iterate with.
53       * @param mOp1
54       *            First value of the operation
55       * @param mOp2
56       *            Second value of the operation
57       */
58      public SubOpAxis(final INodeReadTrx rtx, final AbsAxis mOp1, final AbsAxis mOp2) {
59  
60          super(rtx, mOp1, mOp2);
61      }
62  
63      /**
64       * {@inheritDoc}
65       * 
66       */
67      @Override
68      public AtomicValue operate(final AtomicValue mOperand1, final AtomicValue mOperand2)
69          throws TTXPathException {
70  
71          final Type returnType = getReturnType(mOperand1.getTypeKey(), mOperand2.getTypeKey());
72          final int typeKey = NamePageHash.generateHashForString(returnType.getStringRepr());
73  
74          final byte[] value;
75  
76          switch (returnType) {
77          case DOUBLE:
78          case FLOAT:
79          case DECIMAL:
80          case INTEGER:
81              final double dOp1 = Double.parseDouble(new String(mOperand1.getRawValue()));
82              final double dOp2 = Double.parseDouble(new String(mOperand2.getRawValue()));
83              value = TypedValue.getBytes(dOp1 - dOp2);
84              break;
85          case DATE:
86          case TIME:
87          case DATE_TIME:
88          case YEAR_MONTH_DURATION:
89          case DAY_TIME_DURATION:
90              throw new IllegalStateException("Add operator is not implemented for the type "
91                  + returnType.getStringRepr() + " yet.");
92          default:
93              throw new XPathError(ErrorType.XPTY0004);
94  
95          }
96  
97          return new AtomicValue(value, typeKey);
98  
99      }
100 
101     /**
102      * {@inheritDoc}
103      */
104     @Override
105     protected Type getReturnType(final int mOp1, final int mOp2) throws TTXPathException {
106 
107         Type type1;
108         Type type2;
109         try {
110             type1 = Type.getType(mOp1).getPrimitiveBaseType();
111             type2 = Type.getType(mOp2).getPrimitiveBaseType();
112         } catch (final IllegalStateException e) {
113             throw new XPathError(ErrorType.XPTY0004);
114         }
115 
116         if (type1.isNumericType() && type2.isNumericType()) {
117 
118             // if both have the same numeric type, return it
119             if (type1 == type2) {
120                 return type1;
121             }
122 
123             if (type1 == Type.DOUBLE || type2 == Type.DOUBLE) {
124                 return Type.DOUBLE;
125             } else if (type1 == Type.FLOAT || type2 == Type.FLOAT) {
126                 return Type.FLOAT;
127             } else {
128                 assert (type1 == Type.DECIMAL || type2 == Type.DECIMAL);
129                 return Type.DECIMAL;
130             }
131 
132         } else {
133 
134             switch (type1) {
135             case DATE:
136                 if (type2 == Type.YEAR_MONTH_DURATION || type2 == Type.DAY_TIME_DURATION) {
137                     return type1;
138                 } else if (type2 == Type.DATE) {
139                     return Type.DAY_TIME_DURATION;
140                 }
141                 break;
142             case TIME:
143                 if (type2 == Type.DAY_TIME_DURATION) {
144                     return type1;
145                 } else if (type2 == Type.TIME) {
146                     return Type.DAY_TIME_DURATION;
147                 }
148                 break;
149             case DATE_TIME:
150                 if (type2 == Type.YEAR_MONTH_DURATION || type2 == Type.DAY_TIME_DURATION) {
151                     return type1;
152                 } else if (type2 == Type.DATE_TIME) {
153                     return Type.DAY_TIME_DURATION;
154                 }
155                 break;
156             case YEAR_MONTH_DURATION:
157                 if (type2 == Type.YEAR_MONTH_DURATION) {
158                     return type2;
159                 }
160                 break;
161             case DAY_TIME_DURATION:
162                 if (type2 == Type.DAY_TIME_DURATION) {
163                     return type2;
164                 }
165                 break;
166             default:
167                 throw new XPathError(ErrorType.XPTY0004);
168             }
169             throw new XPathError(ErrorType.XPTY0004);
170         }
171     }
172 
173 }