1
2
3
4
5
6 package dev.metaschema.core.metapath.item.atomic;
7
8 import java.math.BigInteger;
9
10 import dev.metaschema.core.datatype.adapter.MetaschemaDataTypeProvider;
11 import dev.metaschema.core.metapath.function.ArithmeticFunctionException;
12 import dev.metaschema.core.metapath.function.CastFunctionException;
13 import dev.metaschema.core.metapath.function.InvalidValueForCastFunctionException;
14 import dev.metaschema.core.metapath.item.atomic.impl.IntegerItemImpl;
15 import dev.metaschema.core.metapath.type.IAtomicOrUnionType;
16 import dev.metaschema.core.metapath.type.InvalidTypeMetapathException;
17 import dev.metaschema.core.util.ObjectUtils;
18 import edu.umd.cs.findbugs.annotations.NonNull;
19
20
21
22
23 public interface IIntegerItem extends IDecimalItem {
24
25
26
27 @NonNull
28 IIntegerItem ONE = valueOf(ObjectUtils.notNull(BigInteger.ONE));
29
30
31
32 @NonNull
33 IIntegerItem ZERO = valueOf(ObjectUtils.notNull(BigInteger.ZERO));
34
35
36
37 @NonNull
38 IIntegerItem NEGATIVE_ONE = valueOf(ObjectUtils.notNull(BigInteger.ONE.negate()));
39
40
41
42
43
44
45 @NonNull
46 static IAtomicOrUnionType<IIntegerItem> type() {
47 return MetaschemaDataTypeProvider.INTEGER.getItemType();
48 }
49
50 @Override
51 default IAtomicOrUnionType<? extends IIntegerItem> getType() {
52 return type();
53 }
54
55
56
57
58
59
60
61
62
63
64 @NonNull
65 static IIntegerItem valueOf(@NonNull String value) {
66 try {
67 return valueOf(MetaschemaDataTypeProvider.INTEGER.parse(value));
68 } catch (IllegalArgumentException ex) {
69 throw new InvalidTypeMetapathException(null, ex.getMessage(), ex);
70 }
71 }
72
73
74
75
76
77
78
79
80 @NonNull
81 static IIntegerItem valueOf(int value) {
82 @SuppressWarnings("null")
83 @NonNull
84 BigInteger bigInteger = BigInteger.valueOf(value);
85 return valueOf(bigInteger);
86 }
87
88
89
90
91
92
93
94
95 @NonNull
96 static IIntegerItem valueOf(long value) {
97 @SuppressWarnings("null")
98 @NonNull
99 BigInteger bigInteger = BigInteger.valueOf(value);
100 return valueOf(bigInteger);
101 }
102
103
104
105
106
107
108
109
110 @NonNull
111 static IIntegerItem valueOf(boolean value) {
112 return valueOf(ObjectUtils.notNull(value ? BigInteger.ONE : BigInteger.ZERO));
113 }
114
115
116
117
118
119
120
121
122 @NonNull
123 static IIntegerItem valueOf(@NonNull BigInteger value) {
124 int signum = value.signum();
125
126 IIntegerItem retval;
127 if (signum == -1) {
128 retval = new IntegerItemImpl(value);
129 } else if (signum == 0) {
130 retval = INonNegativeIntegerItem.valueOf(value);
131 } else {
132 retval = IPositiveIntegerItem.valueOf(value);
133 }
134 return retval;
135 }
136
137
138
139
140
141
142
143
144
145
146
147 @NonNull
148 static IIntegerItem cast(@NonNull IAnyAtomicItem item) {
149 IIntegerItem retval;
150 if (item instanceof IIntegerItem) {
151 retval = (IIntegerItem) item;
152 } else if (item instanceof INumericItem) {
153 retval = valueOf(((INumericItem) item).asInteger());
154 } else if (item instanceof IBooleanItem) {
155 retval = valueOf(((IBooleanItem) item).toBoolean());
156 } else {
157 try {
158 retval = valueOf(item.asString());
159 } catch (IllegalStateException | InvalidTypeMetapathException ex) {
160
161 throw new InvalidValueForCastFunctionException(ex);
162 }
163 }
164 return retval;
165 }
166
167 @Override
168 default IIntegerItem castAsType(IAnyAtomicItem item) {
169 return cast(item);
170 }
171
172 @Override
173 default IIntegerItem abs() {
174 BigInteger value = asInteger();
175 return value.signum() > -1 ? this : valueOf(ObjectUtils.notNull(value.abs()));
176 }
177
178 @Override
179 default IIntegerItem ceiling() {
180 return this;
181 }
182
183 @Override
184 default IIntegerItem floor() {
185 return this;
186 }
187
188
189
190
191
192
193
194
195 @Override
196 default int toIntValueExact() {
197
198 try {
199 return asInteger().intValueExact();
200 } catch (ArithmeticException ex) {
201 throw new CastFunctionException(
202 CastFunctionException.INPUT_VALUE_TOO_LARGE,
203 this,
204 String.format("Integer value '%s' is out of range for a Java int.", asString()),
205 ex);
206 }
207 }
208
209
210
211
212
213
214
215
216
217 @NonNull
218 default IIntegerItem add(@NonNull IIntegerItem addend) {
219 BigInteger addendLeft = asInteger();
220 BigInteger addendRight = addend.asInteger();
221 return valueOf(ObjectUtils.notNull(addendLeft.add(addendRight)));
222 }
223
224
225
226
227
228
229
230
231
232
233 @NonNull
234 default IIntegerItem subtract(@NonNull IIntegerItem subtrahend) {
235 BigInteger minuendInteger = asInteger();
236 BigInteger subtrahendInteger = subtrahend.asInteger();
237 return valueOf(ObjectUtils.notNull(minuendInteger.subtract(subtrahendInteger)));
238 }
239
240
241
242
243
244
245
246
247
248 @NonNull
249 default IIntegerItem multiply(@NonNull IIntegerItem multiplier) {
250 return valueOf(ObjectUtils.notNull(asInteger().multiply(multiplier.asInteger())));
251 }
252
253
254
255
256
257
258
259
260
261 @NonNull
262 default IIntegerItem integerDivide(@NonNull IIntegerItem divisor) {
263 BigInteger divisorInteger = divisor.asInteger();
264
265 if (BigInteger.ZERO.equals(divisorInteger)) {
266 throw new ArithmeticFunctionException(ArithmeticFunctionException.DIVISION_BY_ZERO,
267 ArithmeticFunctionException.DIVISION_BY_ZERO_MESSAGE);
268 }
269 return valueOf(ObjectUtils.notNull(asInteger().divide(divisorInteger)));
270 }
271
272
273
274
275
276
277
278
279
280
281 @NonNull
282 default IIntegerItem mod(@NonNull IIntegerItem divisor) {
283 BigInteger divisorInteger = divisor.asInteger();
284
285 if (BigInteger.ZERO.equals(divisorInteger)) {
286 throw new ArithmeticFunctionException(ArithmeticFunctionException.DIVISION_BY_ZERO,
287 ArithmeticFunctionException.DIVISION_BY_ZERO_MESSAGE);
288 }
289
290 return valueOf(ObjectUtils.notNull(asInteger().remainder(divisorInteger)));
291 }
292
293 @Override
294 default IIntegerItem negate() {
295 return valueOf(ObjectUtils.notNull(asInteger().negate()));
296 }
297
298
299
300
301
302
303
304
305
306 default int compareTo(IIntegerItem item) {
307 return asInteger().compareTo(item.asInteger());
308 }
309 }