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 package gov.nist.secauto.metaschema.core.metapath;
28
29 import gov.nist.secauto.metaschema.core.metapath.function.OperationFunctions;
30 import gov.nist.secauto.metaschema.core.metapath.function.library.FnNot;
31 import gov.nist.secauto.metaschema.core.metapath.item.atomic.IAnyAtomicItem;
32 import gov.nist.secauto.metaschema.core.metapath.item.atomic.IBase64BinaryItem;
33 import gov.nist.secauto.metaschema.core.metapath.item.atomic.IBooleanItem;
34 import gov.nist.secauto.metaschema.core.metapath.item.atomic.IDateItem;
35 import gov.nist.secauto.metaschema.core.metapath.item.atomic.IDateTimeItem;
36 import gov.nist.secauto.metaschema.core.metapath.item.atomic.IDayTimeDurationItem;
37 import gov.nist.secauto.metaschema.core.metapath.item.atomic.IDurationItem;
38 import gov.nist.secauto.metaschema.core.metapath.item.atomic.IIntegerItem;
39 import gov.nist.secauto.metaschema.core.metapath.item.atomic.INumericItem;
40 import gov.nist.secauto.metaschema.core.metapath.item.atomic.IStringItem;
41 import gov.nist.secauto.metaschema.core.metapath.item.atomic.IYearMonthDurationItem;
42 import gov.nist.secauto.metaschema.core.util.ObjectUtils;
43
44 import java.util.Locale;
45
46 import edu.umd.cs.findbugs.annotations.NonNull;
47
48
49
50
51
52
53 abstract class AbstractComparison
54 extends AbstractBinaryExpression<IExpression, IExpression>
55 implements IComparison {
56
57 @NonNull
58 private final Operator operator;
59
60
61
62
63
64
65
66
67
68
69
70
71
72 public AbstractComparison(@NonNull IExpression left, @NonNull Operator operator, @NonNull IExpression right) {
73 super(left, right);
74 this.operator = ObjectUtils.requireNonNull(operator, "operator");
75 }
76
77
78
79
80
81
82 @NonNull
83 public Operator getOperator() {
84 return operator;
85 }
86
87 @SuppressWarnings("null")
88 @Override
89 public String toASTString() {
90 return String.format("%s[operator=%s]", getClass().getName(), operator);
91 }
92
93
94
95
96
97
98
99
100
101
102
103
104
105 @NonNull
106 protected IBooleanItem compare(
107 @NonNull IAnyAtomicItem left,
108 @NonNull Operator operator,
109 @NonNull IAnyAtomicItem right) {
110 @NonNull IBooleanItem retval;
111 if (left instanceof IStringItem || right instanceof IStringItem) {
112 retval = stringCompare(IStringItem.cast(left), operator, IStringItem.cast(right));
113 } else if (left instanceof INumericItem && right instanceof INumericItem) {
114 retval = numericCompare((INumericItem) left, operator, (INumericItem) right);
115 } else if (left instanceof IBooleanItem && right instanceof IBooleanItem) {
116 retval = booleanCompare((IBooleanItem) left, operator, (IBooleanItem) right);
117 } else if (left instanceof IDateTimeItem && right instanceof IDateTimeItem) {
118 retval = dateTimeCompare((IDateTimeItem) left, operator, (IDateTimeItem) right);
119 } else if (left instanceof IDateItem && right instanceof IDateItem) {
120 retval = dateCompare((IDateItem) left, operator, (IDateItem) right);
121 } else if (left instanceof IDurationItem && right instanceof IDurationItem) {
122 retval = durationCompare((IDurationItem) left, operator, (IDurationItem) right);
123 } else if (left instanceof IBase64BinaryItem && right instanceof IBase64BinaryItem) {
124 retval = binaryCompare((IBase64BinaryItem) left, operator, (IBase64BinaryItem) right);
125 } else {
126 throw new InvalidTypeMetapathException(
127 null,
128 String.format("invalid types for comparison: %s %s %s", left.getClass().getName(),
129 operator.name().toLowerCase(Locale.ROOT), right.getClass().getName()));
130 }
131 return retval;
132 }
133
134
135
136
137
138
139
140
141
142
143
144
145
146 @NonNull
147 public static IBooleanItem stringCompare(@NonNull IStringItem left, @NonNull Operator operator,
148 @NonNull IStringItem right) {
149 IBooleanItem retval;
150 switch (operator) {
151 case EQ:
152 retval = OperationFunctions.opNumericEqual(left.compare(right), IIntegerItem.ZERO);
153 break;
154 case GE:
155 retval = OperationFunctions.opNumericGreaterThan(left.compare(right), IIntegerItem.NEGATIVE_ONE);
156 break;
157 case GT:
158 retval = OperationFunctions.opNumericGreaterThan(left.compare(right), IIntegerItem.ZERO);
159 break;
160 case LE:
161 retval = OperationFunctions.opNumericLessThan(left.compare(right), IIntegerItem.ONE);
162 break;
163 case LT:
164 retval = OperationFunctions.opNumericLessThan(left.compare(right), IIntegerItem.ZERO);
165 break;
166 case NE:
167 retval = FnNot.fnNot(OperationFunctions.opNumericEqual(left.compare(right), IIntegerItem.ZERO));
168 break;
169 default:
170 throw new IllegalArgumentException(
171 String.format("Unsupported operator '%s'", operator.name()));
172 }
173 return retval;
174 }
175
176
177
178
179
180
181
182
183
184
185
186
187
188 @NonNull
189 public static IBooleanItem numericCompare(@NonNull INumericItem left, @NonNull Operator operator,
190 @NonNull INumericItem right) {
191 IBooleanItem retval;
192 switch (operator) {
193 case EQ:
194 retval = OperationFunctions.opNumericEqual(left, right);
195 break;
196 case GE: {
197 IBooleanItem gt = OperationFunctions.opNumericGreaterThan(left, right);
198 IBooleanItem eq = OperationFunctions.opNumericEqual(left, right);
199 retval = IBooleanItem.valueOf(gt.toBoolean() || eq.toBoolean());
200 break;
201 }
202 case GT:
203 retval = OperationFunctions.opNumericGreaterThan(left, right);
204 break;
205 case LE: {
206 IBooleanItem lt = OperationFunctions.opNumericLessThan(left, right);
207 IBooleanItem eq = OperationFunctions.opNumericEqual(left, right);
208 retval = IBooleanItem.valueOf(lt.toBoolean() || eq.toBoolean());
209 break;
210 }
211 case LT:
212 retval = OperationFunctions.opNumericLessThan(left, right);
213 break;
214 case NE:
215 retval = FnNot.fnNot(OperationFunctions.opNumericEqual(left, right));
216 break;
217 default:
218 throw new IllegalArgumentException(String.format("Unsupported operator '%s'", operator.name()));
219 }
220 return retval;
221 }
222
223
224
225
226
227
228
229
230
231
232
233
234
235 @NonNull
236 public static IBooleanItem booleanCompare(@NonNull IBooleanItem left, @NonNull Operator operator,
237 @NonNull IBooleanItem right) {
238 IBooleanItem retval;
239 switch (operator) {
240 case EQ:
241 retval = OperationFunctions.opBooleanEqual(left, right);
242 break;
243 case GE: {
244 IBooleanItem gt = OperationFunctions.opBooleanGreaterThan(left, right);
245 IBooleanItem eq = OperationFunctions.opBooleanEqual(left, right);
246 retval = IBooleanItem.valueOf(gt.toBoolean() || eq.toBoolean());
247 break;
248 }
249 case GT:
250 retval = OperationFunctions.opBooleanGreaterThan(left, right);
251 break;
252 case LE: {
253 IBooleanItem lt = OperationFunctions.opBooleanLessThan(left, right);
254 IBooleanItem eq = OperationFunctions.opBooleanEqual(left, right);
255 retval = IBooleanItem.valueOf(lt.toBoolean() || eq.toBoolean());
256 break;
257 }
258 case LT:
259 retval = OperationFunctions.opBooleanLessThan(left, right);
260 break;
261 case NE:
262 retval = FnNot.fnNot(OperationFunctions.opBooleanEqual(left, right));
263 break;
264 default:
265 throw new IllegalArgumentException(String.format("Unsupported operator '%s'", operator.name()));
266 }
267 return retval;
268 }
269
270
271
272
273
274
275
276
277
278
279
280
281
282 @NonNull
283 public static IBooleanItem dateTimeCompare(@NonNull IDateTimeItem left, @NonNull Operator operator,
284 @NonNull IDateTimeItem right) {
285 IBooleanItem retval;
286 switch (operator) {
287 case EQ:
288 retval = OperationFunctions.opDateTimeEqual(left, right);
289 break;
290 case GE: {
291 IBooleanItem gt = OperationFunctions.opDateTimeGreaterThan(left, right);
292 IBooleanItem eq = OperationFunctions.opDateTimeEqual(left, right);
293 retval = IBooleanItem.valueOf(gt.toBoolean() || eq.toBoolean());
294 break;
295 }
296 case GT:
297 retval = OperationFunctions.opDateTimeGreaterThan(left, right);
298 break;
299 case LE: {
300 IBooleanItem lt = OperationFunctions.opDateTimeLessThan(left, right);
301 IBooleanItem eq = OperationFunctions.opDateTimeEqual(left, right);
302 retval = IBooleanItem.valueOf(lt.toBoolean() || eq.toBoolean());
303 break;
304 }
305 case LT:
306 retval = OperationFunctions.opDateTimeLessThan(left, right);
307 break;
308 case NE:
309 retval = FnNot.fnNot(OperationFunctions.opDateTimeEqual(left, right));
310 break;
311 default:
312 throw new IllegalArgumentException(String.format("Unsupported operator '%s'", operator.name()));
313 }
314 return retval;
315 }
316
317
318
319
320
321
322
323
324
325
326
327
328
329 @NonNull
330 public static IBooleanItem dateCompare(@NonNull IDateItem left, @NonNull Operator operator,
331 @NonNull IDateItem right) {
332 IBooleanItem retval;
333 switch (operator) {
334 case EQ:
335 retval = OperationFunctions.opDateEqual(left, right);
336 break;
337 case GE: {
338 IBooleanItem gt = OperationFunctions.opDateGreaterThan(left, right);
339 IBooleanItem eq = OperationFunctions.opDateEqual(left, right);
340 retval = IBooleanItem.valueOf(gt.toBoolean() || eq.toBoolean());
341 break;
342 }
343 case GT:
344 retval = OperationFunctions.opDateGreaterThan(left, right);
345 break;
346 case LE: {
347 IBooleanItem lt = OperationFunctions.opDateLessThan(left, right);
348 IBooleanItem eq = OperationFunctions.opDateEqual(left, right);
349 retval = IBooleanItem.valueOf(lt.toBoolean() || eq.toBoolean());
350 break;
351 }
352 case LT:
353 retval = OperationFunctions.opDateLessThan(left, right);
354 break;
355 case NE:
356 retval = FnNot.fnNot(OperationFunctions.opDateEqual(left, right));
357 break;
358 default:
359 throw new IllegalArgumentException(String.format("Unsupported operator '%s'", operator.name()));
360 }
361 return retval;
362 }
363
364
365
366
367
368
369
370
371
372
373
374
375
376 @NonNull
377 public static IBooleanItem durationCompare(
378 @NonNull IDurationItem left,
379 @NonNull Operator operator,
380 @NonNull IDurationItem right) {
381 IBooleanItem retval = null;
382 switch (operator) {
383 case EQ:
384 retval = OperationFunctions.opDurationEqual(left, right);
385 break;
386 case GE:
387 if (left instanceof IYearMonthDurationItem && right instanceof IYearMonthDurationItem) {
388 IBooleanItem gt = OperationFunctions.opYearMonthDurationGreaterThan(
389 (IYearMonthDurationItem) left,
390 (IYearMonthDurationItem) right);
391 IBooleanItem eq = OperationFunctions.opDurationEqual(left, right);
392 retval = IBooleanItem.valueOf(gt.toBoolean() || eq.toBoolean());
393 } else if (left instanceof IDayTimeDurationItem && right instanceof IDayTimeDurationItem) {
394 IBooleanItem gt = OperationFunctions.opDayTimeDurationGreaterThan(
395 (IDayTimeDurationItem) left,
396 (IDayTimeDurationItem) right);
397 IBooleanItem eq = OperationFunctions.opDurationEqual(left, right);
398 retval = IBooleanItem.valueOf(gt.toBoolean() || eq.toBoolean());
399 }
400 break;
401 case GT:
402 if (left instanceof IYearMonthDurationItem && right instanceof IYearMonthDurationItem) {
403 retval = OperationFunctions.opYearMonthDurationGreaterThan(
404 (IYearMonthDurationItem) left,
405 (IYearMonthDurationItem) right);
406 } else if (left instanceof IDayTimeDurationItem && right instanceof IDayTimeDurationItem) {
407 retval = OperationFunctions.opDayTimeDurationGreaterThan(
408 (IDayTimeDurationItem) left,
409 (IDayTimeDurationItem) right);
410 }
411 break;
412 case LE:
413 if (left instanceof IYearMonthDurationItem && right instanceof IYearMonthDurationItem) {
414 IBooleanItem lt = OperationFunctions.opYearMonthDurationLessThan(
415 (IYearMonthDurationItem) left,
416 (IYearMonthDurationItem) right);
417 IBooleanItem eq = OperationFunctions.opDurationEqual(left, right);
418 retval = IBooleanItem.valueOf(lt.toBoolean() || eq.toBoolean());
419 } else if (left instanceof IDayTimeDurationItem && right instanceof IDayTimeDurationItem) {
420 IBooleanItem lt = OperationFunctions.opDayTimeDurationLessThan(
421 (IDayTimeDurationItem) left,
422 (IDayTimeDurationItem) right);
423 IBooleanItem eq = OperationFunctions.opDurationEqual(left, right);
424 retval = IBooleanItem.valueOf(lt.toBoolean() || eq.toBoolean());
425 }
426 break;
427 case LT:
428 if (left instanceof IYearMonthDurationItem && right instanceof IYearMonthDurationItem) {
429 retval = OperationFunctions.opYearMonthDurationLessThan(
430 (IYearMonthDurationItem) left,
431 (IYearMonthDurationItem) right);
432 } else if (left instanceof IDayTimeDurationItem && right instanceof IDayTimeDurationItem) {
433 retval = OperationFunctions.opDayTimeDurationLessThan(
434 (IDayTimeDurationItem) left,
435 (IDayTimeDurationItem) right);
436 }
437 break;
438 case NE:
439 retval = FnNot.fnNot(OperationFunctions.opDurationEqual(left, right));
440 break;
441 default:
442 throw new IllegalArgumentException(String.format("Unsupported operator '%s'", operator.name()));
443 }
444
445 if (retval == null) {
446 throw new InvalidTypeMetapathException(
447 null,
448 String.format("The item types '%s' and '%s' are not comparable",
449 left.getClass().getName(),
450 right.getClass().getName()));
451 }
452 return retval;
453 }
454
455
456
457
458
459
460
461
462
463
464
465
466
467 @NonNull
468 public static IBooleanItem binaryCompare(@NonNull IBase64BinaryItem left, @NonNull Operator operator,
469 @NonNull IBase64BinaryItem right) {
470 IBooleanItem retval;
471 switch (operator) {
472 case EQ:
473 retval = OperationFunctions.opBase64BinaryEqual(left, right);
474 break;
475 case GE: {
476 IBooleanItem gt = OperationFunctions.opBase64BinaryGreaterThan(left, right);
477 IBooleanItem eq = OperationFunctions.opBase64BinaryEqual(left, right);
478 retval = IBooleanItem.valueOf(gt.toBoolean() || eq.toBoolean());
479 break;
480 }
481 case GT:
482 retval = OperationFunctions.opBase64BinaryGreaterThan(left, right);
483 break;
484 case LE: {
485 IBooleanItem lt = OperationFunctions.opBase64BinaryLessThan(left, right);
486 IBooleanItem eq = OperationFunctions.opBase64BinaryEqual(left, right);
487 retval = IBooleanItem.valueOf(lt.toBoolean() || eq.toBoolean());
488 break;
489 }
490 case LT:
491 retval = OperationFunctions.opBase64BinaryLessThan(left, right);
492 break;
493 case NE:
494 retval = FnNot.fnNot(OperationFunctions.opBase64BinaryEqual(left, right));
495 break;
496 default:
497 throw new IllegalArgumentException(String.format("Unsupported operator '%s'", operator.name()));
498 }
499 return retval;
500 }
501 }