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