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 DivOpAxis extends AbsObAxis {
47
48
49
50
51
52
53
54
55
56
57
58 public DivOpAxis(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 DECIMAL:
77 case FLOAT:
78 case DOUBLE:
79 final double aD = Double.parseDouble(new String(mOperand1.getRawValue()));
80 final double dValue;
81
82 if (aD == 0.0 || aD == -0.0) {
83 dValue = Double.NaN;
84 } else {
85 dValue = aD / Double.parseDouble(new String(mOperand2.getRawValue()));
86 }
87
88 value = TypedValue.getBytes(dValue);
89 return new AtomicValue(value, typeKey);
90
91 case INTEGER:
92 try {
93 final int iValue =
94 (int)Double.parseDouble(new String(mOperand1.getRawValue()))
95 / (int)Double.parseDouble(new String(mOperand2.getRawValue()));
96 value = TypedValue.getBytes(iValue);
97 return new AtomicValue(value, typeKey);
98 } catch (final ArithmeticException e) {
99 throw new XPathError(ErrorType.FOAR0001);
100 }
101 case YEAR_MONTH_DURATION:
102 case DAY_TIME_DURATION:
103 throw new IllegalStateException("Add operator is not implemented for the type "
104 + returnType.getStringRepr() + " yet.");
105 default:
106 throw new XPathError(ErrorType.XPTY0004);
107
108 }
109
110 }
111
112
113
114
115 @Override
116 protected Type getReturnType(final int mOp1, final int mOp2) throws TTXPathException {
117
118 Type type1;
119 Type type2;
120 try {
121 type1 = Type.getType(mOp1).getPrimitiveBaseType();
122 type2 = Type.getType(mOp2).getPrimitiveBaseType();
123 } catch (final IllegalStateException e) {
124 throw new XPathError(ErrorType.XPTY0004);
125 }
126
127 if (type1.isNumericType() && type2.isNumericType()) {
128
129
130 if (type1 == type2) {
131 return type1;
132 }
133
134 if (type1 == Type.DOUBLE || type2 == Type.DOUBLE) {
135 return Type.DOUBLE;
136 } else if (type1 == Type.FLOAT || type2 == Type.FLOAT) {
137 return Type.FLOAT;
138 } else {
139 assert (type1 == Type.DECIMAL || type2 == Type.DECIMAL);
140 return Type.DECIMAL;
141 }
142
143 } else {
144
145 switch (type1) {
146
147 case YEAR_MONTH_DURATION:
148 if (type2 == Type.YEAR_MONTH_DURATION) {
149 return Type.DECIMAL;
150 }
151 if (type2.isNumericType()) {
152 return type1;
153 }
154 break;
155 case DAY_TIME_DURATION:
156 if (type2 == Type.DAY_TIME_DURATION) {
157 return Type.DECIMAL;
158 }
159 if (type2.isNumericType()) {
160 return type1;
161 }
162 break;
163 default:
164 throw new XPathError(ErrorType.XPTY0004);
165 }
166 throw new XPathError(ErrorType.XPTY0004);
167 }
168 }
169
170 }