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 SubOpAxis extends AbsObAxis {
47
48
49
50
51
52
53
54
55
56
57
58 public SubOpAxis(final INodeReadTrx rtx, final AbsAxis mOp1, final AbsAxis mOp2) {
59
60 super(rtx, mOp1, mOp2);
61 }
62
63
64
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
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
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 }