aboutsummaryrefslogtreecommitdiffstats
path: root/subprojects/store-query/src/main
diff options
context:
space:
mode:
authorLibravatar Kristóf Marussy <kristof@marussy.com>2023-04-23 23:39:39 +0200
committerLibravatar Kristóf Marussy <kristof@marussy.com>2023-04-23 23:42:53 +0200
commit565de1cb116e5e4f116544aaa035be58336656ec (patch)
tree5d4cff8e77e280552f13b9c7f8aafa79a39a0090 /subprojects/store-query/src/main
parentrefactor: simplify ModelAdapter (diff)
downloadrefinery-565de1cb116e5e4f116544aaa035be58336656ec.tar.gz
refinery-565de1cb116e5e4f116544aaa035be58336656ec.tar.zst
refinery-565de1cb116e5e4f116544aaa035be58336656ec.zip
refactor: query terms
* Separate different operators into different classes to make it easier to add functionality (e.g., simplification) later. * Add UpperCardinality terms. * Move UpperCardinality aggregator and tests into refinery-store-query.
Diffstat (limited to 'subprojects/store-query/src/main')
-rw-r--r--subprojects/store-query/src/main/java/tools/refinery/store/query/literal/AssumeLiteral.java13
-rw-r--r--subprojects/store-query/src/main/java/tools/refinery/store/query/substitution/CompositeSubstitution.java15
-rw-r--r--subprojects/store-query/src/main/java/tools/refinery/store/query/substitution/Substitution.java9
-rw-r--r--subprojects/store-query/src/main/java/tools/refinery/store/query/substitution/SubstitutionBuilder.java78
-rw-r--r--subprojects/store-query/src/main/java/tools/refinery/store/query/substitution/Substitutions.java38
-rw-r--r--subprojects/store-query/src/main/java/tools/refinery/store/query/term/AbstractTerm.java41
-rw-r--r--subprojects/store-query/src/main/java/tools/refinery/store/query/term/ArithmeticBinaryOperator.java31
-rw-r--r--subprojects/store-query/src/main/java/tools/refinery/store/query/term/ArithmeticBinaryTerm.java61
-rw-r--r--subprojects/store-query/src/main/java/tools/refinery/store/query/term/ArithmeticUnaryOperator.java21
-rw-r--r--subprojects/store-query/src/main/java/tools/refinery/store/query/term/ArithmeticUnaryTerm.java56
-rw-r--r--subprojects/store-query/src/main/java/tools/refinery/store/query/term/BinaryTerm.java45
-rw-r--r--subprojects/store-query/src/main/java/tools/refinery/store/query/term/ComparisonOperator.java25
-rw-r--r--subprojects/store-query/src/main/java/tools/refinery/store/query/term/ComparisonTerm.java68
-rw-r--r--subprojects/store-query/src/main/java/tools/refinery/store/query/term/ConstantTerm.java42
-rw-r--r--subprojects/store-query/src/main/java/tools/refinery/store/query/term/OpaqueTerm.java85
-rw-r--r--subprojects/store-query/src/main/java/tools/refinery/store/query/term/UnaryTerm.java24
-rw-r--r--subprojects/store-query/src/main/java/tools/refinery/store/query/term/bool/BoolAndTerm.java31
-rw-r--r--subprojects/store-query/src/main/java/tools/refinery/store/query/term/bool/BoolBinaryTerm.java15
-rw-r--r--subprojects/store-query/src/main/java/tools/refinery/store/query/term/bool/BoolConstantTerm.java21
-rw-r--r--subprojects/store-query/src/main/java/tools/refinery/store/query/term/bool/BoolLogicBinaryTerm.java83
-rw-r--r--subprojects/store-query/src/main/java/tools/refinery/store/query/term/bool/BoolNotTerm.java14
-rw-r--r--subprojects/store-query/src/main/java/tools/refinery/store/query/term/bool/BoolOrTerm.java31
-rw-r--r--subprojects/store-query/src/main/java/tools/refinery/store/query/term/bool/BoolTerms.java18
-rw-r--r--subprojects/store-query/src/main/java/tools/refinery/store/query/term/bool/BoolXorTerm.java31
-rw-r--r--subprojects/store-query/src/main/java/tools/refinery/store/query/term/bool/LogicBinaryOperator.java22
-rw-r--r--subprojects/store-query/src/main/java/tools/refinery/store/query/term/comparable/ComparisonTerm.java19
-rw-r--r--subprojects/store-query/src/main/java/tools/refinery/store/query/term/comparable/EqTerm.java30
-rw-r--r--subprojects/store-query/src/main/java/tools/refinery/store/query/term/comparable/GreaterEqTerm.java30
-rw-r--r--subprojects/store-query/src/main/java/tools/refinery/store/query/term/comparable/GreaterTerm.java30
-rw-r--r--subprojects/store-query/src/main/java/tools/refinery/store/query/term/comparable/LessEqTerm.java30
-rw-r--r--subprojects/store-query/src/main/java/tools/refinery/store/query/term/comparable/LessTerm.java30
-rw-r--r--subprojects/store-query/src/main/java/tools/refinery/store/query/term/comparable/NotEqTerm.java30
-rw-r--r--subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntAddTerm.java31
-rw-r--r--subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntArithmeticBinaryTerm.java53
-rw-r--r--subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntArithmeticUnaryTerm.java35
-rw-r--r--subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntBinaryTerm.java15
-rw-r--r--subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntComparisonTerm.java39
-rw-r--r--subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntDivTerm.java31
-rw-r--r--subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntExtremeValueAggregator.java22
-rw-r--r--subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntMaxTerm.java31
-rw-r--r--subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntMinTerm.java31
-rw-r--r--subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntMinusTerm.java30
-rw-r--r--subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntMulTerm.java31
-rw-r--r--subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntPlusTerm.java30
-rw-r--r--subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntPowTerm.java43
-rw-r--r--subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntSubTerm.java31
-rw-r--r--subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntTerms.java78
-rw-r--r--subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntUnaryTerm.java15
-rw-r--r--subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/RealToIntTerm.java16
-rw-r--r--subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/IntToRealTerm.java14
-rw-r--r--subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealAddTerm.java31
-rw-r--r--subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealArithmeticBinaryTerm.java41
-rw-r--r--subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealArithmeticUnaryTerm.java35
-rw-r--r--subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealBinaryTerm.java15
-rw-r--r--subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealComparisonTerm.java40
-rw-r--r--subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealDivTerm.java31
-rw-r--r--subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealExtremeValueAggregator.java22
-rw-r--r--subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealMaxTerm.java31
-rw-r--r--subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealMinTerm.java31
-rw-r--r--subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealMinusTerm.java30
-rw-r--r--subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealMulTerm.java31
-rw-r--r--subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealPlusTerm.java30
-rw-r--r--subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealPowTerm.java31
-rw-r--r--subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealSubTerm.java31
-rw-r--r--subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealTerms.java78
-rw-r--r--subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealUnaryTerm.java15
-rw-r--r--subprojects/store-query/src/main/java/tools/refinery/store/query/term/uppercardinality/UpperCardinalityAddTerm.java31
-rw-r--r--subprojects/store-query/src/main/java/tools/refinery/store/query/term/uppercardinality/UpperCardinalityBinaryTerm.java17
-rw-r--r--subprojects/store-query/src/main/java/tools/refinery/store/query/term/uppercardinality/UpperCardinalityMaxTerm.java31
-rw-r--r--subprojects/store-query/src/main/java/tools/refinery/store/query/term/uppercardinality/UpperCardinalityMinTerm.java31
-rw-r--r--subprojects/store-query/src/main/java/tools/refinery/store/query/term/uppercardinality/UpperCardinalityMulTerm.java31
-rw-r--r--subprojects/store-query/src/main/java/tools/refinery/store/query/term/uppercardinality/UpperCardinalitySumAggregator.java86
-rw-r--r--subprojects/store-query/src/main/java/tools/refinery/store/query/term/uppercardinality/UpperCardinalityTerms.java73
-rw-r--r--subprojects/store-query/src/main/java/tools/refinery/store/query/valuation/MapBasedValuation.java22
-rw-r--r--subprojects/store-query/src/main/java/tools/refinery/store/query/valuation/Valuation.java9
-rw-r--r--subprojects/store-query/src/main/java/tools/refinery/store/query/valuation/ValuationBuilder.java40
76 files changed, 1606 insertions, 981 deletions
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/AssumeLiteral.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/AssumeLiteral.java
index 58d563da..59538831 100644
--- a/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/AssumeLiteral.java
+++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/AssumeLiteral.java
@@ -7,9 +7,9 @@ package tools.refinery.store.query.literal;
7 7
8import tools.refinery.store.query.equality.LiteralEqualityHelper; 8import tools.refinery.store.query.equality.LiteralEqualityHelper;
9import tools.refinery.store.query.substitution.Substitution; 9import tools.refinery.store.query.substitution.Substitution;
10import tools.refinery.store.query.term.ConstantTerm;
10import tools.refinery.store.query.term.Term; 11import tools.refinery.store.query.term.Term;
11import tools.refinery.store.query.term.Variable; 12import tools.refinery.store.query.term.Variable;
12import tools.refinery.store.query.term.bool.BoolConstantTerm;
13 13
14import java.util.Set; 14import java.util.Set;
15 15
@@ -42,13 +42,12 @@ public record AssumeLiteral(Term<Boolean> term) implements Literal {
42 42
43 @Override 43 @Override
44 public LiteralReduction getReduction() { 44 public LiteralReduction getReduction() {
45 if (BoolConstantTerm.TRUE.equals(term)) { 45 if (term instanceof ConstantTerm<Boolean> constantTerm) {
46 return LiteralReduction.ALWAYS_TRUE; 46 // Return {@code ALWAYS_FALSE} for {@code false} or {@code null} literals.
47 } else if (BoolConstantTerm.FALSE.equals(term)) { 47 return Boolean.TRUE.equals(constantTerm.getValue()) ? LiteralReduction.ALWAYS_TRUE :
48 return LiteralReduction.ALWAYS_FALSE; 48 LiteralReduction.ALWAYS_FALSE;
49 } else {
50 return LiteralReduction.NOT_REDUCIBLE;
51 } 49 }
50 return LiteralReduction.NOT_REDUCIBLE;
52 } 51 }
53 52
54 @Override 53 @Override
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/substitution/CompositeSubstitution.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/substitution/CompositeSubstitution.java
deleted file mode 100644
index d175130e..00000000
--- a/subprojects/store-query/src/main/java/tools/refinery/store/query/substitution/CompositeSubstitution.java
+++ /dev/null
@@ -1,15 +0,0 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.query.substitution;
7
8import tools.refinery.store.query.term.Variable;
9
10public record CompositeSubstitution(Substitution first, Substitution second) implements Substitution {
11 @Override
12 public Variable getSubstitute(Variable variable) {
13 return second.getSubstitute(first.getSubstitute(variable));
14 }
15}
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/substitution/Substitution.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/substitution/Substitution.java
index 5714edf4..834fce12 100644
--- a/subprojects/store-query/src/main/java/tools/refinery/store/query/substitution/Substitution.java
+++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/substitution/Substitution.java
@@ -5,7 +5,6 @@
5 */ 5 */
6package tools.refinery.store.query.substitution; 6package tools.refinery.store.query.substitution;
7 7
8import tools.refinery.store.query.term.AnyDataVariable;
9import tools.refinery.store.query.term.DataVariable; 8import tools.refinery.store.query.term.DataVariable;
10import tools.refinery.store.query.term.NodeVariable; 9import tools.refinery.store.query.term.NodeVariable;
11import tools.refinery.store.query.term.Variable; 10import tools.refinery.store.query.term.Variable;
@@ -19,16 +18,12 @@ public interface Substitution {
19 return substitute.asNodeVariable(); 18 return substitute.asNodeVariable();
20 } 19 }
21 20
22 default AnyDataVariable getTypeSafeSubstitute(AnyDataVariable variable) {
23 return getTypeSafeSubstitute((DataVariable<?>) variable);
24 }
25
26 default <T> DataVariable<T> getTypeSafeSubstitute(DataVariable<T> variable) { 21 default <T> DataVariable<T> getTypeSafeSubstitute(DataVariable<T> variable) {
27 var substitute = getSubstitute(variable); 22 var substitute = getSubstitute(variable);
28 return substitute.asDataVariable(variable.getType()); 23 return substitute.asDataVariable(variable.getType());
29 } 24 }
30 25
31 default Substitution andThen(Substitution second) { 26 static SubstitutionBuilder builder() {
32 return new CompositeSubstitution(this, second); 27 return new SubstitutionBuilder();
33 } 28 }
34} 29}
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/substitution/SubstitutionBuilder.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/substitution/SubstitutionBuilder.java
new file mode 100644
index 00000000..658a26e3
--- /dev/null
+++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/substitution/SubstitutionBuilder.java
@@ -0,0 +1,78 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.query.substitution;
7
8import tools.refinery.store.query.term.DataVariable;
9import tools.refinery.store.query.term.NodeVariable;
10import tools.refinery.store.query.term.Variable;
11
12import java.util.Collections;
13import java.util.HashMap;
14import java.util.List;
15import java.util.Map;
16
17@SuppressWarnings("UnusedReturnValue")
18public class SubstitutionBuilder {
19 private final Map<Variable, Variable> map = new HashMap<>();
20 private Substitution fallback;
21
22 SubstitutionBuilder() {
23 total();
24 }
25
26 public SubstitutionBuilder put(NodeVariable original, NodeVariable substitute) {
27 return putChecked(original, substitute);
28 }
29
30 public <T> SubstitutionBuilder put(DataVariable<T> original, DataVariable<T> substitute) {
31 return putChecked(original, substitute);
32 }
33
34 public SubstitutionBuilder putChecked(Variable original, Variable substitute) {
35 if (!original.getSort().equals(substitute.getSort())) {
36 throw new IllegalArgumentException("Cannot substitute variable %s of sort %s with variable %s of sort %s"
37 .formatted(original, original.getSort(), substitute, substitute.getSort()));
38 }
39 if (map.containsKey(original)) {
40 throw new IllegalArgumentException("Already has substitution for variable %s".formatted(original));
41 }
42 map.put(original, substitute);
43 return this;
44 }
45
46 public SubstitutionBuilder putManyChecked(List<Variable> originals, List<Variable> substitutes) {
47 int size = originals.size();
48 if (size != substitutes.size()) {
49 throw new IllegalArgumentException("Cannot substitute %d variables %s with %d variables %s"
50 .formatted(size, originals, substitutes.size(), substitutes));
51 }
52 for (int i = 0; i < size; i++) {
53 putChecked(originals.get(i), substitutes.get(i));
54 }
55 return this;
56 }
57
58 public SubstitutionBuilder fallback(Substitution newFallback) {
59 fallback = newFallback;
60 return this;
61 }
62
63 public SubstitutionBuilder total() {
64 return fallback(StatelessSubstitution.FAILING);
65 }
66
67 public SubstitutionBuilder partial() {
68 return fallback(StatelessSubstitution.IDENTITY);
69 }
70
71 public SubstitutionBuilder renewing() {
72 return fallback(new RenewingSubstitution());
73 }
74
75 public Substitution build() {
76 return map.isEmpty() ? fallback : new MapBasedSubstitution(Collections.unmodifiableMap(map), fallback);
77 }
78}
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/substitution/Substitutions.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/substitution/Substitutions.java
deleted file mode 100644
index c4791bf1..00000000
--- a/subprojects/store-query/src/main/java/tools/refinery/store/query/substitution/Substitutions.java
+++ /dev/null
@@ -1,38 +0,0 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.query.substitution;
7
8import org.jetbrains.annotations.NotNull;
9import org.jetbrains.annotations.Nullable;
10import tools.refinery.store.query.term.Variable;
11
12import java.util.Map;
13
14public final class Substitutions {
15 private Substitutions() {
16 throw new IllegalStateException("This is a static utility class and should not be instantiate directly");
17 }
18
19 public static Substitution total(Map<Variable, Variable> map) {
20 return new MapBasedSubstitution(map, StatelessSubstitution.FAILING);
21 }
22
23 public static Substitution partial(Map<Variable, Variable> map) {
24 return new MapBasedSubstitution(map, StatelessSubstitution.IDENTITY);
25 }
26
27 public static Substitution renewing(Map<Variable, Variable> map) {
28 return new MapBasedSubstitution(map, renewing());
29 }
30
31 public static Substitution renewing() {
32 return new RenewingSubstitution();
33 }
34
35 public static Substitution compose(@Nullable Substitution first, @NotNull Substitution second) {
36 return first == null ? second : first.andThen(second);
37 }
38}
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/AbstractTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/AbstractTerm.java
new file mode 100644
index 00000000..d0ae3c12
--- /dev/null
+++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/AbstractTerm.java
@@ -0,0 +1,41 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.query.term;
7
8import tools.refinery.store.query.equality.LiteralEqualityHelper;
9
10import java.util.Objects;
11
12public abstract class AbstractTerm<T> implements Term<T> {
13 private final Class<T> type;
14
15 protected AbstractTerm(Class<T> type) {
16 this.type = type;
17 }
18
19 @Override
20 public boolean equalsWithSubstitution(LiteralEqualityHelper helper, AnyTerm other) {
21 return getClass().equals(other.getClass()) && type.equals(other.getType());
22 }
23
24 @Override
25 public Class<T> getType() {
26 return type;
27 }
28
29 @Override
30 public boolean equals(Object o) {
31 if (this == o) return true;
32 if (o == null || getClass() != o.getClass()) return false;
33 AbstractTerm<?> that = (AbstractTerm<?>) o;
34 return type.equals(that.type);
35 }
36
37 @Override
38 public int hashCode() {
39 return Objects.hash(getClass(), type);
40 }
41}
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/ArithmeticBinaryOperator.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/ArithmeticBinaryOperator.java
deleted file mode 100644
index 5ff7c65c..00000000
--- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/ArithmeticBinaryOperator.java
+++ /dev/null
@@ -1,31 +0,0 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.query.term;
7
8public enum ArithmeticBinaryOperator {
9 ADD("+", true),
10 SUB("-", true),
11 MUL("*", true),
12 DIV("/", true),
13 POW("**", true),
14 MIN("min", false),
15 MAX("max", false);
16
17 private final String text;
18 private final boolean infix;
19
20 ArithmeticBinaryOperator(String text, boolean infix) {
21 this.text = text;
22 this.infix = infix;
23 }
24
25 public String formatString(String left, String right) {
26 if (infix) {
27 return "(%s) %s (%s)".formatted(left, text, right);
28 }
29 return "%s(%s, %s)".formatted(text, left, right);
30 }
31}
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/ArithmeticBinaryTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/ArithmeticBinaryTerm.java
deleted file mode 100644
index e405df00..00000000
--- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/ArithmeticBinaryTerm.java
+++ /dev/null
@@ -1,61 +0,0 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.query.term;
7
8import tools.refinery.store.query.equality.LiteralEqualityHelper;
9
10import java.util.Objects;
11
12public abstract class ArithmeticBinaryTerm<T> extends BinaryTerm<T, T, T> {
13 private final ArithmeticBinaryOperator operator;
14
15 protected ArithmeticBinaryTerm(ArithmeticBinaryOperator operator, Term<T> left, Term<T> right) {
16 super(left, right);
17 this.operator = operator;
18 }
19
20 @Override
21 public Class<T> getLeftType() {
22 return getType();
23 }
24
25 @Override
26 public Class<T> getRightType() {
27 return getType();
28 }
29
30 public ArithmeticBinaryOperator getOperator() {
31 return operator;
32 }
33
34 @Override
35 public boolean equalsWithSubstitution(LiteralEqualityHelper helper, AnyTerm other) {
36 if (!super.equalsWithSubstitution(helper, other)) {
37 return false;
38 }
39 var otherArithmeticBinaryTerm = (ArithmeticBinaryTerm<?>) other;
40 return operator == otherArithmeticBinaryTerm.operator;
41 }
42
43 @Override
44 public String toString() {
45 return operator.formatString(getLeft().toString(), getRight().toString());
46 }
47
48 @Override
49 public boolean equals(Object o) {
50 if (this == o) return true;
51 if (o == null || getClass() != o.getClass()) return false;
52 if (!super.equals(o)) return false;
53 ArithmeticBinaryTerm<?> that = (ArithmeticBinaryTerm<?>) o;
54 return operator == that.operator;
55 }
56
57 @Override
58 public int hashCode() {
59 return Objects.hash(super.hashCode(), operator);
60 }
61}
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/ArithmeticUnaryOperator.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/ArithmeticUnaryOperator.java
deleted file mode 100644
index d98134f3..00000000
--- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/ArithmeticUnaryOperator.java
+++ /dev/null
@@ -1,21 +0,0 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.query.term;
7
8public enum ArithmeticUnaryOperator {
9 PLUS("+"),
10 MINUS("-");
11
12 private final String prefix;
13
14 ArithmeticUnaryOperator(String prefix) {
15 this.prefix = prefix;
16 }
17
18 public String formatString(String body) {
19 return "%s(%s)".formatted(prefix, body);
20 }
21}
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/ArithmeticUnaryTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/ArithmeticUnaryTerm.java
deleted file mode 100644
index bdc87545..00000000
--- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/ArithmeticUnaryTerm.java
+++ /dev/null
@@ -1,56 +0,0 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.query.term;
7
8import tools.refinery.store.query.equality.LiteralEqualityHelper;
9
10import java.util.Objects;
11
12public abstract class ArithmeticUnaryTerm<T> extends UnaryTerm<T, T> {
13 private final ArithmeticUnaryOperator operator;
14
15 protected ArithmeticUnaryTerm(ArithmeticUnaryOperator operator, Term<T> body) {
16 super(body);
17 this.operator = operator;
18 }
19
20 @Override
21 public Class<T> getBodyType() {
22 return getType();
23 }
24
25 public ArithmeticUnaryOperator getOperator() {
26 return operator;
27 }
28
29 @Override
30 public boolean equalsWithSubstitution(LiteralEqualityHelper helper, AnyTerm other) {
31 if (!super.equalsWithSubstitution(helper, other)) {
32 return false;
33 }
34 var otherArithmeticUnaryTerm = (ArithmeticUnaryTerm<?>) other;
35 return operator == otherArithmeticUnaryTerm.operator;
36 }
37
38 @Override
39 public String toString() {
40 return operator.formatString(getBody().toString());
41 }
42
43 @Override
44 public boolean equals(Object o) {
45 if (this == o) return true;
46 if (o == null || getClass() != o.getClass()) return false;
47 if (!super.equals(o)) return false;
48 ArithmeticUnaryTerm<?> that = (ArithmeticUnaryTerm<?>) o;
49 return operator == that.operator;
50 }
51
52 @Override
53 public int hashCode() {
54 return Objects.hash(super.hashCode(), operator);
55 }
56}
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/BinaryTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/BinaryTerm.java
index b2994d23..8ad17839 100644
--- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/BinaryTerm.java
+++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/BinaryTerm.java
@@ -14,26 +14,35 @@ import java.util.HashSet;
14import java.util.Objects; 14import java.util.Objects;
15import java.util.Set; 15import java.util.Set;
16 16
17public abstract class BinaryTerm<R, T1, T2> implements Term<R> { 17public abstract class BinaryTerm<R, T1, T2> extends AbstractTerm<R> {
18 private final Class<T1> leftType;
19 private final Class<T2> rightType;
18 private final Term<T1> left; 20 private final Term<T1> left;
19 private final Term<T2> right; 21 private final Term<T2> right;
20 22
21 protected BinaryTerm(Term<T1> left, Term<T2> right) { 23 protected BinaryTerm(Class<R> type, Class<T1> leftType, Class<T2> rightType, Term<T1> left, Term<T2> right) {
22 if (!left.getType().equals(getLeftType())) { 24 super(type);
23 throw new IllegalArgumentException("Expected left %s to be of type %s, got %s instead".formatted(left, 25 if (!left.getType().equals(leftType)) {
24 getLeftType().getName(), left.getType().getName())); 26 throw new IllegalArgumentException("Expected left %s to be of type %s, got %s instead".formatted(
27 left, leftType.getName(), left.getType().getName()));
25 } 28 }
26 if (!right.getType().equals(getRightType())) { 29 if (!right.getType().equals(rightType)) {
27 throw new IllegalArgumentException("Expected right %s to be of type %s, got %s instead".formatted(right, 30 throw new IllegalArgumentException("Expected right %s to be of type %s, got %s instead".formatted(
28 getRightType().getName(), right.getType().getName())); 31 right, rightType.getName(), right.getType().getName()));
29 } 32 }
33 this.leftType = leftType;
34 this.rightType = rightType;
30 this.left = left; 35 this.left = left;
31 this.right = right; 36 this.right = right;
32 } 37 }
33 38
34 public abstract Class<T1> getLeftType(); 39 public Class<T1> getLeftType() {
40 return leftType;
41 }
35 42
36 public abstract Class<T2> getRightType(); 43 public Class<T2> getRightType() {
44 return rightType;
45 }
37 46
38 public Term<T1> getLeft() { 47 public Term<T1> getLeft() {
39 return left; 48 return left;
@@ -60,12 +69,14 @@ public abstract class BinaryTerm<R, T1, T2> implements Term<R> {
60 69
61 @Override 70 @Override
62 public boolean equalsWithSubstitution(LiteralEqualityHelper helper, AnyTerm other) { 71 public boolean equalsWithSubstitution(LiteralEqualityHelper helper, AnyTerm other) {
63 if (getClass() != other.getClass()) { 72 if (!super.equalsWithSubstitution(helper, other)) {
64 return false; 73 return false;
65 } 74 }
66 var otherBinaryTerm = (BinaryTerm<?, ?, ?>) other; 75 var otherBinaryTerm = (BinaryTerm<?, ?, ?>) other;
67 return left.equalsWithSubstitution(helper, otherBinaryTerm.left) && right.equalsWithSubstitution(helper, 76 return leftType.equals(otherBinaryTerm.leftType) &&
68 otherBinaryTerm.right); 77 rightType.equals(otherBinaryTerm.rightType) &&
78 left.equalsWithSubstitution(helper, otherBinaryTerm.left) &&
79 right.equalsWithSubstitution(helper, otherBinaryTerm.right);
69 } 80 }
70 81
71 @Override 82 @Override
@@ -87,12 +98,16 @@ public abstract class BinaryTerm<R, T1, T2> implements Term<R> {
87 public boolean equals(Object o) { 98 public boolean equals(Object o) {
88 if (this == o) return true; 99 if (this == o) return true;
89 if (o == null || getClass() != o.getClass()) return false; 100 if (o == null || getClass() != o.getClass()) return false;
101 if (!super.equals(o)) return false;
90 BinaryTerm<?, ?, ?> that = (BinaryTerm<?, ?, ?>) o; 102 BinaryTerm<?, ?, ?> that = (BinaryTerm<?, ?, ?>) o;
91 return left.equals(that.left) && right.equals(that.right); 103 return Objects.equals(leftType, that.leftType) &&
104 Objects.equals(rightType, that.rightType) &&
105 Objects.equals(left, that.left) &&
106 Objects.equals(right, that.right);
92 } 107 }
93 108
94 @Override 109 @Override
95 public int hashCode() { 110 public int hashCode() {
96 return Objects.hash(getClass(), left, right); 111 return Objects.hash(super.hashCode(), leftType, rightType, left, right);
97 } 112 }
98} 113}
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/ComparisonOperator.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/ComparisonOperator.java
deleted file mode 100644
index d04ae22c..00000000
--- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/ComparisonOperator.java
+++ /dev/null
@@ -1,25 +0,0 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.query.term;
7
8public enum ComparisonOperator {
9 EQ("=="),
10 NOT_EQ("!="),
11 LESS("<"),
12 LESS_EQ("<="),
13 GREATER(">"),
14 GREATER_EQ(">=");
15
16 private final String text;
17
18 ComparisonOperator(String text) {
19 this.text = text;
20 }
21
22 public String formatString(String left, String right) {
23 return "(%s) %s (%s)".formatted(left, text, right);
24 }
25}
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/ComparisonTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/ComparisonTerm.java
deleted file mode 100644
index 2c304aef..00000000
--- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/ComparisonTerm.java
+++ /dev/null
@@ -1,68 +0,0 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.query.term;
7
8import tools.refinery.store.query.equality.LiteralEqualityHelper;
9
10import java.util.Objects;
11
12public abstract class ComparisonTerm<T> extends BinaryTerm<Boolean, T, T> {
13 private final ComparisonOperator operator;
14
15 protected ComparisonTerm(ComparisonOperator operator, Term<T> left, Term<T> right) {
16 super(left, right);
17 this.operator = operator;
18 }
19
20 @Override
21 public Class<Boolean> getType() {
22 return Boolean.class;
23 }
24
25 public abstract Class<T> getOperandType();
26
27 @Override
28 public Class<T> getLeftType() {
29 return getOperandType();
30 }
31
32 @Override
33 public Class<T> getRightType() {
34 return getOperandType();
35 }
36
37 public ComparisonOperator getOperator() {
38 return operator;
39 }
40
41 @Override
42 public boolean equalsWithSubstitution(LiteralEqualityHelper helper, AnyTerm other) {
43 if (!super.equalsWithSubstitution(helper, other)) {
44 return false;
45 }
46 var otherComparisonTerm = (ComparisonTerm<?>) other;
47 return operator == otherComparisonTerm.operator;
48 }
49
50 @Override
51 public String toString() {
52 return operator.formatString(getLeft().toString(), getRight().toString());
53 }
54
55 @Override
56 public boolean equals(Object o) {
57 if (this == o) return true;
58 if (o == null || getClass() != o.getClass()) return false;
59 if (!super.equals(o)) return false;
60 ComparisonTerm<?> that = (ComparisonTerm<?>) o;
61 return operator == that.operator;
62 }
63
64 @Override
65 public int hashCode() {
66 return Objects.hash(super.hashCode(), operator);
67 }
68}
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/ConstantTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/ConstantTerm.java
index b03f07fd..2f6c56d1 100644
--- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/ConstantTerm.java
+++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/ConstantTerm.java
@@ -9,21 +9,18 @@ import tools.refinery.store.query.equality.LiteralEqualityHelper;
9import tools.refinery.store.query.substitution.Substitution; 9import tools.refinery.store.query.substitution.Substitution;
10import tools.refinery.store.query.valuation.Valuation; 10import tools.refinery.store.query.valuation.Valuation;
11 11
12import java.util.Objects;
12import java.util.Set; 13import java.util.Set;
13 14
14public record ConstantTerm<T>(Class<T> type, T value) implements Term<T> { 15public final class ConstantTerm<T> extends AbstractTerm<T> {
15 public ConstantTerm { 16 private final T value;
16 if (value == null) {
17 throw new IllegalArgumentException("value should not be null");
18 }
19 if (!type.isInstance(value)) {
20 throw new IllegalArgumentException("value %s is not an instance of %s".formatted(value, type.getName()));
21 }
22 }
23 17
24 @Override 18 public ConstantTerm(Class<T> type, T value) {
25 public Class<T> getType() { 19 super(type);
26 return type; 20 if (value != null && !type.isInstance(value)) {
21 throw new IllegalArgumentException("Value %s is not an instance of %s".formatted(value, type.getName()));
22 }
23 this.value = value;
27 } 24 }
28 25
29 public T getValue() { 26 public T getValue() {
@@ -42,7 +39,11 @@ public record ConstantTerm<T>(Class<T> type, T value) implements Term<T> {
42 39
43 @Override 40 @Override
44 public boolean equalsWithSubstitution(LiteralEqualityHelper helper, AnyTerm other) { 41 public boolean equalsWithSubstitution(LiteralEqualityHelper helper, AnyTerm other) {
45 return equals(other); 42 if (!super.equalsWithSubstitution(helper, other)) {
43 return false;
44 }
45 var otherConstantTerm = (ConstantTerm<?>) other;
46 return Objects.equals(value, otherConstantTerm.value);
46 } 47 }
47 48
48 @Override 49 @Override
@@ -52,6 +53,19 @@ public record ConstantTerm<T>(Class<T> type, T value) implements Term<T> {
52 53
53 @Override 54 @Override
54 public String toString() { 55 public String toString() {
55 return getValue().toString(); 56 return value.toString();
57 }
58
59 @Override
60 public boolean equals(Object o) {
61 if (this == o) return true;
62 if (o == null || getClass() != o.getClass()) return false;
63 ConstantTerm<?> that = (ConstantTerm<?>) o;
64 return Objects.equals(value, that.value);
65 }
66
67 @Override
68 public int hashCode() {
69 return Objects.hash(value);
56 } 70 }
57} 71}
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/OpaqueTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/OpaqueTerm.java
deleted file mode 100644
index 6626365f..00000000
--- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/OpaqueTerm.java
+++ /dev/null
@@ -1,85 +0,0 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.query.term;
7
8import tools.refinery.store.query.equality.LiteralEqualityHelper;
9import tools.refinery.store.query.substitution.Substitution;
10import tools.refinery.store.query.substitution.Substitutions;
11import tools.refinery.store.query.valuation.Valuation;
12
13import java.util.Objects;
14import java.util.Set;
15import java.util.function.Function;
16import java.util.stream.Collectors;
17
18public final class OpaqueTerm<T> implements Term<T> {
19 private final Class<T> type;
20 private final Function<? super Valuation, ? extends T> evaluator;
21 private final Set<AnyDataVariable> variables;
22 private final Substitution substitution;
23
24 public OpaqueTerm(Class<T> type, Function<? super Valuation, ? extends T> evaluator,
25 Set<? extends AnyDataVariable> variables) {
26 this(type, evaluator, variables, null);
27 }
28
29 private OpaqueTerm(Class<T> type, Function<? super Valuation, ? extends T> evaluator,
30 Set<? extends AnyDataVariable> variables, Substitution substitution) {
31 this.type = type;
32 this.evaluator = evaluator;
33 this.variables = Set.copyOf(variables);
34 this.substitution = substitution;
35 }
36
37 @Override
38 public Class<T> getType() {
39 return type;
40 }
41
42 @Override
43 public Set<AnyDataVariable> getInputVariables() {
44 return variables;
45 }
46
47 @Override
48 public T evaluate(Valuation valuation) {
49 return evaluator.apply(valuation.substitute(substitution));
50 }
51
52 @Override
53 public Term<T> substitute(Substitution newSubstitution) {
54 var substitutedVariables = variables.stream()
55 .map(newSubstitution::getTypeSafeSubstitute)
56 .collect(Collectors.toUnmodifiableSet());
57 return new OpaqueTerm<>(type, evaluator, substitutedVariables,
58 Substitutions.compose(substitution, newSubstitution));
59 }
60
61 @Override
62 public boolean equalsWithSubstitution(LiteralEqualityHelper helper, AnyTerm other) {
63 // Cannot inspect the opaque evaluator for deep equality.
64 return equals(other);
65 }
66
67 @Override
68 public String toString() {
69 return "<opaque>";
70 }
71
72 @Override
73 public boolean equals(Object o) {
74 if (this == o) return true;
75 if (o == null || getClass() != o.getClass()) return false;
76 OpaqueTerm<?> that = (OpaqueTerm<?>) o;
77 return type.equals(that.type) && evaluator.equals(that.evaluator) && Objects.equals(substitution,
78 that.substitution);
79 }
80
81 @Override
82 public int hashCode() {
83 return Objects.hash(type, evaluator, substitution);
84 }
85}
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/UnaryTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/UnaryTerm.java
index 069e0d95..a46ebe31 100644
--- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/UnaryTerm.java
+++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/UnaryTerm.java
@@ -12,18 +12,23 @@ import tools.refinery.store.query.valuation.Valuation;
12import java.util.Objects; 12import java.util.Objects;
13import java.util.Set; 13import java.util.Set;
14 14
15public abstract class UnaryTerm<R, T> implements Term<R> { 15public abstract class UnaryTerm<R, T> extends AbstractTerm<R> {
16 private final Class<T> bodyType;
16 private final Term<T> body; 17 private final Term<T> body;
17 18
18 protected UnaryTerm(Term<T> body) { 19 protected UnaryTerm(Class<R> type, Class<T> bodyType, Term<T> body) {
19 if (!body.getType().equals(getBodyType())) { 20 super(type);
21 if (!body.getType().equals(bodyType)) {
20 throw new IllegalArgumentException("Expected body %s to be of type %s, got %s instead".formatted(body, 22 throw new IllegalArgumentException("Expected body %s to be of type %s, got %s instead".formatted(body,
21 getBodyType().getName(), body.getType().getName())); 23 bodyType.getName(), body.getType().getName()));
22 } 24 }
25 this.bodyType = bodyType;
23 this.body = body; 26 this.body = body;
24 } 27 }
25 28
26 public abstract Class<T> getBodyType(); 29 public Class<T> getBodyType() {
30 return bodyType;
31 }
27 32
28 public Term<T> getBody() { 33 public Term<T> getBody() {
29 return body; 34 return body;
@@ -39,11 +44,11 @@ public abstract class UnaryTerm<R, T> implements Term<R> {
39 44
40 @Override 45 @Override
41 public boolean equalsWithSubstitution(LiteralEqualityHelper helper, AnyTerm other) { 46 public boolean equalsWithSubstitution(LiteralEqualityHelper helper, AnyTerm other) {
42 if (getClass() != other.getClass()) { 47 if (!super.equalsWithSubstitution(helper, other)) {
43 return false; 48 return false;
44 } 49 }
45 var otherUnaryTerm = (UnaryTerm<?, ?>) other; 50 var otherUnaryTerm = (UnaryTerm<?, ?>) other;
46 return body.equalsWithSubstitution(helper, otherUnaryTerm.body); 51 return bodyType.equals(otherUnaryTerm.bodyType) && body.equalsWithSubstitution(helper, otherUnaryTerm.body);
47 } 52 }
48 53
49 @Override 54 @Override
@@ -62,12 +67,13 @@ public abstract class UnaryTerm<R, T> implements Term<R> {
62 public boolean equals(Object o) { 67 public boolean equals(Object o) {
63 if (this == o) return true; 68 if (this == o) return true;
64 if (o == null || getClass() != o.getClass()) return false; 69 if (o == null || getClass() != o.getClass()) return false;
70 if (!super.equals(o)) return false;
65 UnaryTerm<?, ?> unaryTerm = (UnaryTerm<?, ?>) o; 71 UnaryTerm<?, ?> unaryTerm = (UnaryTerm<?, ?>) o;
66 return body.equals(unaryTerm.body); 72 return Objects.equals(bodyType, unaryTerm.bodyType) && Objects.equals(body, unaryTerm.body);
67 } 73 }
68 74
69 @Override 75 @Override
70 public int hashCode() { 76 public int hashCode() {
71 return Objects.hash(getClass(), body); 77 return Objects.hash(super.hashCode(), bodyType, body);
72 } 78 }
73} 79}
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/bool/BoolAndTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/bool/BoolAndTerm.java
new file mode 100644
index 00000000..f9e1c06f
--- /dev/null
+++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/bool/BoolAndTerm.java
@@ -0,0 +1,31 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.query.term.bool;
7
8import tools.refinery.store.query.substitution.Substitution;
9import tools.refinery.store.query.term.Term;
10
11public class BoolAndTerm extends BoolBinaryTerm {
12 public BoolAndTerm(Term<Boolean> left, Term<Boolean> right) {
13 super(left, right);
14 }
15
16 @Override
17 public Term<Boolean> doSubstitute(Substitution substitution, Term<Boolean> substitutedLeft,
18 Term<Boolean> substitutedRight) {
19 return new BoolAndTerm(substitutedLeft, substitutedRight);
20 }
21
22 @Override
23 protected Boolean doEvaluate(Boolean leftValue, Boolean rightValue) {
24 return leftValue && rightValue;
25 }
26
27 @Override
28 public String toString() {
29 return "(%s && %s)".formatted(getLeft(), getRight());
30 }
31}
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/bool/BoolBinaryTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/bool/BoolBinaryTerm.java
new file mode 100644
index 00000000..a85aa63a
--- /dev/null
+++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/bool/BoolBinaryTerm.java
@@ -0,0 +1,15 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.query.term.bool;
7
8import tools.refinery.store.query.term.BinaryTerm;
9import tools.refinery.store.query.term.Term;
10
11public abstract class BoolBinaryTerm extends BinaryTerm<Boolean, Boolean, Boolean> {
12 protected BoolBinaryTerm(Term<Boolean> left, Term<Boolean> right) {
13 super(Boolean.class, Boolean.class, Boolean.class, left, right);
14 }
15}
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/bool/BoolConstantTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/bool/BoolConstantTerm.java
deleted file mode 100644
index e5690ab6..00000000
--- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/bool/BoolConstantTerm.java
+++ /dev/null
@@ -1,21 +0,0 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.query.term.bool;
7
8import tools.refinery.store.query.term.ConstantTerm;
9
10public final class BoolConstantTerm {
11 public static final ConstantTerm<Boolean> TRUE = new ConstantTerm<>(Boolean.class, true);
12 public static final ConstantTerm<Boolean> FALSE = new ConstantTerm<>(Boolean.class, false);
13
14 private BoolConstantTerm() {
15 throw new IllegalStateException("This is a static utility class and should not be instantiated directly");
16 }
17
18 public static ConstantTerm<Boolean> valueOf(boolean boolValue) {
19 return boolValue ? TRUE : FALSE;
20 }
21}
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/bool/BoolLogicBinaryTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/bool/BoolLogicBinaryTerm.java
deleted file mode 100644
index 11e764c2..00000000
--- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/bool/BoolLogicBinaryTerm.java
+++ /dev/null
@@ -1,83 +0,0 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.query.term.bool;
7
8import tools.refinery.store.query.equality.LiteralEqualityHelper;
9import tools.refinery.store.query.substitution.Substitution;
10import tools.refinery.store.query.term.*;
11
12import java.util.Objects;
13
14public class BoolLogicBinaryTerm extends BinaryTerm<Boolean, Boolean, Boolean> {
15 private final LogicBinaryOperator operator;
16
17 protected BoolLogicBinaryTerm(LogicBinaryOperator operator, Term<Boolean> left, Term<Boolean> right) {
18 super(left, right);
19 this.operator = operator;
20 }
21
22 @Override
23 public Class<Boolean> getType() {
24 return Boolean.class;
25 }
26
27 @Override
28 public Class<Boolean> getLeftType() {
29 return getType();
30 }
31
32 @Override
33 public Class<Boolean> getRightType() {
34 return getType();
35 }
36
37 public LogicBinaryOperator getOperator() {
38 return operator;
39 }
40
41 @Override
42 public boolean equalsWithSubstitution(LiteralEqualityHelper helper, AnyTerm other) {
43 if (!super.equalsWithSubstitution(helper, other)) {
44 return false;
45 }
46 var otherBoolLogicBinaryTerm = (BoolLogicBinaryTerm) other;
47 return operator == otherBoolLogicBinaryTerm.operator;
48 }
49
50 @Override
51 public Term<Boolean> doSubstitute(Substitution substitution, Term<Boolean> substitutedLeft,
52 Term<Boolean> substitutedRight) {
53 return new BoolLogicBinaryTerm(getOperator(), substitutedLeft, substitutedRight);
54 }
55
56 @Override
57 protected Boolean doEvaluate(Boolean leftValue, Boolean rightValue) {
58 return switch (getOperator()) {
59 case AND -> leftValue && rightValue;
60 case OR -> leftValue || rightValue;
61 case XOR -> leftValue ^ rightValue;
62 };
63 }
64
65 @Override
66 public String toString() {
67 return operator.formatString(getLeft().toString(), getRight().toString());
68 }
69
70 @Override
71 public boolean equals(Object o) {
72 if (this == o) return true;
73 if (o == null || getClass() != o.getClass()) return false;
74 if (!super.equals(o)) return false;
75 BoolLogicBinaryTerm that = (BoolLogicBinaryTerm) o;
76 return operator == that.operator;
77 }
78
79 @Override
80 public int hashCode() {
81 return Objects.hash(super.hashCode(), operator);
82 }
83}
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/bool/BoolNotTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/bool/BoolNotTerm.java
index bb06cf8b..8d3382b3 100644
--- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/bool/BoolNotTerm.java
+++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/bool/BoolNotTerm.java
@@ -11,17 +11,7 @@ import tools.refinery.store.query.term.UnaryTerm;
11 11
12public class BoolNotTerm extends UnaryTerm<Boolean, Boolean> { 12public class BoolNotTerm extends UnaryTerm<Boolean, Boolean> {
13 protected BoolNotTerm(Term<Boolean> body) { 13 protected BoolNotTerm(Term<Boolean> body) {
14 super(body); 14 super(Boolean.class, Boolean.class, body);
15 }
16
17 @Override
18 public Class<Boolean> getType() {
19 return Boolean.class;
20 }
21
22 @Override
23 public Class<Boolean> getBodyType() {
24 return getType();
25 } 15 }
26 16
27 @Override 17 @Override
@@ -36,6 +26,6 @@ public class BoolNotTerm extends UnaryTerm<Boolean, Boolean> {
36 26
37 @Override 27 @Override
38 public String toString() { 28 public String toString() {
39 return "!(%s)".formatted(getBody()); 29 return "(!%s)".formatted(getBody());
40 } 30 }
41} 31}
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/bool/BoolOrTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/bool/BoolOrTerm.java
new file mode 100644
index 00000000..b5195d52
--- /dev/null
+++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/bool/BoolOrTerm.java
@@ -0,0 +1,31 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.query.term.bool;
7
8import tools.refinery.store.query.substitution.Substitution;
9import tools.refinery.store.query.term.Term;
10
11public class BoolOrTerm extends BoolBinaryTerm {
12 public BoolOrTerm(Term<Boolean> left, Term<Boolean> right) {
13 super(left, right);
14 }
15
16 @Override
17 public Term<Boolean> doSubstitute(Substitution substitution, Term<Boolean> substitutedLeft,
18 Term<Boolean> substitutedRight) {
19 return new BoolOrTerm(substitutedLeft, substitutedRight);
20 }
21
22 @Override
23 protected Boolean doEvaluate(Boolean leftValue, Boolean rightValue) {
24 return leftValue || rightValue;
25 }
26
27 @Override
28 public String toString() {
29 return "(%s || %s)".formatted(getLeft(), getRight());
30 }
31}
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/bool/BoolTerms.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/bool/BoolTerms.java
index 55825952..fa54f686 100644
--- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/bool/BoolTerms.java
+++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/bool/BoolTerms.java
@@ -13,23 +13,23 @@ public final class BoolTerms {
13 throw new IllegalArgumentException("This is a static utility class and should not be instantiated directly"); 13 throw new IllegalArgumentException("This is a static utility class and should not be instantiated directly");
14 } 14 }
15 15
16 public static ConstantTerm<Boolean> constant(boolean value) { 16 public static Term<Boolean> constant(Boolean value) {
17 return BoolConstantTerm.valueOf(value); 17 return new ConstantTerm<>(Boolean.class, value);
18 } 18 }
19 19
20 public static BoolNotTerm not(Term<Boolean> body) { 20 public static Term<Boolean> not(Term<Boolean> body) {
21 return new BoolNotTerm(body); 21 return new BoolNotTerm(body);
22 } 22 }
23 23
24 public static BoolLogicBinaryTerm and(Term<Boolean> left, Term<Boolean> right) { 24 public static Term<Boolean> and(Term<Boolean> left, Term<Boolean> right) {
25 return new BoolLogicBinaryTerm(LogicBinaryOperator.AND, left, right); 25 return new BoolAndTerm(left, right);
26 } 26 }
27 27
28 public static BoolLogicBinaryTerm or(Term<Boolean> left, Term<Boolean> right) { 28 public static Term<Boolean> or(Term<Boolean> left, Term<Boolean> right) {
29 return new BoolLogicBinaryTerm(LogicBinaryOperator.OR, left, right); 29 return new BoolOrTerm(left, right);
30 } 30 }
31 31
32 public static BoolLogicBinaryTerm xor(Term<Boolean> left, Term<Boolean> right) { 32 public static Term<Boolean> xor(Term<Boolean> left, Term<Boolean> right) {
33 return new BoolLogicBinaryTerm(LogicBinaryOperator.XOR, left, right); 33 return new BoolXorTerm(left, right);
34 } 34 }
35} 35}
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/bool/BoolXorTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/bool/BoolXorTerm.java
new file mode 100644
index 00000000..7478b8a5
--- /dev/null
+++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/bool/BoolXorTerm.java
@@ -0,0 +1,31 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.query.term.bool;
7
8import tools.refinery.store.query.substitution.Substitution;
9import tools.refinery.store.query.term.Term;
10
11public class BoolXorTerm extends BoolBinaryTerm {
12 public BoolXorTerm(Term<Boolean> left, Term<Boolean> right) {
13 super(left, right);
14 }
15
16 @Override
17 public Term<Boolean> doSubstitute(Substitution substitution, Term<Boolean> substitutedLeft,
18 Term<Boolean> substitutedRight) {
19 return new BoolXorTerm(substitutedLeft, substitutedRight);
20 }
21
22 @Override
23 protected Boolean doEvaluate(Boolean leftValue, Boolean rightValue) {
24 return leftValue ^ rightValue;
25 }
26
27 @Override
28 public String toString() {
29 return "(%s ^^ %s)".formatted(getLeft(), getRight());
30 }
31}
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/bool/LogicBinaryOperator.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/bool/LogicBinaryOperator.java
deleted file mode 100644
index 93a72f88..00000000
--- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/bool/LogicBinaryOperator.java
+++ /dev/null
@@ -1,22 +0,0 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.query.term.bool;
7
8public enum LogicBinaryOperator {
9 AND("&&"),
10 OR("||"),
11 XOR("^^");
12
13 private final String text;
14
15 LogicBinaryOperator(String text) {
16 this.text = text;
17 }
18
19 public String formatString(String left, String right) {
20 return "(%s) %s (%s)".formatted(left, text, right);
21 }
22}
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/comparable/ComparisonTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/comparable/ComparisonTerm.java
new file mode 100644
index 00000000..5ca5a0a1
--- /dev/null
+++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/comparable/ComparisonTerm.java
@@ -0,0 +1,19 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.query.term.comparable;
7
8import tools.refinery.store.query.term.BinaryTerm;
9import tools.refinery.store.query.term.Term;
10
11public abstract class ComparisonTerm<T> extends BinaryTerm<Boolean, T, T> {
12 protected ComparisonTerm(Class<T> argumentType, Term<T> left, Term<T> right) {
13 super(Boolean.class, argumentType, argumentType, left, right);
14 }
15
16 public Class<T> getArgumentType() {
17 return getLeftType();
18 }
19}
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/comparable/EqTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/comparable/EqTerm.java
new file mode 100644
index 00000000..b8cf36f8
--- /dev/null
+++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/comparable/EqTerm.java
@@ -0,0 +1,30 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.query.term.comparable;
7
8import tools.refinery.store.query.substitution.Substitution;
9import tools.refinery.store.query.term.Term;
10
11public class EqTerm<T> extends ComparisonTerm<T> {
12 public EqTerm(Class<T> argumentType, Term<T> left, Term<T> right) {
13 super(argumentType, left, right);
14 }
15
16 @Override
17 protected Boolean doEvaluate(T leftValue, T rightValue) {
18 return leftValue.equals(rightValue);
19 }
20
21 @Override
22 public Term<Boolean> doSubstitute(Substitution substitution, Term<T> substitutedLeft, Term<T> substitutedRight) {
23 return new EqTerm<>(getArgumentType(), substitutedLeft, substitutedRight);
24 }
25
26 @Override
27 public String toString() {
28 return "(%s == %s)".formatted(getLeft(), getRight());
29 }
30}
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/comparable/GreaterEqTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/comparable/GreaterEqTerm.java
new file mode 100644
index 00000000..b109eb1a
--- /dev/null
+++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/comparable/GreaterEqTerm.java
@@ -0,0 +1,30 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.query.term.comparable;
7
8import tools.refinery.store.query.substitution.Substitution;
9import tools.refinery.store.query.term.Term;
10
11public class GreaterEqTerm<T extends Comparable<T>> extends ComparisonTerm<T> {
12 public GreaterEqTerm(Class<T> argumentType, Term<T> left, Term<T> right) {
13 super(argumentType, left, right);
14 }
15
16 @Override
17 protected Boolean doEvaluate(T leftValue, T rightValue) {
18 return leftValue.compareTo(rightValue) >= 0;
19 }
20
21 @Override
22 public Term<Boolean> doSubstitute(Substitution substitution, Term<T> substitutedLeft, Term<T> substitutedRight) {
23 return new GreaterEqTerm<>(getArgumentType(), substitutedLeft, substitutedRight);
24 }
25
26 @Override
27 public String toString() {
28 return "(%s >= %s)".formatted(getLeft(), getRight());
29 }
30}
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/comparable/GreaterTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/comparable/GreaterTerm.java
new file mode 100644
index 00000000..1b67f8b5
--- /dev/null
+++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/comparable/GreaterTerm.java
@@ -0,0 +1,30 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.query.term.comparable;
7
8import tools.refinery.store.query.substitution.Substitution;
9import tools.refinery.store.query.term.Term;
10
11public class GreaterTerm<T extends Comparable<T>> extends ComparisonTerm<T> {
12 public GreaterTerm(Class<T> argumentType, Term<T> left, Term<T> right) {
13 super(argumentType, left, right);
14 }
15
16 @Override
17 protected Boolean doEvaluate(T leftValue, T rightValue) {
18 return leftValue.compareTo(rightValue) > 0;
19 }
20
21 @Override
22 public Term<Boolean> doSubstitute(Substitution substitution, Term<T> substitutedLeft, Term<T> substitutedRight) {
23 return new GreaterTerm<>(getArgumentType(), substitutedLeft, substitutedRight);
24 }
25
26 @Override
27 public String toString() {
28 return "(%s > %s)".formatted(getLeft(), getRight());
29 }
30}
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/comparable/LessEqTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/comparable/LessEqTerm.java
new file mode 100644
index 00000000..1b34535f
--- /dev/null
+++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/comparable/LessEqTerm.java
@@ -0,0 +1,30 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.query.term.comparable;
7
8import tools.refinery.store.query.substitution.Substitution;
9import tools.refinery.store.query.term.Term;
10
11public class LessEqTerm<T extends Comparable<T>> extends ComparisonTerm<T> {
12 public LessEqTerm(Class<T> argumentType, Term<T> left, Term<T> right) {
13 super(argumentType, left, right);
14 }
15
16 @Override
17 protected Boolean doEvaluate(T leftValue, T rightValue) {
18 return leftValue.compareTo(rightValue) <= 0;
19 }
20
21 @Override
22 public Term<Boolean> doSubstitute(Substitution substitution, Term<T> substitutedLeft, Term<T> substitutedRight) {
23 return new LessEqTerm<>(getArgumentType(), substitutedLeft, substitutedRight);
24 }
25
26 @Override
27 public String toString() {
28 return "(%s <= %s)".formatted(getLeft(), getRight());
29 }
30}
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/comparable/LessTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/comparable/LessTerm.java
new file mode 100644
index 00000000..44e70902
--- /dev/null
+++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/comparable/LessTerm.java
@@ -0,0 +1,30 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.query.term.comparable;
7
8import tools.refinery.store.query.substitution.Substitution;
9import tools.refinery.store.query.term.Term;
10
11public class LessTerm<T extends Comparable<T>> extends ComparisonTerm<T> {
12 public LessTerm(Class<T> argumentType, Term<T> left, Term<T> right) {
13 super(argumentType, left, right);
14 }
15
16 @Override
17 protected Boolean doEvaluate(T leftValue, T rightValue) {
18 return leftValue.compareTo(rightValue) < 0;
19 }
20
21 @Override
22 public Term<Boolean> doSubstitute(Substitution substitution, Term<T> substitutedLeft, Term<T> substitutedRight) {
23 return new LessTerm<>(getArgumentType(), substitutedLeft, substitutedRight);
24 }
25
26 @Override
27 public String toString() {
28 return "(%s < %s)".formatted(getLeft(), getRight());
29 }
30}
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/comparable/NotEqTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/comparable/NotEqTerm.java
new file mode 100644
index 00000000..1f9734c4
--- /dev/null
+++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/comparable/NotEqTerm.java
@@ -0,0 +1,30 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.query.term.comparable;
7
8import tools.refinery.store.query.substitution.Substitution;
9import tools.refinery.store.query.term.Term;
10
11public class NotEqTerm<T> extends ComparisonTerm<T> {
12 public NotEqTerm(Class<T> argumentType, Term<T> left, Term<T> right) {
13 super(argumentType, left, right);
14 }
15
16 @Override
17 protected Boolean doEvaluate(T leftValue, T rightValue) {
18 return !leftValue.equals(rightValue);
19 }
20
21 @Override
22 public Term<Boolean> doSubstitute(Substitution substitution, Term<T> substitutedLeft, Term<T> substitutedRight) {
23 return new NotEqTerm<>(getArgumentType(), substitutedLeft, substitutedRight);
24 }
25
26 @Override
27 public String toString() {
28 return "(%s != %s)".formatted(getLeft(), getRight());
29 }
30}
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntAddTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntAddTerm.java
new file mode 100644
index 00000000..dbea3efc
--- /dev/null
+++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntAddTerm.java
@@ -0,0 +1,31 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.query.term.int_;
7
8import tools.refinery.store.query.substitution.Substitution;
9import tools.refinery.store.query.term.Term;
10
11public class IntAddTerm extends IntBinaryTerm {
12 public IntAddTerm(Term<Integer> left, Term<Integer> right) {
13 super(left, right);
14 }
15
16 @Override
17 public Term<Integer> doSubstitute(Substitution substitution, Term<Integer> substitutedLeft,
18 Term<Integer> substitutedRight) {
19 return new IntAddTerm(substitutedLeft, substitutedRight);
20 }
21
22 @Override
23 protected Integer doEvaluate(Integer leftValue, Integer rightValue) {
24 return leftValue + rightValue;
25 }
26
27 @Override
28 public String toString() {
29 return "(%s + %s)".formatted(getLeft(), getRight());
30 }
31}
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntArithmeticBinaryTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntArithmeticBinaryTerm.java
deleted file mode 100644
index 8a76ecbd..00000000
--- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntArithmeticBinaryTerm.java
+++ /dev/null
@@ -1,53 +0,0 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.query.term.int_;
7
8import tools.refinery.store.query.substitution.Substitution;
9import tools.refinery.store.query.term.ArithmeticBinaryOperator;
10import tools.refinery.store.query.term.ArithmeticBinaryTerm;
11import tools.refinery.store.query.term.Term;
12
13public class IntArithmeticBinaryTerm extends ArithmeticBinaryTerm<Integer> {
14 public IntArithmeticBinaryTerm(ArithmeticBinaryOperator operator, Term<Integer> left, Term<Integer> right) {
15 super(operator, left, right);
16 }
17
18 @Override
19 public Class<Integer> getType() {
20 return Integer.class;
21 }
22
23 @Override
24 public Term<Integer> doSubstitute(Substitution substitution, Term<Integer> substitutedLeft,
25 Term<Integer> substitutedRight) {
26 return new IntArithmeticBinaryTerm(getOperator(), substitutedLeft, substitutedRight);
27 }
28
29 @Override
30 protected Integer doEvaluate(Integer leftValue, Integer rightValue) {
31 return switch (getOperator()) {
32 case ADD -> leftValue + rightValue;
33 case SUB -> leftValue - rightValue;
34 case MUL -> leftValue * rightValue;
35 case DIV -> rightValue == 0 ? null : leftValue / rightValue;
36 case POW -> rightValue < 0 ? null : power(leftValue, rightValue);
37 case MIN -> Math.min(leftValue, rightValue);
38 case MAX -> Math.max(leftValue, rightValue);
39 };
40 }
41
42 private static int power(int base, int exponent) {
43 int accum = 1;
44 while (exponent > 0) {
45 if (exponent % 2 == 1) {
46 accum = accum * base;
47 }
48 base = base * base;
49 exponent = exponent / 2;
50 }
51 return accum;
52 }
53}
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntArithmeticUnaryTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntArithmeticUnaryTerm.java
deleted file mode 100644
index 8522f2c1..00000000
--- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntArithmeticUnaryTerm.java
+++ /dev/null
@@ -1,35 +0,0 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.query.term.int_;
7
8import tools.refinery.store.query.substitution.Substitution;
9import tools.refinery.store.query.term.Term;
10import tools.refinery.store.query.term.ArithmeticUnaryOperator;
11import tools.refinery.store.query.term.ArithmeticUnaryTerm;
12
13public class IntArithmeticUnaryTerm extends ArithmeticUnaryTerm<Integer> {
14 public IntArithmeticUnaryTerm(ArithmeticUnaryOperator operation, Term<Integer> body) {
15 super(operation, body);
16 }
17
18 @Override
19 public Class<Integer> getType() {
20 return Integer.class;
21 }
22
23 @Override
24 protected Term<Integer> doSubstitute(Substitution substitution, Term<Integer> substitutedBody) {
25 return new IntArithmeticUnaryTerm(getOperator(), substitutedBody);
26 }
27
28 @Override
29 protected Integer doEvaluate(Integer bodyValue) {
30 return switch(getOperator()) {
31 case PLUS -> bodyValue;
32 case MINUS -> -bodyValue;
33 };
34 }
35}
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntBinaryTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntBinaryTerm.java
new file mode 100644
index 00000000..27ced4e4
--- /dev/null
+++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntBinaryTerm.java
@@ -0,0 +1,15 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.query.term.int_;
7
8import tools.refinery.store.query.term.BinaryTerm;
9import tools.refinery.store.query.term.Term;
10
11public abstract class IntBinaryTerm extends BinaryTerm<Integer, Integer, Integer> {
12 protected IntBinaryTerm(Term<Integer> left, Term<Integer> right) {
13 super(Integer.class, Integer.class, Integer.class, left, right);
14 }
15}
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntComparisonTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntComparisonTerm.java
deleted file mode 100644
index 2ce2b2f3..00000000
--- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntComparisonTerm.java
+++ /dev/null
@@ -1,39 +0,0 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.query.term.int_;
7import tools.refinery.store.query.substitution.Substitution;
8import tools.refinery.store.query.term.ComparisonOperator;
9import tools.refinery.store.query.term.ComparisonTerm;
10import tools.refinery.store.query.term.Term;
11
12public class IntComparisonTerm extends ComparisonTerm<Integer> {
13 public IntComparisonTerm(ComparisonOperator operator, Term<Integer> left, Term<Integer> right) {
14 super(operator, left, right);
15 }
16
17 @Override
18 public Class<Integer> getOperandType() {
19 return Integer.class;
20 }
21
22 @Override
23 public Term<Boolean> doSubstitute(Substitution substitution, Term<Integer> substitutedLeft,
24 Term<Integer> substitutedRight) {
25 return new IntComparisonTerm(getOperator(), substitutedLeft, substitutedRight);
26 }
27
28 @Override
29 protected Boolean doEvaluate(Integer leftValue, Integer rightValue) {
30 return switch (getOperator()) {
31 case EQ -> leftValue.equals(rightValue);
32 case NOT_EQ -> !leftValue.equals(rightValue);
33 case LESS -> leftValue < rightValue;
34 case LESS_EQ -> leftValue <= rightValue;
35 case GREATER -> leftValue > rightValue;
36 case GREATER_EQ -> leftValue >= rightValue;
37 };
38 }
39}
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntDivTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntDivTerm.java
new file mode 100644
index 00000000..2a35058c
--- /dev/null
+++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntDivTerm.java
@@ -0,0 +1,31 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.query.term.int_;
7
8import tools.refinery.store.query.substitution.Substitution;
9import tools.refinery.store.query.term.Term;
10
11public class IntDivTerm extends IntBinaryTerm {
12 public IntDivTerm(Term<Integer> left, Term<Integer> right) {
13 super(left, right);
14 }
15
16 @Override
17 public Term<Integer> doSubstitute(Substitution substitution, Term<Integer> substitutedLeft,
18 Term<Integer> substitutedRight) {
19 return new IntDivTerm(substitutedLeft, substitutedRight);
20 }
21
22 @Override
23 protected Integer doEvaluate(Integer leftValue, Integer rightValue) {
24 return rightValue == 0 ? null : leftValue / rightValue;
25 }
26
27 @Override
28 public String toString() {
29 return "(%s / %s)".formatted(getLeft(), getRight());
30 }
31}
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntExtremeValueAggregator.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntExtremeValueAggregator.java
deleted file mode 100644
index 7982f45c..00000000
--- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntExtremeValueAggregator.java
+++ /dev/null
@@ -1,22 +0,0 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.query.term.int_;
7
8import tools.refinery.store.query.term.ExtremeValueAggregator;
9
10import java.util.Comparator;
11
12public final class IntExtremeValueAggregator {
13 public static final ExtremeValueAggregator<Integer> MINIMUM = new ExtremeValueAggregator<>(Integer.class,
14 Integer.MAX_VALUE);
15
16 public static final ExtremeValueAggregator<Integer> MAXIMUM = new ExtremeValueAggregator<>(Integer.class,
17 Integer.MIN_VALUE, Comparator.reverseOrder());
18
19 private IntExtremeValueAggregator() {
20 throw new IllegalStateException("This is a static utility class and should not be instantiated directly");
21 }
22}
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntMaxTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntMaxTerm.java
new file mode 100644
index 00000000..f81fc509
--- /dev/null
+++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntMaxTerm.java
@@ -0,0 +1,31 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.query.term.int_;
7
8import tools.refinery.store.query.substitution.Substitution;
9import tools.refinery.store.query.term.Term;
10
11public class IntMaxTerm extends IntBinaryTerm {
12 public IntMaxTerm(Term<Integer> left, Term<Integer> right) {
13 super(left, right);
14 }
15
16 @Override
17 public Term<Integer> doSubstitute(Substitution substitution, Term<Integer> substitutedLeft,
18 Term<Integer> substitutedRight) {
19 return new IntMaxTerm(substitutedLeft, substitutedRight);
20 }
21
22 @Override
23 protected Integer doEvaluate(Integer leftValue, Integer rightValue) {
24 return Math.max(rightValue, leftValue);
25 }
26
27 @Override
28 public String toString() {
29 return "max(%s, %s)".formatted(getLeft(), getRight());
30 }
31}
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntMinTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntMinTerm.java
new file mode 100644
index 00000000..89182e26
--- /dev/null
+++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntMinTerm.java
@@ -0,0 +1,31 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.query.term.int_;
7
8import tools.refinery.store.query.substitution.Substitution;
9import tools.refinery.store.query.term.Term;
10
11public class IntMinTerm extends IntBinaryTerm {
12 public IntMinTerm(Term<Integer> left, Term<Integer> right) {
13 super(left, right);
14 }
15
16 @Override
17 public Term<Integer> doSubstitute(Substitution substitution, Term<Integer> substitutedLeft,
18 Term<Integer> substitutedRight) {
19 return new IntMinTerm(substitutedLeft, substitutedRight);
20 }
21
22 @Override
23 protected Integer doEvaluate(Integer leftValue, Integer rightValue) {
24 return Math.min(rightValue, leftValue);
25 }
26
27 @Override
28 public String toString() {
29 return "min(%s, %s)".formatted(getLeft(), getRight());
30 }
31}
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntMinusTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntMinusTerm.java
new file mode 100644
index 00000000..709aa5ba
--- /dev/null
+++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntMinusTerm.java
@@ -0,0 +1,30 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.query.term.int_;
7
8import tools.refinery.store.query.substitution.Substitution;
9import tools.refinery.store.query.term.Term;
10
11public class IntMinusTerm extends IntUnaryTerm {
12 public IntMinusTerm(Term<Integer> body) {
13 super(body);
14 }
15
16 @Override
17 protected Term<Integer> doSubstitute(Substitution substitution, Term<Integer> substitutedBody) {
18 return new IntMinusTerm(substitutedBody);
19 }
20
21 @Override
22 protected Integer doEvaluate(Integer bodyValue) {
23 return -bodyValue;
24 }
25
26 @Override
27 public String toString() {
28 return "(-%s)".formatted(getBody());
29 }
30}
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntMulTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntMulTerm.java
new file mode 100644
index 00000000..89d4c5f4
--- /dev/null
+++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntMulTerm.java
@@ -0,0 +1,31 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.query.term.int_;
7
8import tools.refinery.store.query.substitution.Substitution;
9import tools.refinery.store.query.term.Term;
10
11public class IntMulTerm extends IntBinaryTerm {
12 public IntMulTerm(Term<Integer> left, Term<Integer> right) {
13 super(left, right);
14 }
15
16 @Override
17 public Term<Integer> doSubstitute(Substitution substitution, Term<Integer> substitutedLeft,
18 Term<Integer> substitutedRight) {
19 return new IntMulTerm(substitutedLeft, substitutedRight);
20 }
21
22 @Override
23 protected Integer doEvaluate(Integer leftValue, Integer rightValue) {
24 return leftValue * rightValue;
25 }
26
27 @Override
28 public String toString() {
29 return "(%s * %s)".formatted(getLeft(), getRight());
30 }
31}
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntPlusTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntPlusTerm.java
new file mode 100644
index 00000000..aef83bb4
--- /dev/null
+++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntPlusTerm.java
@@ -0,0 +1,30 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.query.term.int_;
7
8import tools.refinery.store.query.substitution.Substitution;
9import tools.refinery.store.query.term.Term;
10
11public class IntPlusTerm extends IntUnaryTerm {
12 public IntPlusTerm(Term<Integer> body) {
13 super(body);
14 }
15
16 @Override
17 protected Term<Integer> doSubstitute(Substitution substitution, Term<Integer> substitutedBody) {
18 return new IntPlusTerm(substitutedBody);
19 }
20
21 @Override
22 protected Integer doEvaluate(Integer bodyValue) {
23 return bodyValue;
24 }
25
26 @Override
27 public String toString() {
28 return "(+%s)".formatted(getBody());
29 }
30}
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntPowTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntPowTerm.java
new file mode 100644
index 00000000..d5af97a1
--- /dev/null
+++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntPowTerm.java
@@ -0,0 +1,43 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.query.term.int_;
7
8import tools.refinery.store.query.substitution.Substitution;
9import tools.refinery.store.query.term.Term;
10
11public class IntPowTerm extends IntBinaryTerm {
12 public IntPowTerm(Term<Integer> left, Term<Integer> right) {
13 super(left, right);
14 }
15
16 @Override
17 public Term<Integer> doSubstitute(Substitution substitution, Term<Integer> substitutedLeft,
18 Term<Integer> substitutedRight) {
19 return new IntPowTerm(substitutedLeft, substitutedRight);
20 }
21
22 @Override
23 protected Integer doEvaluate(Integer leftValue, Integer rightValue) {
24 return rightValue < 0 ? null : power(leftValue, rightValue);
25 }
26
27 private static int power(int base, int exponent) {
28 int accum = 1;
29 while (exponent > 0) {
30 if (exponent % 2 == 1) {
31 accum = accum * base;
32 }
33 base = base * base;
34 exponent = exponent / 2;
35 }
36 return accum;
37 }
38
39 @Override
40 public String toString() {
41 return "(%s ** %s)".formatted(getLeft(), getRight());
42 }
43}
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntSubTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntSubTerm.java
new file mode 100644
index 00000000..2c27afb1
--- /dev/null
+++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntSubTerm.java
@@ -0,0 +1,31 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.query.term.int_;
7
8import tools.refinery.store.query.substitution.Substitution;
9import tools.refinery.store.query.term.Term;
10
11public class IntSubTerm extends IntBinaryTerm {
12 public IntSubTerm(Term<Integer> left, Term<Integer> right) {
13 super(left, right);
14 }
15
16 @Override
17 public Term<Integer> doSubstitute(Substitution substitution, Term<Integer> substitutedLeft,
18 Term<Integer> substitutedRight) {
19 return new IntSubTerm(substitutedLeft, substitutedRight);
20 }
21
22 @Override
23 protected Integer doEvaluate(Integer leftValue, Integer rightValue) {
24 return leftValue - rightValue;
25 }
26
27 @Override
28 public String toString() {
29 return "(%s - %s)".formatted(getLeft(), getRight());
30 }
31}
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntTerms.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntTerms.java
index 38f7f449..acb98b94 100644
--- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntTerms.java
+++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntTerms.java
@@ -5,82 +5,90 @@
5 */ 5 */
6package tools.refinery.store.query.term.int_; 6package tools.refinery.store.query.term.int_;
7 7
8import tools.refinery.store.query.term.*; 8import tools.refinery.store.query.term.Aggregator;
9import tools.refinery.store.query.term.ConstantTerm;
10import tools.refinery.store.query.term.ExtremeValueAggregator;
11import tools.refinery.store.query.term.Term;
12import tools.refinery.store.query.term.comparable.*;
13
14import java.util.Comparator;
9 15
10public final class IntTerms { 16public final class IntTerms {
11 public static final Aggregator<Integer, Integer> INT_SUM = IntSumAggregator.INSTANCE; 17 public static final Aggregator<Integer, Integer> INT_SUM = IntSumAggregator.INSTANCE;
12 public static final Aggregator<Integer, Integer> INT_MIN = IntExtremeValueAggregator.MINIMUM; 18 public static final Aggregator<Integer, Integer> INT_MIN = new ExtremeValueAggregator<>(Integer.class,
13 public static final Aggregator<Integer, Integer> INT_MAX = IntExtremeValueAggregator.MAXIMUM; 19 Integer.MAX_VALUE);
20 public static final Aggregator<Integer, Integer> INT_MAX = new ExtremeValueAggregator<>(Integer.class,
21 Integer.MIN_VALUE, Comparator.reverseOrder());
14 22
15 private IntTerms() { 23 private IntTerms() {
16 throw new IllegalArgumentException("This is a static utility class and should not be instantiated directly"); 24 throw new IllegalArgumentException("This is a static utility class and should not be instantiated directly");
17 } 25 }
18 26
19 public static ConstantTerm<Integer> constant(int value) { 27 public static Term<Integer> constant(Integer value) {
20 return new ConstantTerm<>(Integer.class, value); 28 return new ConstantTerm<>(Integer.class, value);
21 } 29 }
22 30
23 public static IntArithmeticUnaryTerm plus(Term<Integer> body) { 31 public static Term<Integer> plus(Term<Integer> body) {
24 return new IntArithmeticUnaryTerm(ArithmeticUnaryOperator.PLUS, body); 32 return new IntPlusTerm(body);
25 } 33 }
26 34
27 public static IntArithmeticUnaryTerm minus(Term<Integer> body) { 35 public static Term<Integer> minus(Term<Integer> body) {
28 return new IntArithmeticUnaryTerm(ArithmeticUnaryOperator.MINUS, body); 36 return new IntMinusTerm(body);
29 } 37 }
30 38
31 public static IntArithmeticBinaryTerm add(Term<Integer> left, Term<Integer> right) { 39 public static Term<Integer> add(Term<Integer> left, Term<Integer> right) {
32 return new IntArithmeticBinaryTerm(ArithmeticBinaryOperator.ADD, left, right); 40 return new IntAddTerm(left, right);
33 } 41 }
34 42
35 public static IntArithmeticBinaryTerm sub(Term<Integer> left, Term<Integer> right) { 43 public static Term<Integer> sub(Term<Integer> left, Term<Integer> right) {
36 return new IntArithmeticBinaryTerm(ArithmeticBinaryOperator.SUB, left, right); 44 return new IntSubTerm(left, right);
37 } 45 }
38 46
39 public static IntArithmeticBinaryTerm mul(Term<Integer> left, Term<Integer> right) { 47 public static Term<Integer> mul(Term<Integer> left, Term<Integer> right) {
40 return new IntArithmeticBinaryTerm(ArithmeticBinaryOperator.MUL, left, right); 48 return new IntMulTerm(left, right);
41 } 49 }
42 50
43 public static IntArithmeticBinaryTerm div(Term<Integer> left, Term<Integer> right) { 51 public static Term<Integer> div(Term<Integer> left, Term<Integer> right) {
44 return new IntArithmeticBinaryTerm(ArithmeticBinaryOperator.DIV, left, right); 52 return new IntDivTerm(left, right);
45 } 53 }
46 54
47 public static IntArithmeticBinaryTerm pow(Term<Integer> left, Term<Integer> right) { 55 public static Term<Integer> pow(Term<Integer> left, Term<Integer> right) {
48 return new IntArithmeticBinaryTerm(ArithmeticBinaryOperator.POW, left, right); 56 return new IntPowTerm(left, right);
49 } 57 }
50 58
51 public static IntArithmeticBinaryTerm min(Term<Integer> left, Term<Integer> right) { 59 public static Term<Integer> min(Term<Integer> left, Term<Integer> right) {
52 return new IntArithmeticBinaryTerm(ArithmeticBinaryOperator.MIN, left, right); 60 return new IntMinTerm(left, right);
53 } 61 }
54 62
55 public static IntArithmeticBinaryTerm max(Term<Integer> left, Term<Integer> right) { 63 public static Term<Integer> max(Term<Integer> left, Term<Integer> right) {
56 return new IntArithmeticBinaryTerm(ArithmeticBinaryOperator.MAX, left, right); 64 return new IntMaxTerm(left, right);
57 } 65 }
58 66
59 public static IntComparisonTerm eq(Term<Integer> left, Term<Integer> right) { 67 public static Term<Boolean> eq(Term<Integer> left, Term<Integer> right) {
60 return new IntComparisonTerm(ComparisonOperator.EQ, left, right); 68 return new EqTerm<>(Integer.class, left, right);
61 } 69 }
62 70
63 public static IntComparisonTerm notEq(Term<Integer> left, Term<Integer> right) { 71 public static Term<Boolean> notEq(Term<Integer> left, Term<Integer> right) {
64 return new IntComparisonTerm(ComparisonOperator.NOT_EQ, left, right); 72 return new NotEqTerm<>(Integer.class, left, right);
65 } 73 }
66 74
67 public static IntComparisonTerm less(Term<Integer> left, Term<Integer> right) { 75 public static Term<Boolean> less(Term<Integer> left, Term<Integer> right) {
68 return new IntComparisonTerm(ComparisonOperator.LESS, left, right); 76 return new LessTerm<>(Integer.class, left, right);
69 } 77 }
70 78
71 public static IntComparisonTerm lessEq(Term<Integer> left, Term<Integer> right) { 79 public static Term<Boolean> lessEq(Term<Integer> left, Term<Integer> right) {
72 return new IntComparisonTerm(ComparisonOperator.LESS_EQ, left, right); 80 return new LessEqTerm<>(Integer.class, left, right);
73 } 81 }
74 82
75 public static IntComparisonTerm greater(Term<Integer> left, Term<Integer> right) { 83 public static Term<Boolean> greater(Term<Integer> left, Term<Integer> right) {
76 return new IntComparisonTerm(ComparisonOperator.GREATER, left, right); 84 return new GreaterTerm<>(Integer.class, left, right);
77 } 85 }
78 86
79 public static IntComparisonTerm greaterEq(Term<Integer> left, Term<Integer> right) { 87 public static Term<Boolean> greaterEq(Term<Integer> left, Term<Integer> right) {
80 return new IntComparisonTerm(ComparisonOperator.GREATER_EQ, left, right); 88 return new GreaterEqTerm<>(Integer.class, left, right);
81 } 89 }
82 90
83 public static RealToIntTerm asInt(Term<Double> body) { 91 public static Term<Integer> asInt(Term<Double> body) {
84 return new RealToIntTerm(body); 92 return new RealToIntTerm(body);
85 } 93 }
86} 94}
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntUnaryTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntUnaryTerm.java
new file mode 100644
index 00000000..49b4c647
--- /dev/null
+++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntUnaryTerm.java
@@ -0,0 +1,15 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.query.term.int_;
7
8import tools.refinery.store.query.term.Term;
9import tools.refinery.store.query.term.UnaryTerm;
10
11public abstract class IntUnaryTerm extends UnaryTerm<Integer, Integer> {
12 protected IntUnaryTerm(Term<Integer> body) {
13 super(Integer.class, Integer.class, body);
14 }
15}
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/RealToIntTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/RealToIntTerm.java
index 399adf4a..7d383562 100644
--- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/RealToIntTerm.java
+++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/RealToIntTerm.java
@@ -11,22 +11,12 @@ import tools.refinery.store.query.term.UnaryTerm;
11 11
12public class RealToIntTerm extends UnaryTerm<Integer, Double> { 12public class RealToIntTerm extends UnaryTerm<Integer, Double> {
13 protected RealToIntTerm(Term<Double> body) { 13 protected RealToIntTerm(Term<Double> body) {
14 super(body); 14 super(Integer.class, Double.class, body);
15 }
16
17 @Override
18 public Class<Integer> getType() {
19 return Integer.class;
20 }
21
22 @Override
23 public Class<Double> getBodyType() {
24 return Double.class;
25 } 15 }
26 16
27 @Override 17 @Override
28 protected Integer doEvaluate(Double bodyValue) { 18 protected Integer doEvaluate(Double bodyValue) {
29 return bodyValue.intValue(); 19 return bodyValue.isNaN() ? null : bodyValue.intValue();
30 } 20 }
31 21
32 @Override 22 @Override
@@ -36,6 +26,6 @@ public class RealToIntTerm extends UnaryTerm<Integer, Double> {
36 26
37 @Override 27 @Override
38 public String toString() { 28 public String toString() {
39 return "(%s) as int".formatted(getBody()); 29 return "(%s as int)".formatted(getBody());
40 } 30 }
41} 31}
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/IntToRealTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/IntToRealTerm.java
index 4f7d5687..2f53117a 100644
--- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/IntToRealTerm.java
+++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/IntToRealTerm.java
@@ -11,17 +11,7 @@ import tools.refinery.store.query.term.UnaryTerm;
11 11
12public class IntToRealTerm extends UnaryTerm<Double, Integer> { 12public class IntToRealTerm extends UnaryTerm<Double, Integer> {
13 protected IntToRealTerm(Term<Integer> body) { 13 protected IntToRealTerm(Term<Integer> body) {
14 super(body); 14 super(Double.class, Integer.class, body);
15 }
16
17 @Override
18 public Class<Double> getType() {
19 return Double.class;
20 }
21
22 @Override
23 public Class<Integer> getBodyType() {
24 return Integer.class;
25 } 15 }
26 16
27 @Override 17 @Override
@@ -36,6 +26,6 @@ public class IntToRealTerm extends UnaryTerm<Double, Integer> {
36 26
37 @Override 27 @Override
38 public String toString() { 28 public String toString() {
39 return "(%s) as real".formatted(getBody()); 29 return "(%s as real)".formatted(getBody());
40 } 30 }
41} 31}
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealAddTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealAddTerm.java
new file mode 100644
index 00000000..33fc9e41
--- /dev/null
+++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealAddTerm.java
@@ -0,0 +1,31 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.query.term.real;
7
8import tools.refinery.store.query.substitution.Substitution;
9import tools.refinery.store.query.term.Term;
10
11public class RealAddTerm extends RealBinaryTerm {
12 public RealAddTerm(Term<Double> left, Term<Double> right) {
13 super(left, right);
14 }
15
16 @Override
17 public Term<Double> doSubstitute(Substitution substitution, Term<Double> substitutedLeft,
18 Term<Double> substitutedRight) {
19 return new RealAddTerm(substitutedLeft, substitutedRight);
20 }
21
22 @Override
23 protected Double doEvaluate(Double leftValue, Double rightValue) {
24 return leftValue + rightValue;
25 }
26
27 @Override
28 public String toString() {
29 return "(%s + %s)".formatted(getLeft(), getRight());
30 }
31}
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealArithmeticBinaryTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealArithmeticBinaryTerm.java
deleted file mode 100644
index 8d5c9242..00000000
--- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealArithmeticBinaryTerm.java
+++ /dev/null
@@ -1,41 +0,0 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.query.term.real;
7
8import tools.refinery.store.query.substitution.Substitution;
9import tools.refinery.store.query.term.ArithmeticBinaryOperator;
10import tools.refinery.store.query.term.ArithmeticBinaryTerm;
11import tools.refinery.store.query.term.Term;
12
13public class RealArithmeticBinaryTerm extends ArithmeticBinaryTerm<Double> {
14 public RealArithmeticBinaryTerm(ArithmeticBinaryOperator operator, Term<Double> left, Term<Double> right) {
15 super(operator, left, right);
16 }
17
18 @Override
19 public Class<Double> getType() {
20 return Double.class;
21 }
22
23 @Override
24 public Term<Double> doSubstitute(Substitution substitution, Term<Double> substitutedLeft,
25 Term<Double> substitutedRight) {
26 return new RealArithmeticBinaryTerm(getOperator(), substitutedLeft, substitutedRight);
27 }
28
29 @Override
30 protected Double doEvaluate(Double leftValue, Double rightValue) {
31 return switch (getOperator()) {
32 case ADD -> leftValue + rightValue;
33 case SUB -> leftValue - rightValue;
34 case MUL -> leftValue * rightValue;
35 case DIV -> leftValue / rightValue;
36 case POW -> Math.pow(leftValue, rightValue);
37 case MIN -> Math.min(leftValue, rightValue);
38 case MAX -> Math.max(leftValue, rightValue);
39 };
40 }
41}
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealArithmeticUnaryTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealArithmeticUnaryTerm.java
deleted file mode 100644
index 9d233dfc..00000000
--- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealArithmeticUnaryTerm.java
+++ /dev/null
@@ -1,35 +0,0 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.query.term.real;
7
8import tools.refinery.store.query.substitution.Substitution;
9import tools.refinery.store.query.term.ArithmeticUnaryOperator;
10import tools.refinery.store.query.term.ArithmeticUnaryTerm;
11import tools.refinery.store.query.term.Term;
12
13public class RealArithmeticUnaryTerm extends ArithmeticUnaryTerm<Double> {
14 public RealArithmeticUnaryTerm(ArithmeticUnaryOperator operation, Term<Double> body) {
15 super(operation, body);
16 }
17
18 @Override
19 public Class<Double> getType() {
20 return Double.class;
21 }
22
23 @Override
24 protected Term<Double> doSubstitute(Substitution substitution, Term<Double> substitutedBody) {
25 return new RealArithmeticUnaryTerm(getOperator(), substitutedBody);
26 }
27
28 @Override
29 protected Double doEvaluate(Double bodyValue) {
30 return switch(getOperator()) {
31 case PLUS -> bodyValue;
32 case MINUS -> -bodyValue;
33 };
34 }
35}
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealBinaryTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealBinaryTerm.java
new file mode 100644
index 00000000..000f3623
--- /dev/null
+++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealBinaryTerm.java
@@ -0,0 +1,15 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.query.term.real;
7
8import tools.refinery.store.query.term.BinaryTerm;
9import tools.refinery.store.query.term.Term;
10
11public abstract class RealBinaryTerm extends BinaryTerm<Double, Double, Double> {
12 protected RealBinaryTerm(Term<Double> left, Term<Double> right) {
13 super(Double.class, Double.class, Double.class, left, right);
14 }
15}
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealComparisonTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealComparisonTerm.java
deleted file mode 100644
index 25c88f89..00000000
--- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealComparisonTerm.java
+++ /dev/null
@@ -1,40 +0,0 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.query.term.real;
7
8import tools.refinery.store.query.substitution.Substitution;
9import tools.refinery.store.query.term.ComparisonOperator;
10import tools.refinery.store.query.term.ComparisonTerm;
11import tools.refinery.store.query.term.Term;
12
13public class RealComparisonTerm extends ComparisonTerm<Double> {
14 public RealComparisonTerm(ComparisonOperator operator, Term<Double> left, Term<Double> right) {
15 super(operator, left, right);
16 }
17
18 @Override
19 public Class<Double> getOperandType() {
20 return Double.class;
21 }
22
23 @Override
24 public Term<Boolean> doSubstitute(Substitution substitution, Term<Double> substitutedLeft,
25 Term<Double> substitutedRight) {
26 return new RealComparisonTerm(getOperator(), substitutedLeft, substitutedRight);
27 }
28
29 @Override
30 protected Boolean doEvaluate(Double leftValue, Double rightValue) {
31 return switch (getOperator()) {
32 case EQ -> leftValue.equals(rightValue);
33 case NOT_EQ -> !leftValue.equals(rightValue);
34 case LESS -> leftValue < rightValue;
35 case LESS_EQ -> leftValue <= rightValue;
36 case GREATER -> leftValue > rightValue;
37 case GREATER_EQ -> leftValue >= rightValue;
38 };
39 }
40}
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealDivTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealDivTerm.java
new file mode 100644
index 00000000..1e55bf42
--- /dev/null
+++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealDivTerm.java
@@ -0,0 +1,31 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.query.term.real;
7
8import tools.refinery.store.query.substitution.Substitution;
9import tools.refinery.store.query.term.Term;
10
11public class RealDivTerm extends RealBinaryTerm {
12 public RealDivTerm(Term<Double> left, Term<Double> right) {
13 super(left, right);
14 }
15
16 @Override
17 public Term<Double> doSubstitute(Substitution substitution, Term<Double> substitutedLeft,
18 Term<Double> substitutedRight) {
19 return new RealDivTerm(substitutedLeft, substitutedRight);
20 }
21
22 @Override
23 protected Double doEvaluate(Double leftValue, Double rightValue) {
24 return leftValue / rightValue;
25 }
26
27 @Override
28 public String toString() {
29 return "(%s / %s)".formatted(getLeft(), getRight());
30 }
31}
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealExtremeValueAggregator.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealExtremeValueAggregator.java
deleted file mode 100644
index 526e643b..00000000
--- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealExtremeValueAggregator.java
+++ /dev/null
@@ -1,22 +0,0 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.query.term.real;
7
8import tools.refinery.store.query.term.ExtremeValueAggregator;
9
10import java.util.Comparator;
11
12public final class RealExtremeValueAggregator {
13 public static final ExtremeValueAggregator<Double> MINIMUM = new ExtremeValueAggregator<>(Double.class,
14 Double.POSITIVE_INFINITY);
15
16 public static final ExtremeValueAggregator<Double> MAXIMUM = new ExtremeValueAggregator<>(Double.class,
17 Double.NEGATIVE_INFINITY, Comparator.reverseOrder());
18
19 private RealExtremeValueAggregator() {
20 throw new IllegalStateException("This is a static utility class and should not be instantiated directly");
21 }
22}
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealMaxTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealMaxTerm.java
new file mode 100644
index 00000000..2a249496
--- /dev/null
+++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealMaxTerm.java
@@ -0,0 +1,31 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.query.term.real;
7
8import tools.refinery.store.query.substitution.Substitution;
9import tools.refinery.store.query.term.Term;
10
11public class RealMaxTerm extends RealBinaryTerm {
12 public RealMaxTerm(Term<Double> left, Term<Double> right) {
13 super(left, right);
14 }
15
16 @Override
17 public Term<Double> doSubstitute(Substitution substitution, Term<Double> substitutedLeft,
18 Term<Double> substitutedRight) {
19 return new RealMaxTerm(substitutedLeft, substitutedRight);
20 }
21
22 @Override
23 protected Double doEvaluate(Double leftValue, Double rightValue) {
24 return Math.max(leftValue, rightValue);
25 }
26
27 @Override
28 public String toString() {
29 return "max(%s, %s)".formatted(getLeft(), getRight());
30 }
31}
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealMinTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealMinTerm.java
new file mode 100644
index 00000000..2eb4cc1e
--- /dev/null
+++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealMinTerm.java
@@ -0,0 +1,31 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.query.term.real;
7
8import tools.refinery.store.query.substitution.Substitution;
9import tools.refinery.store.query.term.Term;
10
11public class RealMinTerm extends RealBinaryTerm {
12 public RealMinTerm(Term<Double> left, Term<Double> right) {
13 super(left, right);
14 }
15
16 @Override
17 public Term<Double> doSubstitute(Substitution substitution, Term<Double> substitutedLeft,
18 Term<Double> substitutedRight) {
19 return new RealMinTerm(substitutedLeft, substitutedRight);
20 }
21
22 @Override
23 protected Double doEvaluate(Double leftValue, Double rightValue) {
24 return Math.min(leftValue, rightValue);
25 }
26
27 @Override
28 public String toString() {
29 return "min(%s, %s)".formatted(getLeft(), getRight());
30 }
31}
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealMinusTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealMinusTerm.java
new file mode 100644
index 00000000..4afec7a1
--- /dev/null
+++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealMinusTerm.java
@@ -0,0 +1,30 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.query.term.real;
7
8import tools.refinery.store.query.substitution.Substitution;
9import tools.refinery.store.query.term.Term;
10
11public class RealMinusTerm extends RealUnaryTerm {
12 public RealMinusTerm(Term<Double> body) {
13 super(body);
14 }
15
16 @Override
17 protected Term<Double> doSubstitute(Substitution substitution, Term<Double> substitutedBody) {
18 return new RealMinusTerm(substitutedBody);
19 }
20
21 @Override
22 protected Double doEvaluate(Double bodyValue) {
23 return -bodyValue;
24 }
25
26 @Override
27 public String toString() {
28 return "(-%s)".formatted(getBody());
29 }
30}
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealMulTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealMulTerm.java
new file mode 100644
index 00000000..ec95ac6f
--- /dev/null
+++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealMulTerm.java
@@ -0,0 +1,31 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.query.term.real;
7
8import tools.refinery.store.query.substitution.Substitution;
9import tools.refinery.store.query.term.Term;
10
11public class RealMulTerm extends RealBinaryTerm {
12 public RealMulTerm(Term<Double> left, Term<Double> right) {
13 super(left, right);
14 }
15
16 @Override
17 public Term<Double> doSubstitute(Substitution substitution, Term<Double> substitutedLeft,
18 Term<Double> substitutedRight) {
19 return new RealMulTerm(substitutedLeft, substitutedRight);
20 }
21
22 @Override
23 protected Double doEvaluate(Double leftValue, Double rightValue) {
24 return leftValue * rightValue;
25 }
26
27 @Override
28 public String toString() {
29 return "(%s * %s)".formatted(getLeft(), getRight());
30 }
31}
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealPlusTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealPlusTerm.java
new file mode 100644
index 00000000..64dd2e70
--- /dev/null
+++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealPlusTerm.java
@@ -0,0 +1,30 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.query.term.real;
7
8import tools.refinery.store.query.substitution.Substitution;
9import tools.refinery.store.query.term.Term;
10
11public class RealPlusTerm extends RealUnaryTerm {
12 public RealPlusTerm(Term<Double> body) {
13 super(body);
14 }
15
16 @Override
17 protected Term<Double> doSubstitute(Substitution substitution, Term<Double> substitutedBody) {
18 return new RealPlusTerm(substitutedBody);
19 }
20
21 @Override
22 protected Double doEvaluate(Double bodyValue) {
23 return bodyValue;
24 }
25
26 @Override
27 public String toString() {
28 return "(+%s)".formatted(getBody());
29 }
30}
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealPowTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealPowTerm.java
new file mode 100644
index 00000000..11c952ea
--- /dev/null
+++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealPowTerm.java
@@ -0,0 +1,31 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.query.term.real;
7
8import tools.refinery.store.query.substitution.Substitution;
9import tools.refinery.store.query.term.Term;
10
11public class RealPowTerm extends RealBinaryTerm {
12 public RealPowTerm(Term<Double> left, Term<Double> right) {
13 super(left, right);
14 }
15
16 @Override
17 public Term<Double> doSubstitute(Substitution substitution, Term<Double> substitutedLeft,
18 Term<Double> substitutedRight) {
19 return new RealPowTerm(substitutedLeft, substitutedRight);
20 }
21
22 @Override
23 protected Double doEvaluate(Double leftValue, Double rightValue) {
24 return Math.pow(leftValue, rightValue);
25 }
26
27 @Override
28 public String toString() {
29 return "(%s ** %s)".formatted(getLeft(), getRight());
30 }
31}
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealSubTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealSubTerm.java
new file mode 100644
index 00000000..8cc701ed
--- /dev/null
+++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealSubTerm.java
@@ -0,0 +1,31 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.query.term.real;
7
8import tools.refinery.store.query.substitution.Substitution;
9import tools.refinery.store.query.term.Term;
10
11public class RealSubTerm extends RealBinaryTerm {
12 public RealSubTerm(Term<Double> left, Term<Double> right) {
13 super(left, right);
14 }
15
16 @Override
17 public Term<Double> doSubstitute(Substitution substitution, Term<Double> substitutedLeft,
18 Term<Double> substitutedRight) {
19 return new RealSubTerm(substitutedLeft, substitutedRight);
20 }
21
22 @Override
23 protected Double doEvaluate(Double leftValue, Double rightValue) {
24 return leftValue - rightValue;
25 }
26
27 @Override
28 public String toString() {
29 return "(%s - %s)".formatted(getLeft(), getRight());
30 }
31}
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealTerms.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealTerms.java
index 1240d478..79220358 100644
--- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealTerms.java
+++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealTerms.java
@@ -5,82 +5,90 @@
5 */ 5 */
6package tools.refinery.store.query.term.real; 6package tools.refinery.store.query.term.real;
7 7
8import tools.refinery.store.query.term.*; 8import tools.refinery.store.query.term.Aggregator;
9import tools.refinery.store.query.term.ConstantTerm;
10import tools.refinery.store.query.term.ExtremeValueAggregator;
11import tools.refinery.store.query.term.Term;
12import tools.refinery.store.query.term.comparable.*;
13
14import java.util.Comparator;
9 15
10public final class RealTerms { 16public final class RealTerms {
11 public static final Aggregator<Double, Double> REAL_SUM = RealSumAggregator.INSTANCE; 17 public static final Aggregator<Double, Double> REAL_SUM = RealSumAggregator.INSTANCE;
12 public static final Aggregator<Double, Double> REAL_MIN = RealExtremeValueAggregator.MINIMUM; 18 public static final Aggregator<Double, Double> REAL_MIN = new ExtremeValueAggregator<>(Double.class,
13 public static final Aggregator<Double, Double> REAL_MAX = RealExtremeValueAggregator.MAXIMUM; 19 Double.POSITIVE_INFINITY);
20 public static final Aggregator<Double, Double> REAL_MAX = new ExtremeValueAggregator<>(Double.class,
21 Double.NEGATIVE_INFINITY, Comparator.reverseOrder());
14 22
15 private RealTerms() { 23 private RealTerms() {
16 throw new IllegalArgumentException("This is a static utility class and should not be instantiated directly"); 24 throw new IllegalArgumentException("This is a static utility class and should not be instantiated directly");
17 } 25 }
18 26
19 public static ConstantTerm<Double> constant(double value) { 27 public static Term<Double> constant(Double value) {
20 return new ConstantTerm<>(Double.class, value); 28 return new ConstantTerm<>(Double.class, value);
21 } 29 }
22 30
23 public static RealArithmeticUnaryTerm plus(Term<Double> body) { 31 public static Term<Double> plus(Term<Double> body) {
24 return new RealArithmeticUnaryTerm(ArithmeticUnaryOperator.PLUS, body); 32 return new RealPlusTerm(body);
25 } 33 }
26 34
27 public static RealArithmeticUnaryTerm minus(Term<Double> body) { 35 public static Term<Double> minus(Term<Double> body) {
28 return new RealArithmeticUnaryTerm(ArithmeticUnaryOperator.MINUS, body); 36 return new RealMinusTerm(body);
29 } 37 }
30 38
31 public static RealArithmeticBinaryTerm add(Term<Double> left, Term<Double> right) { 39 public static Term<Double> add(Term<Double> left, Term<Double> right) {
32 return new RealArithmeticBinaryTerm(ArithmeticBinaryOperator.ADD, left, right); 40 return new RealAddTerm(left, right);
33 } 41 }
34 42
35 public static RealArithmeticBinaryTerm sub(Term<Double> left, Term<Double> right) { 43 public static Term<Double> sub(Term<Double> left, Term<Double> right) {
36 return new RealArithmeticBinaryTerm(ArithmeticBinaryOperator.SUB, left, right); 44 return new RealSubTerm(left, right);
37 } 45 }
38 46
39 public static RealArithmeticBinaryTerm mul(Term<Double> left, Term<Double> right) { 47 public static Term<Double> mul(Term<Double> left, Term<Double> right) {
40 return new RealArithmeticBinaryTerm(ArithmeticBinaryOperator.MUL, left, right); 48 return new RealMulTerm(left, right);
41 } 49 }
42 50
43 public static RealArithmeticBinaryTerm div(Term<Double> left, Term<Double> right) { 51 public static Term<Double> div(Term<Double> left, Term<Double> right) {
44 return new RealArithmeticBinaryTerm(ArithmeticBinaryOperator.DIV, left, right); 52 return new RealDivTerm(left, right);
45 } 53 }
46 54
47 public static RealArithmeticBinaryTerm pow(Term<Double> left, Term<Double> right) { 55 public static Term<Double> pow(Term<Double> left, Term<Double> right) {
48 return new RealArithmeticBinaryTerm(ArithmeticBinaryOperator.POW, left, right); 56 return new RealPowTerm(left, right);
49 } 57 }
50 58
51 public static RealArithmeticBinaryTerm min(Term<Double> left, Term<Double> right) { 59 public static Term<Double> min(Term<Double> left, Term<Double> right) {
52 return new RealArithmeticBinaryTerm(ArithmeticBinaryOperator.MIN, left, right); 60 return new RealMinTerm(left, right);
53 } 61 }
54 62
55 public static RealArithmeticBinaryTerm max(Term<Double> left, Term<Double> right) { 63 public static Term<Double> max(Term<Double> left, Term<Double> right) {
56 return new RealArithmeticBinaryTerm(ArithmeticBinaryOperator.MAX, left, right); 64 return new RealMaxTerm(left, right);
57 } 65 }
58 66
59 public static RealComparisonTerm eq(Term<Double> left, Term<Double> right) { 67 public static Term<Boolean> eq(Term<Double> left, Term<Double> right) {
60 return new RealComparisonTerm(ComparisonOperator.EQ, left, right); 68 return new EqTerm<>(Double.class, left, right);
61 } 69 }
62 70
63 public static RealComparisonTerm notEq(Term<Double> left, Term<Double> right) { 71 public static Term<Boolean> notEq(Term<Double> left, Term<Double> right) {
64 return new RealComparisonTerm(ComparisonOperator.NOT_EQ, left, right); 72 return new NotEqTerm<>(Double.class, left, right);
65 } 73 }
66 74
67 public static RealComparisonTerm less(Term<Double> left, Term<Double> right) { 75 public static Term<Boolean> less(Term<Double> left, Term<Double> right) {
68 return new RealComparisonTerm(ComparisonOperator.LESS, left, right); 76 return new LessTerm<>(Double.class, left, right);
69 } 77 }
70 78
71 public static RealComparisonTerm lessEq(Term<Double> left, Term<Double> right) { 79 public static Term<Boolean> lessEq(Term<Double> left, Term<Double> right) {
72 return new RealComparisonTerm(ComparisonOperator.LESS_EQ, left, right); 80 return new LessEqTerm<>(Double.class, left, right);
73 } 81 }
74 82
75 public static RealComparisonTerm greater(Term<Double> left, Term<Double> right) { 83 public static Term<Boolean> greater(Term<Double> left, Term<Double> right) {
76 return new RealComparisonTerm(ComparisonOperator.GREATER, left, right); 84 return new GreaterTerm<>(Double.class, left, right);
77 } 85 }
78 86
79 public static RealComparisonTerm greaterEq(Term<Double> left, Term<Double> right) { 87 public static Term<Boolean> greaterEq(Term<Double> left, Term<Double> right) {
80 return new RealComparisonTerm(ComparisonOperator.GREATER_EQ, left, right); 88 return new GreaterEqTerm<>(Double.class, left, right);
81 } 89 }
82 90
83 public static IntToRealTerm asReal(Term<Integer> body) { 91 public static Term<Double> asReal(Term<Integer> body) {
84 return new IntToRealTerm(body); 92 return new IntToRealTerm(body);
85 } 93 }
86} 94}
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealUnaryTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealUnaryTerm.java
new file mode 100644
index 00000000..d41c4ed9
--- /dev/null
+++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealUnaryTerm.java
@@ -0,0 +1,15 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.query.term.real;
7
8import tools.refinery.store.query.term.Term;
9import tools.refinery.store.query.term.UnaryTerm;
10
11public abstract class RealUnaryTerm extends UnaryTerm<Double, Double> {
12 protected RealUnaryTerm(Term<Double> body) {
13 super(Double.class, Double.class, body);
14 }
15}
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/uppercardinality/UpperCardinalityAddTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/uppercardinality/UpperCardinalityAddTerm.java
new file mode 100644
index 00000000..68905f51
--- /dev/null
+++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/uppercardinality/UpperCardinalityAddTerm.java
@@ -0,0 +1,31 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.query.term.uppercardinality;
7
8import tools.refinery.store.query.substitution.Substitution;
9import tools.refinery.store.query.term.Term;
10import tools.refinery.store.representation.cardinality.UpperCardinality;
11
12public class UpperCardinalityAddTerm extends UpperCardinalityBinaryTerm {
13 protected UpperCardinalityAddTerm(Term<UpperCardinality> left, Term<UpperCardinality> right) {
14 super(left, right);
15 }
16
17 @Override
18 protected UpperCardinality doEvaluate(UpperCardinality leftValue, UpperCardinality rightValue) {
19 return leftValue.add(rightValue);
20 }
21
22 @Override
23 public Term<UpperCardinality> doSubstitute(Substitution substitution, Term<UpperCardinality> substitutedLeft, Term<UpperCardinality> substitutedRight) {
24 return new UpperCardinalityAddTerm(substitutedLeft, substitutedRight);
25 }
26
27 @Override
28 public String toString() {
29 return "(%s + %s)".formatted(getLeft(), getRight());
30 }
31}
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/uppercardinality/UpperCardinalityBinaryTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/uppercardinality/UpperCardinalityBinaryTerm.java
new file mode 100644
index 00000000..0cf8fe44
--- /dev/null
+++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/uppercardinality/UpperCardinalityBinaryTerm.java
@@ -0,0 +1,17 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.query.term.uppercardinality;
7
8import tools.refinery.store.query.term.BinaryTerm;
9import tools.refinery.store.query.term.Term;
10import tools.refinery.store.representation.cardinality.UpperCardinality;
11
12public abstract class UpperCardinalityBinaryTerm extends BinaryTerm<UpperCardinality, UpperCardinality,
13 UpperCardinality> {
14 protected UpperCardinalityBinaryTerm(Term<UpperCardinality> left, Term<UpperCardinality> right) {
15 super(UpperCardinality.class, UpperCardinality.class, UpperCardinality.class, left, right);
16 }
17}
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/uppercardinality/UpperCardinalityMaxTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/uppercardinality/UpperCardinalityMaxTerm.java
new file mode 100644
index 00000000..ff75f64e
--- /dev/null
+++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/uppercardinality/UpperCardinalityMaxTerm.java
@@ -0,0 +1,31 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.query.term.uppercardinality;
7
8import tools.refinery.store.query.substitution.Substitution;
9import tools.refinery.store.query.term.Term;
10import tools.refinery.store.representation.cardinality.UpperCardinality;
11
12public class UpperCardinalityMaxTerm extends UpperCardinalityBinaryTerm {
13 protected UpperCardinalityMaxTerm(Term<UpperCardinality> left, Term<UpperCardinality> right) {
14 super(left, right);
15 }
16
17 @Override
18 protected UpperCardinality doEvaluate(UpperCardinality leftValue, UpperCardinality rightValue) {
19 return leftValue.max(rightValue);
20 }
21
22 @Override
23 public Term<UpperCardinality> doSubstitute(Substitution substitution, Term<UpperCardinality> substitutedLeft, Term<UpperCardinality> substitutedRight) {
24 return new UpperCardinalityMaxTerm(substitutedLeft, substitutedRight);
25 }
26
27 @Override
28 public String toString() {
29 return "max(%s, %s)".formatted(getLeft(), getRight());
30 }
31}
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/uppercardinality/UpperCardinalityMinTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/uppercardinality/UpperCardinalityMinTerm.java
new file mode 100644
index 00000000..1e89e9f4
--- /dev/null
+++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/uppercardinality/UpperCardinalityMinTerm.java
@@ -0,0 +1,31 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.query.term.uppercardinality;
7
8import tools.refinery.store.query.substitution.Substitution;
9import tools.refinery.store.query.term.Term;
10import tools.refinery.store.representation.cardinality.UpperCardinality;
11
12public class UpperCardinalityMinTerm extends UpperCardinalityBinaryTerm {
13 protected UpperCardinalityMinTerm(Term<UpperCardinality> left, Term<UpperCardinality> right) {
14 super(left, right);
15 }
16
17 @Override
18 protected UpperCardinality doEvaluate(UpperCardinality leftValue, UpperCardinality rightValue) {
19 return leftValue.min(rightValue);
20 }
21
22 @Override
23 public Term<UpperCardinality> doSubstitute(Substitution substitution, Term<UpperCardinality> substitutedLeft, Term<UpperCardinality> substitutedRight) {
24 return new UpperCardinalityMinTerm(substitutedLeft, substitutedRight);
25 }
26
27 @Override
28 public String toString() {
29 return "min(%s, %s)".formatted(getLeft(), getRight());
30 }
31}
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/uppercardinality/UpperCardinalityMulTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/uppercardinality/UpperCardinalityMulTerm.java
new file mode 100644
index 00000000..3b4970f4
--- /dev/null
+++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/uppercardinality/UpperCardinalityMulTerm.java
@@ -0,0 +1,31 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.query.term.uppercardinality;
7
8import tools.refinery.store.query.substitution.Substitution;
9import tools.refinery.store.query.term.Term;
10import tools.refinery.store.representation.cardinality.UpperCardinality;
11
12public class UpperCardinalityMulTerm extends UpperCardinalityBinaryTerm {
13 protected UpperCardinalityMulTerm(Term<UpperCardinality> left, Term<UpperCardinality> right) {
14 super(left, right);
15 }
16
17 @Override
18 protected UpperCardinality doEvaluate(UpperCardinality leftValue, UpperCardinality rightValue) {
19 return leftValue.multiply(rightValue);
20 }
21
22 @Override
23 public Term<UpperCardinality> doSubstitute(Substitution substitution, Term<UpperCardinality> substitutedLeft, Term<UpperCardinality> substitutedRight) {
24 return new UpperCardinalityMulTerm(substitutedLeft, substitutedRight);
25 }
26
27 @Override
28 public String toString() {
29 return "(%s * %s)".formatted(getLeft(), getRight());
30 }
31}
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/uppercardinality/UpperCardinalitySumAggregator.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/uppercardinality/UpperCardinalitySumAggregator.java
new file mode 100644
index 00000000..5bbd3081
--- /dev/null
+++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/uppercardinality/UpperCardinalitySumAggregator.java
@@ -0,0 +1,86 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.query.term.uppercardinality;
7
8import tools.refinery.store.query.term.StatefulAggregate;
9import tools.refinery.store.query.term.StatefulAggregator;
10import tools.refinery.store.representation.cardinality.FiniteUpperCardinality;
11import tools.refinery.store.representation.cardinality.UnboundedUpperCardinality;
12import tools.refinery.store.representation.cardinality.UpperCardinalities;
13import tools.refinery.store.representation.cardinality.UpperCardinality;
14
15public class UpperCardinalitySumAggregator implements StatefulAggregator<UpperCardinality, UpperCardinality> {
16 public static final UpperCardinalitySumAggregator INSTANCE = new UpperCardinalitySumAggregator();
17
18 private UpperCardinalitySumAggregator() {
19 }
20
21 @Override
22 public Class<UpperCardinality> getResultType() {
23 return UpperCardinality.class;
24 }
25
26 @Override
27 public Class<UpperCardinality> getInputType() {
28 return UpperCardinality.class;
29 }
30
31 @Override
32 public StatefulAggregate<UpperCardinality, UpperCardinality> createEmptyAggregate() {
33 return new Aggregate();
34 }
35
36 private static class Aggregate implements StatefulAggregate<UpperCardinality, UpperCardinality> {
37 private int sumFiniteUpperBounds;
38 private int countUnbounded;
39
40 public Aggregate() {
41 this(0, 0);
42 }
43
44 private Aggregate(int sumFiniteUpperBounds, int countUnbounded) {
45 this.sumFiniteUpperBounds = sumFiniteUpperBounds;
46 this.countUnbounded = countUnbounded;
47 }
48
49 @Override
50 public void add(UpperCardinality value) {
51 if (value instanceof FiniteUpperCardinality finiteUpperCardinality) {
52 sumFiniteUpperBounds += finiteUpperCardinality.finiteUpperBound();
53 } else if (value instanceof UnboundedUpperCardinality) {
54 countUnbounded += 1;
55 } else {
56 throw new IllegalArgumentException("Unknown UpperCardinality: " + value);
57 }
58 }
59
60 @Override
61 public void remove(UpperCardinality value) {
62 if (value instanceof FiniteUpperCardinality finiteUpperCardinality) {
63 sumFiniteUpperBounds -= finiteUpperCardinality.finiteUpperBound();
64 } else if (value instanceof UnboundedUpperCardinality) {
65 countUnbounded -= 1;
66 } else {
67 throw new IllegalArgumentException("Unknown UpperCardinality: " + value);
68 }
69 }
70
71 @Override
72 public UpperCardinality getResult() {
73 return countUnbounded > 0 ? UpperCardinalities.UNBOUNDED : UpperCardinalities.valueOf(sumFiniteUpperBounds);
74 }
75
76 @Override
77 public boolean isEmpty() {
78 return sumFiniteUpperBounds == 0 && countUnbounded == 0;
79 }
80
81 @Override
82 public StatefulAggregate<UpperCardinality, UpperCardinality> deepCopy() {
83 return new Aggregate(sumFiniteUpperBounds, countUnbounded);
84 }
85 }
86}
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/uppercardinality/UpperCardinalityTerms.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/uppercardinality/UpperCardinalityTerms.java
new file mode 100644
index 00000000..13914f2d
--- /dev/null
+++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/uppercardinality/UpperCardinalityTerms.java
@@ -0,0 +1,73 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.query.term.uppercardinality;
7
8import tools.refinery.store.query.term.Aggregator;
9import tools.refinery.store.query.term.ConstantTerm;
10import tools.refinery.store.query.term.ExtremeValueAggregator;
11import tools.refinery.store.query.term.Term;
12import tools.refinery.store.query.term.comparable.*;
13import tools.refinery.store.representation.cardinality.UpperCardinalities;
14import tools.refinery.store.representation.cardinality.UpperCardinality;
15
16import java.util.Comparator;
17
18public final class UpperCardinalityTerms {
19 public static final Aggregator<UpperCardinality, UpperCardinality> UPPER_CARDINALITY_SUM =
20 UpperCardinalitySumAggregator.INSTANCE;
21 public static final Aggregator<UpperCardinality, UpperCardinality> UPPER_CARDINALITY_MIN =
22 new ExtremeValueAggregator<>(UpperCardinality.class, UpperCardinalities.UNBOUNDED);
23 public static final Aggregator<UpperCardinality, UpperCardinality> UPPER_CARDINALITY_MAX =
24 new ExtremeValueAggregator<>(UpperCardinality.class, UpperCardinalities.ZERO, Comparator.reverseOrder());
25
26 private UpperCardinalityTerms() {
27 throw new IllegalStateException("This is a static utility class and should not be instantiated directly");
28 }
29
30 public static Term<UpperCardinality> constant(UpperCardinality value) {
31 return new ConstantTerm<>(UpperCardinality.class, value);
32 }
33
34 public static Term<UpperCardinality> add(Term<UpperCardinality> left, Term<UpperCardinality> right) {
35 return new UpperCardinalityAddTerm(left, right);
36 }
37
38 public static Term<UpperCardinality> mul(Term<UpperCardinality> left, Term<UpperCardinality> right) {
39 return new UpperCardinalityMulTerm(left, right);
40 }
41
42 public static Term<UpperCardinality> min(Term<UpperCardinality> left, Term<UpperCardinality> right) {
43 return new UpperCardinalityMinTerm(left, right);
44 }
45
46 public static Term<UpperCardinality> max(Term<UpperCardinality> left, Term<UpperCardinality> right) {
47 return new UpperCardinalityMaxTerm(left, right);
48 }
49
50 public static Term<Boolean> eq(Term<UpperCardinality> left, Term<UpperCardinality> right) {
51 return new EqTerm<>(UpperCardinality.class, left, right);
52 }
53
54 public static Term<Boolean> notEq(Term<UpperCardinality> left, Term<UpperCardinality> right) {
55 return new NotEqTerm<>(UpperCardinality.class, left, right);
56 }
57
58 public static Term<Boolean> less(Term<UpperCardinality> left, Term<UpperCardinality> right) {
59 return new LessTerm<>(UpperCardinality.class, left, right);
60 }
61
62 public static Term<Boolean> lessEq(Term<UpperCardinality> left, Term<UpperCardinality> right) {
63 return new LessEqTerm<>(UpperCardinality.class, left, right);
64 }
65
66 public static Term<Boolean> greater(Term<UpperCardinality> left, Term<UpperCardinality> right) {
67 return new GreaterTerm<>(UpperCardinality.class, left, right);
68 }
69
70 public static Term<Boolean> greaterEq(Term<UpperCardinality> left, Term<UpperCardinality> right) {
71 return new GreaterEqTerm<>(UpperCardinality.class, left, right);
72 }
73}
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/valuation/MapBasedValuation.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/valuation/MapBasedValuation.java
new file mode 100644
index 00000000..261ceaa5
--- /dev/null
+++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/valuation/MapBasedValuation.java
@@ -0,0 +1,22 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.query.valuation;
7
8import tools.refinery.store.query.term.AnyDataVariable;
9import tools.refinery.store.query.term.DataVariable;
10
11import java.util.Map;
12
13record MapBasedValuation(Map<AnyDataVariable, Object> values) implements Valuation {
14 @Override
15 public <T> T getValue(DataVariable<T> variable) {
16 if (!values.containsKey(variable)) {
17 throw new IllegalArgumentException("No value for variable %s".formatted(variable));
18 }
19 var value = values.get(variable);
20 return variable.getType().cast(value);
21 }
22}
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/valuation/Valuation.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/valuation/Valuation.java
index 88fee35b..1588e957 100644
--- a/subprojects/store-query/src/main/java/tools/refinery/store/query/valuation/Valuation.java
+++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/valuation/Valuation.java
@@ -10,6 +10,7 @@ import tools.refinery.store.query.substitution.Substitution;
10import tools.refinery.store.query.term.AnyDataVariable; 10import tools.refinery.store.query.term.AnyDataVariable;
11import tools.refinery.store.query.term.DataVariable; 11import tools.refinery.store.query.term.DataVariable;
12 12
13import java.util.Map;
13import java.util.Set; 14import java.util.Set;
14 15
15public interface Valuation { 16public interface Valuation {
@@ -25,4 +26,12 @@ public interface Valuation {
25 default Valuation restrict(Set<? extends AnyDataVariable> allowedVariables) { 26 default Valuation restrict(Set<? extends AnyDataVariable> allowedVariables) {
26 return new RestrictedValuation(this, Set.copyOf(allowedVariables)); 27 return new RestrictedValuation(this, Set.copyOf(allowedVariables));
27 } 28 }
29
30 static ValuationBuilder builder() {
31 return new ValuationBuilder();
32 }
33
34 static Valuation empty() {
35 return new MapBasedValuation(Map.of());
36 }
28} 37}
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/valuation/ValuationBuilder.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/valuation/ValuationBuilder.java
new file mode 100644
index 00000000..7337dbc3
--- /dev/null
+++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/valuation/ValuationBuilder.java
@@ -0,0 +1,40 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.query.valuation;
7
8import tools.refinery.store.query.term.AnyDataVariable;
9import tools.refinery.store.query.term.DataVariable;
10
11import java.util.Collections;
12import java.util.HashMap;
13import java.util.Map;
14
15public class ValuationBuilder {
16 private final Map<AnyDataVariable, Object> values = new HashMap<>();
17
18 ValuationBuilder() {
19 }
20
21 public <T> ValuationBuilder put(DataVariable<T> variable, T value) {
22 return putChecked(variable, value);
23 }
24
25 public ValuationBuilder putChecked(AnyDataVariable variable, Object value) {
26 if (value != null && !variable.getType().isInstance(value)) {
27 throw new IllegalArgumentException("Value %s is not an instance of %s"
28 .formatted(value, variable.getType().getName()));
29 }
30 if (values.containsKey(variable)) {
31 throw new IllegalArgumentException("Already has value for variable %s".formatted(variable));
32 }
33 values.put(variable, value);
34 return this;
35 }
36
37 public Valuation build() {
38 return new MapBasedValuation(Collections.unmodifiableMap(values));
39 }
40}