1
2
3
4
5
6 package dev.metaschema.core.metapath.cst.math;
7
8 import dev.metaschema.core.metapath.DynamicContext;
9 import dev.metaschema.core.metapath.IExpression;
10 import dev.metaschema.core.metapath.cst.IExpressionVisitor;
11 import dev.metaschema.core.metapath.function.FunctionUtils;
12 import dev.metaschema.core.metapath.function.impl.OperationFunctions;
13 import dev.metaschema.core.metapath.item.ISequence;
14 import dev.metaschema.core.metapath.item.atomic.IAnyAtomicItem;
15 import dev.metaschema.core.metapath.item.atomic.INumericItem;
16 import edu.umd.cs.findbugs.annotations.NonNull;
17 import edu.umd.cs.findbugs.annotations.Nullable;
18
19
20
21
22
23
24
25
26 public class Modulo
27 extends AbstractArithmeticExpression<INumericItem> {
28
29
30
31
32
33
34
35
36
37
38
39
40 public Modulo(
41 @NonNull String text,
42 @NonNull IExpression dividend,
43 @NonNull IExpression divisor) {
44 super(text, dividend, divisor, INumericItem.class);
45 }
46
47 @Override
48 public Class<INumericItem> getBaseResultType() {
49 return INumericItem.class;
50 }
51
52 @Override
53 public <RESULT, CONTEXT> RESULT accept(IExpressionVisitor<RESULT, CONTEXT> visitor, CONTEXT context) {
54 return visitor.visitModulo(this, context);
55 }
56
57 @Override
58 protected ISequence<? extends INumericItem> evaluate(DynamicContext dynamicContext, ISequence<?> focus) {
59 IAnyAtomicItem leftItem = ISequence.of(getLeft().accept(dynamicContext, focus).atomize()).getFirstItem(true);
60 IAnyAtomicItem rightItem = ISequence.of(getRight().accept(dynamicContext, focus).atomize()).getFirstItem(true);
61 INumericItem dividend = leftItem == null ? null : FunctionUtils.castToNumeric(leftItem);
62 INumericItem divisor = rightItem == null ? null : FunctionUtils.castToNumeric(rightItem);
63 return resultOrEmpty(dividend, divisor);
64 }
65
66
67
68
69
70
71
72
73
74
75
76 @NonNull
77 protected static ISequence<? extends INumericItem> resultOrEmpty(@Nullable INumericItem dividend,
78 @Nullable INumericItem divisor) {
79 ISequence<? extends INumericItem> retval;
80 if (dividend == null || divisor == null) {
81 retval = ISequence.empty();
82 } else {
83 INumericItem result = OperationFunctions.opNumericMod(dividend, divisor);
84 retval = ISequence.of(result);
85 }
86 return retval;
87 }
88 }