1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
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
42
43
44
45
46 public class MulOpAxis extends AbsObAxis {
47
48
49
50
51
52
53
54
55
56
57
58 public MulOpAxis(final INodeReadTrx rtx, final AbsAxis mOp1, final AbsAxis mOp2) {
59
60 super(rtx, mOp1, mOp2);
61 }
62
63
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
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
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
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 }