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 multiplication on two input operators.
44   * </p>
45   */
46  public class MulOpAxis 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 MulOpAxis(final INodeReadTrx rtx, final AbsAxis mOp1, final AbsAxis mOp2) {
59  
60          super(rtx, mOp1, mOp2);
61      }
62  
63      /**
64       * {@inheritDoc}
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  
85          case YEAR_MONTH_DURATION:
86          case DAY_TIME_DURATION:
87              throw new IllegalStateException("Add operator is not implemented for the type "
88                  + returnType.getStringRepr() + " yet.");
89          default:
90              throw new XPathError(ErrorType.XPTY0004);
91  
92          }
93  
94          return new AtomicValue(value, typeKey);
95  
96      }
97  
98      /**
99       * {@inheritDoc}
100      */
101     @Override
102     protected Type getReturnType(final int mOp1, final int mOp2) throws TTXPathException {
103 
104         Type type1;
105         Type type2;
106         try {
107             type1 = Type.getType(mOp1).getPrimitiveBaseType();
108             type2 = Type.getType(mOp2).getPrimitiveBaseType();
109         } catch (final IllegalStateException e) {
110             throw new XPathError(ErrorType.XPTY0004);
111         }
112 
113         if (type1.isNumericType() && type2.isNumericType()) {
114 
115             // if both have the same numeric type, return it
116             if (type1 == type2) {
117                 return type1;
118             }
119 
120             if (type1 == Type.DOUBLE || type2 == Type.DOUBLE) {
121                 return Type.DOUBLE;
122             } else if (type1 == Type.FLOAT || type2 == Type.FLOAT) {
123                 return Type.FLOAT;
124             } else {
125                 assert (type1 == Type.DECIMAL || type2 == Type.DECIMAL);
126                 return Type.DECIMAL;
127             }
128 
129         } else {
130 
131             switch (type1) {
132 
133             case YEAR_MONTH_DURATION:
134                 if (type2.isNumericType()) {
135                     return type1;
136                 }
137                 break;
138             case DAY_TIME_DURATION:
139                 if (type2.isNumericType()) {
140                     return type1;
141                 }
142                 break;
143             case DOUBLE:
144             case FLOAT:
145             case DECIMAL:
146             case INTEGER:
147                 if (type2 == Type.DAY_TIME_DURATION || type2 == Type.YEAR_MONTH_DURATION) {
148                     return type2;
149                 }
150                 break;
151             default:
152                 throw new XPathError(ErrorType.XPTY0004);
153             }
154             throw new XPathError(ErrorType.XPTY0004);
155         }
156     }
157 
158 }