diff options
Diffstat (limited to 'subprojects/store-query/src/main/java/tools/refinery/store')
166 files changed, 37 insertions, 7114 deletions
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/Constraint.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/Constraint.java deleted file mode 100644 index 916fb35c..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/Constraint.java +++ /dev/null | |||
@@ -1,72 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query; | ||
7 | |||
8 | import tools.refinery.store.query.equality.LiteralEqualityHelper; | ||
9 | import tools.refinery.store.query.literal.*; | ||
10 | import tools.refinery.store.query.term.*; | ||
11 | |||
12 | import java.util.List; | ||
13 | |||
14 | public interface Constraint { | ||
15 | String name(); | ||
16 | |||
17 | List<Parameter> getParameters(); | ||
18 | |||
19 | default int arity() { | ||
20 | return getParameters().size(); | ||
21 | } | ||
22 | |||
23 | default boolean invalidIndex(int i) { | ||
24 | return i < 0 || i >= arity(); | ||
25 | } | ||
26 | |||
27 | default Reduction getReduction() { | ||
28 | return Reduction.NOT_REDUCIBLE; | ||
29 | } | ||
30 | |||
31 | default boolean equals(LiteralEqualityHelper helper, Constraint other) { | ||
32 | return equals(other); | ||
33 | } | ||
34 | |||
35 | default String toReferenceString() { | ||
36 | return name(); | ||
37 | } | ||
38 | |||
39 | default CallLiteral call(CallPolarity polarity, List<Variable> arguments) { | ||
40 | return new CallLiteral(polarity, this, arguments); | ||
41 | } | ||
42 | |||
43 | default CallLiteral call(CallPolarity polarity, Variable... arguments) { | ||
44 | return call(polarity, List.of(arguments)); | ||
45 | } | ||
46 | |||
47 | default CallLiteral call(Variable... arguments) { | ||
48 | return call(CallPolarity.POSITIVE, arguments); | ||
49 | } | ||
50 | |||
51 | default CallLiteral callTransitive(NodeVariable left, NodeVariable right) { | ||
52 | return call(CallPolarity.TRANSITIVE, List.of(left, right)); | ||
53 | } | ||
54 | |||
55 | default AssignedValue<Integer> count(List<Variable> arguments) { | ||
56 | return targetVariable -> new CountLiteral(targetVariable, this, arguments); | ||
57 | } | ||
58 | |||
59 | default AssignedValue<Integer> count(Variable... arguments) { | ||
60 | return count(List.of(arguments)); | ||
61 | } | ||
62 | |||
63 | default <R, T> AssignedValue<R> aggregateBy(DataVariable<T> inputVariable, Aggregator<R, T> aggregator, | ||
64 | List<Variable> arguments) { | ||
65 | return targetVariable -> new AggregationLiteral<>(targetVariable, aggregator, inputVariable, this, arguments); | ||
66 | } | ||
67 | |||
68 | default <R, T> AssignedValue<R> aggregateBy(DataVariable<T> inputVariable, Aggregator<R, T> aggregator, | ||
69 | Variable... arguments) { | ||
70 | return aggregateBy(inputVariable, aggregator, List.of(arguments)); | ||
71 | } | ||
72 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/InvalidQueryException.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/InvalidQueryException.java deleted file mode 100644 index c39277a0..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/InvalidQueryException.java +++ /dev/null | |||
@@ -1,23 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query; | ||
7 | |||
8 | public class InvalidQueryException extends RuntimeException { | ||
9 | public InvalidQueryException() { | ||
10 | } | ||
11 | |||
12 | public InvalidQueryException(String message) { | ||
13 | super(message); | ||
14 | } | ||
15 | |||
16 | public InvalidQueryException(String message, Throwable cause) { | ||
17 | super(message, cause); | ||
18 | } | ||
19 | |||
20 | public InvalidQueryException(Throwable cause) { | ||
21 | super(cause); | ||
22 | } | ||
23 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/ModelQueryAdapter.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/ModelQueryAdapter.java index 1fa96a07..513825b7 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/ModelQueryAdapter.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/ModelQueryAdapter.java | |||
@@ -6,8 +6,8 @@ | |||
6 | package tools.refinery.store.query; | 6 | package tools.refinery.store.query; |
7 | 7 | ||
8 | import tools.refinery.store.adapter.ModelAdapter; | 8 | import tools.refinery.store.adapter.ModelAdapter; |
9 | import tools.refinery.store.query.dnf.AnyQuery; | 9 | import tools.refinery.logic.dnf.AnyQuery; |
10 | import tools.refinery.store.query.dnf.Query; | 10 | import tools.refinery.logic.dnf.Query; |
11 | import tools.refinery.store.query.resultset.AnyResultSet; | 11 | import tools.refinery.store.query.resultset.AnyResultSet; |
12 | import tools.refinery.store.query.resultset.ResultSet; | 12 | import tools.refinery.store.query.resultset.ResultSet; |
13 | 13 | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/ModelQueryBuilder.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/ModelQueryBuilder.java index 332e6381..71e2c5bf 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/ModelQueryBuilder.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/ModelQueryBuilder.java | |||
@@ -7,8 +7,8 @@ package tools.refinery.store.query; | |||
7 | 7 | ||
8 | import tools.refinery.store.adapter.ModelAdapterBuilder; | 8 | import tools.refinery.store.adapter.ModelAdapterBuilder; |
9 | import tools.refinery.store.model.ModelStore; | 9 | import tools.refinery.store.model.ModelStore; |
10 | import tools.refinery.store.query.dnf.AnyQuery; | 10 | import tools.refinery.logic.dnf.AnyQuery; |
11 | import tools.refinery.store.query.rewriter.DnfRewriter; | 11 | import tools.refinery.logic.rewriter.DnfRewriter; |
12 | 12 | ||
13 | import java.util.Collection; | 13 | import java.util.Collection; |
14 | import java.util.List; | 14 | import java.util.List; |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/ModelQueryStoreAdapter.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/ModelQueryStoreAdapter.java index 8b67c5c1..fec8c999 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/ModelQueryStoreAdapter.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/ModelQueryStoreAdapter.java | |||
@@ -7,8 +7,8 @@ package tools.refinery.store.query; | |||
7 | 7 | ||
8 | import tools.refinery.store.adapter.ModelStoreAdapter; | 8 | import tools.refinery.store.adapter.ModelStoreAdapter; |
9 | import tools.refinery.store.model.Model; | 9 | import tools.refinery.store.model.Model; |
10 | import tools.refinery.store.query.dnf.AnyQuery; | 10 | import tools.refinery.logic.dnf.AnyQuery; |
11 | import tools.refinery.store.query.dnf.Query; | 11 | import tools.refinery.logic.dnf.Query; |
12 | import tools.refinery.store.query.view.AnySymbolView; | 12 | import tools.refinery.store.query.view.AnySymbolView; |
13 | 13 | ||
14 | import java.util.Collection; | 14 | import java.util.Collection; |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/AbstractQueryBuilder.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/AbstractQueryBuilder.java deleted file mode 100644 index 2a3e3ce0..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/AbstractQueryBuilder.java +++ /dev/null | |||
@@ -1,175 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.dnf; | ||
7 | |||
8 | import tools.refinery.store.query.dnf.callback.*; | ||
9 | import tools.refinery.store.query.literal.Literal; | ||
10 | import tools.refinery.store.query.term.NodeVariable; | ||
11 | import tools.refinery.store.query.term.ParameterDirection; | ||
12 | import tools.refinery.store.query.term.Variable; | ||
13 | |||
14 | import java.util.Collection; | ||
15 | import java.util.List; | ||
16 | import java.util.Set; | ||
17 | |||
18 | public abstract class AbstractQueryBuilder<T extends AbstractQueryBuilder<T>> { | ||
19 | protected final DnfBuilder dnfBuilder; | ||
20 | |||
21 | protected AbstractQueryBuilder(DnfBuilder dnfBuilder) { | ||
22 | this.dnfBuilder = dnfBuilder; | ||
23 | } | ||
24 | |||
25 | protected abstract T self(); | ||
26 | |||
27 | public NodeVariable parameter() { | ||
28 | return dnfBuilder.parameter(); | ||
29 | } | ||
30 | |||
31 | public NodeVariable parameter(String name) { | ||
32 | return dnfBuilder.parameter(name); | ||
33 | } | ||
34 | |||
35 | public NodeVariable parameter(ParameterDirection direction) { | ||
36 | return dnfBuilder.parameter(direction); | ||
37 | } | ||
38 | |||
39 | public NodeVariable parameter(String name, ParameterDirection direction) { | ||
40 | return dnfBuilder.parameter(name, direction); | ||
41 | } | ||
42 | |||
43 | public T parameter(NodeVariable variable) { | ||
44 | dnfBuilder.parameter(variable); | ||
45 | return self(); | ||
46 | } | ||
47 | |||
48 | public T parameter(NodeVariable variable, ParameterDirection direction) { | ||
49 | dnfBuilder.parameter(variable, direction); | ||
50 | return self(); | ||
51 | } | ||
52 | |||
53 | public T parameters(NodeVariable... variables) { | ||
54 | dnfBuilder.parameters(variables); | ||
55 | return self(); | ||
56 | } | ||
57 | |||
58 | public T parameters(List<NodeVariable> variables) { | ||
59 | dnfBuilder.parameters(variables); | ||
60 | return self(); | ||
61 | } | ||
62 | |||
63 | public T parameters(List<NodeVariable> variables, ParameterDirection direction) { | ||
64 | dnfBuilder.parameters(variables, direction); | ||
65 | return self(); | ||
66 | } | ||
67 | |||
68 | public T symbolicParameters(List<SymbolicParameter> parameters) { | ||
69 | dnfBuilder.symbolicParameters(parameters); | ||
70 | return self(); | ||
71 | } | ||
72 | |||
73 | public T functionalDependencies(Collection<FunctionalDependency<Variable>> functionalDependencies) { | ||
74 | dnfBuilder.functionalDependencies(functionalDependencies); | ||
75 | return self(); | ||
76 | } | ||
77 | |||
78 | public T functionalDependency(FunctionalDependency<Variable> functionalDependency) { | ||
79 | dnfBuilder.functionalDependency(functionalDependency); | ||
80 | return self(); | ||
81 | } | ||
82 | |||
83 | public T functionalDependency(Set<? extends Variable> forEach, Set<? extends Variable> unique) { | ||
84 | dnfBuilder.functionalDependency(forEach, unique); | ||
85 | return self(); | ||
86 | } | ||
87 | |||
88 | public T clause(ClauseCallback0 callback) { | ||
89 | dnfBuilder.clause(callback); | ||
90 | return self(); | ||
91 | } | ||
92 | |||
93 | public T clause(ClauseCallback1Data0 callback) { | ||
94 | dnfBuilder.clause(callback); | ||
95 | return self(); | ||
96 | } | ||
97 | |||
98 | public <U1> T clause(Class<U1> type1, ClauseCallback1Data1<U1> callback) { | ||
99 | dnfBuilder.clause(type1, callback); | ||
100 | return self(); | ||
101 | } | ||
102 | |||
103 | public T clause(ClauseCallback2Data0 callback) { | ||
104 | dnfBuilder.clause(callback); | ||
105 | return self(); | ||
106 | } | ||
107 | |||
108 | public <U1> T clause(Class<U1> type1, ClauseCallback2Data1<U1> callback) { | ||
109 | dnfBuilder.clause(type1, callback); | ||
110 | return self(); | ||
111 | } | ||
112 | |||
113 | public <U1, U2> T clause(Class<U1> type1, Class<U2> type2, ClauseCallback2Data2<U1, U2> callback) { | ||
114 | dnfBuilder.clause(type1, type2, callback); | ||
115 | return self(); | ||
116 | } | ||
117 | |||
118 | public T clause(ClauseCallback3Data0 callback) { | ||
119 | dnfBuilder.clause(callback); | ||
120 | return self(); | ||
121 | } | ||
122 | |||
123 | public <U1> T clause(Class<U1> type1, ClauseCallback3Data1<U1> callback) { | ||
124 | dnfBuilder.clause(type1, callback); | ||
125 | return self(); | ||
126 | } | ||
127 | |||
128 | public <U1, U2> T clause(Class<U1> type1, Class<U2> type2, ClauseCallback3Data2<U1, U2> callback) { | ||
129 | dnfBuilder.clause(type1, type2, callback); | ||
130 | return self(); | ||
131 | } | ||
132 | |||
133 | public <U1, U2, U3> T clause(Class<U1> type1, Class<U2> type2, Class<U3> type3, | ||
134 | ClauseCallback3Data3<U1, U2, U3> callback) { | ||
135 | dnfBuilder.clause(type1, type2, type3, callback); | ||
136 | return self(); | ||
137 | } | ||
138 | |||
139 | public T clause(ClauseCallback4Data0 callback) { | ||
140 | dnfBuilder.clause(callback); | ||
141 | return self(); | ||
142 | } | ||
143 | |||
144 | public <U1> T clause(Class<U1> type1, ClauseCallback4Data1<U1> callback) { | ||
145 | dnfBuilder.clause(type1, callback); | ||
146 | return self(); | ||
147 | } | ||
148 | |||
149 | public <U1, U2> T clause(Class<U1> type1, Class<U2> type2, ClauseCallback4Data2<U1, U2> callback) { | ||
150 | dnfBuilder.clause(type1, type2, callback); | ||
151 | return self(); | ||
152 | } | ||
153 | |||
154 | public <U1, U2, U3> T clause(Class<U1> type1, Class<U2> type2, Class<U3> type3, | ||
155 | ClauseCallback4Data3<U1, U2, U3> callback) { | ||
156 | dnfBuilder.clause(type1, type2, type3, callback); | ||
157 | return self(); | ||
158 | } | ||
159 | |||
160 | public <U1, U2, U3, U4> T clause(Class<U1> type1, Class<U2> type2, Class<U3> type3, Class<U4> type4, | ||
161 | ClauseCallback4Data4<U1, U2, U3, U4> callback) { | ||
162 | dnfBuilder.clause(type1, type2, type3, type4, callback); | ||
163 | return self(); | ||
164 | } | ||
165 | |||
166 | public T clause(Literal... literals) { | ||
167 | dnfBuilder.clause(literals); | ||
168 | return self(); | ||
169 | } | ||
170 | |||
171 | public T clause(Collection<? extends Literal> literals) { | ||
172 | dnfBuilder.clause(literals); | ||
173 | return self(); | ||
174 | } | ||
175 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/AnyQuery.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/AnyQuery.java deleted file mode 100644 index 5e28af68..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/AnyQuery.java +++ /dev/null | |||
@@ -1,16 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.dnf; | ||
7 | |||
8 | public sealed interface AnyQuery permits Query { | ||
9 | String name(); | ||
10 | |||
11 | int arity(); | ||
12 | |||
13 | Class<?> valueType(); | ||
14 | |||
15 | Dnf getDnf(); | ||
16 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/ClausePostProcessor.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/ClausePostProcessor.java deleted file mode 100644 index 8800a155..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/ClausePostProcessor.java +++ /dev/null | |||
@@ -1,362 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.dnf; | ||
7 | |||
8 | import org.jetbrains.annotations.NotNull; | ||
9 | import tools.refinery.store.query.Constraint; | ||
10 | import tools.refinery.store.query.InvalidQueryException; | ||
11 | import tools.refinery.store.query.literal.*; | ||
12 | import tools.refinery.store.query.substitution.MapBasedSubstitution; | ||
13 | import tools.refinery.store.query.substitution.StatelessSubstitution; | ||
14 | import tools.refinery.store.query.substitution.Substitution; | ||
15 | import tools.refinery.store.query.term.ParameterDirection; | ||
16 | import tools.refinery.store.query.term.Variable; | ||
17 | |||
18 | import java.util.*; | ||
19 | import java.util.function.Function; | ||
20 | |||
21 | class ClausePostProcessor { | ||
22 | private final Map<Variable, ParameterInfo> parameters; | ||
23 | private final List<Literal> literals; | ||
24 | private final Map<Variable, Variable> representatives = new LinkedHashMap<>(); | ||
25 | private final Map<Variable, Set<Variable>> equivalencePartition = new HashMap<>(); | ||
26 | private List<Literal> substitutedLiterals; | ||
27 | private final Set<Variable> existentiallyQuantifiedVariables = new LinkedHashSet<>(); | ||
28 | private Set<Variable> positiveVariables; | ||
29 | private Map<Variable, Set<SortableLiteral>> variableToLiteralInputMap; | ||
30 | private PriorityQueue<SortableLiteral> literalsWithAllInputsBound; | ||
31 | private LinkedHashSet<Literal> topologicallySortedLiterals; | ||
32 | |||
33 | public ClausePostProcessor(Map<Variable, ParameterInfo> parameters, List<Literal> literals) { | ||
34 | this.parameters = parameters; | ||
35 | this.literals = literals; | ||
36 | } | ||
37 | |||
38 | public Result postProcessClause() { | ||
39 | mergeEquivalentNodeVariables(); | ||
40 | substitutedLiterals = new ArrayList<>(literals.size()); | ||
41 | keepParameterEquivalences(); | ||
42 | substituteLiterals(); | ||
43 | computeExistentiallyQuantifiedVariables(); | ||
44 | computePositiveVariables(); | ||
45 | validatePositiveRepresentatives(); | ||
46 | validatePrivateVariables(); | ||
47 | topologicallySortLiterals(); | ||
48 | var filteredLiterals = new ArrayList<Literal>(topologicallySortedLiterals.size()); | ||
49 | for (var literal : topologicallySortedLiterals) { | ||
50 | var reducedLiteral = literal.reduce(); | ||
51 | if (BooleanLiteral.FALSE.equals(reducedLiteral)) { | ||
52 | return ConstantResult.ALWAYS_FALSE; | ||
53 | } else if (!BooleanLiteral.TRUE.equals(reducedLiteral)) { | ||
54 | filteredLiterals.add(reducedLiteral); | ||
55 | } | ||
56 | } | ||
57 | if (filteredLiterals.isEmpty()) { | ||
58 | return ConstantResult.ALWAYS_TRUE; | ||
59 | } | ||
60 | if (hasContradictoryCall(filteredLiterals)) { | ||
61 | return ConstantResult.ALWAYS_FALSE; | ||
62 | } | ||
63 | var clause = new DnfClause(Collections.unmodifiableSet(positiveVariables), | ||
64 | Collections.unmodifiableList(filteredLiterals)); | ||
65 | return new ClauseResult(clause); | ||
66 | } | ||
67 | |||
68 | private void mergeEquivalentNodeVariables() { | ||
69 | for (var literal : literals) { | ||
70 | if (isPositiveEquivalence(literal)) { | ||
71 | var equivalenceLiteral = (EquivalenceLiteral) literal; | ||
72 | mergeVariables(equivalenceLiteral.getLeft(), equivalenceLiteral.getRight()); | ||
73 | } | ||
74 | } | ||
75 | } | ||
76 | |||
77 | private static boolean isPositiveEquivalence(Literal literal) { | ||
78 | return literal instanceof EquivalenceLiteral equivalenceLiteral && equivalenceLiteral.isPositive(); | ||
79 | } | ||
80 | |||
81 | private void mergeVariables(Variable left, Variable right) { | ||
82 | var leftRepresentative = getRepresentative(left); | ||
83 | var rightRepresentative = getRepresentative(right); | ||
84 | var leftInfo = parameters.get(leftRepresentative); | ||
85 | var rightInfo = parameters.get(rightRepresentative); | ||
86 | if (leftInfo != null && (rightInfo == null || leftInfo.index() <= rightInfo.index())) { | ||
87 | // Prefer the variable occurring earlier in the parameter list as a representative. | ||
88 | doMergeVariables(leftRepresentative, rightRepresentative); | ||
89 | } else { | ||
90 | doMergeVariables(rightRepresentative, leftRepresentative); | ||
91 | } | ||
92 | } | ||
93 | |||
94 | private void doMergeVariables(Variable parentRepresentative, Variable newChildRepresentative) { | ||
95 | var parentSet = getEquivalentVariables(parentRepresentative); | ||
96 | var childSet = getEquivalentVariables(newChildRepresentative); | ||
97 | parentSet.addAll(childSet); | ||
98 | equivalencePartition.remove(newChildRepresentative); | ||
99 | for (var childEquivalentNodeVariable : childSet) { | ||
100 | representatives.put(childEquivalentNodeVariable, parentRepresentative); | ||
101 | } | ||
102 | } | ||
103 | |||
104 | private Variable getRepresentative(Variable variable) { | ||
105 | return representatives.computeIfAbsent(variable, Function.identity()); | ||
106 | } | ||
107 | |||
108 | private Set<Variable> getEquivalentVariables(Variable variable) { | ||
109 | var representative = getRepresentative(variable); | ||
110 | if (!representative.equals(variable)) { | ||
111 | throw new AssertionError("NodeVariable %s already has a representative %s" | ||
112 | .formatted(variable, representative)); | ||
113 | } | ||
114 | return equivalencePartition.computeIfAbsent(variable, key -> { | ||
115 | var set = new HashSet<Variable>(1); | ||
116 | set.add(key); | ||
117 | return set; | ||
118 | }); | ||
119 | } | ||
120 | |||
121 | private void keepParameterEquivalences() { | ||
122 | for (var pair : representatives.entrySet()) { | ||
123 | var left = pair.getKey(); | ||
124 | var right = pair.getValue(); | ||
125 | if (!left.equals(right) && parameters.containsKey(left) && parameters.containsKey(right)) { | ||
126 | substitutedLiterals.add(new EquivalenceLiteral(true, left, right)); | ||
127 | } | ||
128 | } | ||
129 | } | ||
130 | |||
131 | private void substituteLiterals() { | ||
132 | Substitution substitution; | ||
133 | if (representatives.isEmpty()) { | ||
134 | substitution = null; | ||
135 | } else { | ||
136 | substitution = new MapBasedSubstitution(Collections.unmodifiableMap(representatives), | ||
137 | StatelessSubstitution.IDENTITY); | ||
138 | } | ||
139 | for (var literal : literals) { | ||
140 | if (isPositiveEquivalence(literal)) { | ||
141 | // We already retained all equivalences that cannot be replaced with substitutions in | ||
142 | // {@link#keepParameterEquivalences()}. | ||
143 | continue; | ||
144 | } | ||
145 | var substitutedLiteral = substitution == null ? literal : literal.substitute(substitution); | ||
146 | substitutedLiterals.add(substitutedLiteral); | ||
147 | } | ||
148 | } | ||
149 | |||
150 | private void computeExistentiallyQuantifiedVariables() { | ||
151 | for (var literal : substitutedLiterals) { | ||
152 | existentiallyQuantifiedVariables.addAll(literal.getOutputVariables()); | ||
153 | } | ||
154 | } | ||
155 | |||
156 | private void computePositiveVariables() { | ||
157 | positiveVariables = new LinkedHashSet<>(); | ||
158 | for (var pair : parameters.entrySet()) { | ||
159 | var variable = pair.getKey(); | ||
160 | if (pair.getValue().direction() == ParameterDirection.IN) { | ||
161 | // Inputs count as positive, because they are already bound when we evaluate literals. | ||
162 | positiveVariables.add(variable); | ||
163 | } else if (!existentiallyQuantifiedVariables.contains(variable)) { | ||
164 | throw new InvalidQueryException("Unbound %s parameter %s" | ||
165 | .formatted(ParameterDirection.OUT, variable)); | ||
166 | } | ||
167 | } | ||
168 | positiveVariables.addAll(existentiallyQuantifiedVariables); | ||
169 | } | ||
170 | |||
171 | private void validatePositiveRepresentatives() { | ||
172 | for (var pair : equivalencePartition.entrySet()) { | ||
173 | var representative = pair.getKey(); | ||
174 | if (!positiveVariables.contains(representative)) { | ||
175 | var variableSet = pair.getValue(); | ||
176 | throw new InvalidQueryException("Variables %s were merged by equivalence but are not bound" | ||
177 | .formatted(variableSet)); | ||
178 | } | ||
179 | } | ||
180 | } | ||
181 | |||
182 | private void validatePrivateVariables() { | ||
183 | var negativeVariablesMap = new HashMap<Variable, Literal>(); | ||
184 | for (var literal : substitutedLiterals) { | ||
185 | for (var variable : literal.getPrivateVariables(positiveVariables)) { | ||
186 | var oldLiteral = negativeVariablesMap.put(variable, literal); | ||
187 | if (oldLiteral != null) { | ||
188 | throw new InvalidQueryException("Unbound variable %s appears in multiple literals %s and %s" | ||
189 | .formatted(variable, oldLiteral, literal)); | ||
190 | } | ||
191 | } | ||
192 | } | ||
193 | } | ||
194 | |||
195 | private void topologicallySortLiterals() { | ||
196 | topologicallySortedLiterals = new LinkedHashSet<>(substitutedLiterals.size()); | ||
197 | variableToLiteralInputMap = new HashMap<>(); | ||
198 | literalsWithAllInputsBound = new PriorityQueue<>(); | ||
199 | int size = substitutedLiterals.size(); | ||
200 | for (int i = 0; i < size; i++) { | ||
201 | var literal = substitutedLiterals.get(i); | ||
202 | var sortableLiteral = new SortableLiteral(i, literal); | ||
203 | sortableLiteral.enqueue(); | ||
204 | } | ||
205 | while (!literalsWithAllInputsBound.isEmpty()) { | ||
206 | var variable = literalsWithAllInputsBound.remove(); | ||
207 | variable.addToSortedLiterals(); | ||
208 | } | ||
209 | if (!variableToLiteralInputMap.isEmpty()) { | ||
210 | throw new InvalidQueryException("Unbound input variables %s" | ||
211 | .formatted(variableToLiteralInputMap.keySet())); | ||
212 | } | ||
213 | } | ||
214 | |||
215 | private boolean hasContradictoryCall(Collection<Literal> filteredLiterals) { | ||
216 | var positiveCalls = new HashMap<Constraint, Set<CallLiteral>>(); | ||
217 | for (var literal : filteredLiterals) { | ||
218 | if (literal instanceof CallLiteral callLiteral && callLiteral.getPolarity() == CallPolarity.POSITIVE) { | ||
219 | var callsOfTarget = positiveCalls.computeIfAbsent(callLiteral.getTarget(), key -> new HashSet<>()); | ||
220 | callsOfTarget.add(callLiteral); | ||
221 | } | ||
222 | } | ||
223 | for (var literal : filteredLiterals) { | ||
224 | if (literal instanceof CallLiteral callLiteral && callLiteral.getPolarity() == CallPolarity.NEGATIVE) { | ||
225 | var callsOfTarget = positiveCalls.get(callLiteral.getTarget()); | ||
226 | if (contradicts(callLiteral, callsOfTarget)) { | ||
227 | return true; | ||
228 | } | ||
229 | } | ||
230 | } | ||
231 | return false; | ||
232 | } | ||
233 | |||
234 | private boolean contradicts(CallLiteral negativeCall, Collection<CallLiteral> positiveCalls) { | ||
235 | if (positiveCalls == null) { | ||
236 | return false; | ||
237 | } | ||
238 | for (var positiveCall : positiveCalls) { | ||
239 | if (contradicts(negativeCall, positiveCall)) { | ||
240 | return true; | ||
241 | } | ||
242 | } | ||
243 | return false; | ||
244 | } | ||
245 | |||
246 | private boolean contradicts(CallLiteral negativeCall, CallLiteral positiveCall) { | ||
247 | var privateVariables = negativeCall.getPrivateVariables(positiveVariables); | ||
248 | var negativeArguments = negativeCall.getArguments(); | ||
249 | var positiveArguments = positiveCall.getArguments(); | ||
250 | int arity = negativeArguments.size(); | ||
251 | for (int i = 0; i < arity; i++) { | ||
252 | var negativeArgument = negativeArguments.get(i); | ||
253 | if (privateVariables.contains(negativeArgument)) { | ||
254 | continue; | ||
255 | } | ||
256 | var positiveArgument = positiveArguments.get(i); | ||
257 | if (!negativeArgument.equals(positiveArgument)) { | ||
258 | return false; | ||
259 | } | ||
260 | } | ||
261 | return true; | ||
262 | } | ||
263 | |||
264 | private class SortableLiteral implements Comparable<SortableLiteral> { | ||
265 | private final int index; | ||
266 | private final Literal literal; | ||
267 | private final Set<Variable> remainingInputs; | ||
268 | |||
269 | private SortableLiteral(int index, Literal literal) { | ||
270 | this.index = index; | ||
271 | this.literal = literal; | ||
272 | remainingInputs = new HashSet<>(literal.getInputVariables(positiveVariables)); | ||
273 | for (var pair : parameters.entrySet()) { | ||
274 | if (pair.getValue().direction() == ParameterDirection.IN) { | ||
275 | remainingInputs.remove(pair.getKey()); | ||
276 | } | ||
277 | } | ||
278 | } | ||
279 | |||
280 | public void enqueue() { | ||
281 | if (allInputsBound()) { | ||
282 | addToAllInputsBoundQueue(); | ||
283 | } else { | ||
284 | addToVariableToLiteralInputMap(); | ||
285 | } | ||
286 | } | ||
287 | |||
288 | private void bindVariable(Variable input) { | ||
289 | if (!remainingInputs.remove(input)) { | ||
290 | throw new AssertionError("Already processed input %s of literal %s".formatted(input, literal)); | ||
291 | } | ||
292 | if (allInputsBound()) { | ||
293 | addToAllInputsBoundQueue(); | ||
294 | } | ||
295 | } | ||
296 | |||
297 | private boolean allInputsBound() { | ||
298 | return remainingInputs.isEmpty(); | ||
299 | } | ||
300 | |||
301 | private void addToVariableToLiteralInputMap() { | ||
302 | for (var inputVariable : remainingInputs) { | ||
303 | var literalSetForInput = variableToLiteralInputMap.computeIfAbsent( | ||
304 | inputVariable, key -> new HashSet<>()); | ||
305 | literalSetForInput.add(this); | ||
306 | } | ||
307 | } | ||
308 | |||
309 | private void addToAllInputsBoundQueue() { | ||
310 | literalsWithAllInputsBound.add(this); | ||
311 | } | ||
312 | |||
313 | public void addToSortedLiterals() { | ||
314 | if (!allInputsBound()) { | ||
315 | throw new AssertionError("Inputs %s of %s are not yet bound".formatted(remainingInputs, literal)); | ||
316 | } | ||
317 | // Add literal if we haven't yet added a duplicate of this literal. | ||
318 | topologicallySortedLiterals.add(literal); | ||
319 | for (var variable : literal.getOutputVariables()) { | ||
320 | var literalSetForInput = variableToLiteralInputMap.remove(variable); | ||
321 | if (literalSetForInput == null) { | ||
322 | continue; | ||
323 | } | ||
324 | for (var targetSortableLiteral : literalSetForInput) { | ||
325 | targetSortableLiteral.bindVariable(variable); | ||
326 | } | ||
327 | } | ||
328 | } | ||
329 | |||
330 | @Override | ||
331 | public int compareTo(@NotNull ClausePostProcessor.SortableLiteral other) { | ||
332 | return Integer.compare(index, other.index); | ||
333 | } | ||
334 | |||
335 | @Override | ||
336 | public boolean equals(Object o) { | ||
337 | if (this == o) return true; | ||
338 | if (o == null || getClass() != o.getClass()) return false; | ||
339 | SortableLiteral that = (SortableLiteral) o; | ||
340 | return index == that.index && Objects.equals(literal, that.literal); | ||
341 | } | ||
342 | |||
343 | @Override | ||
344 | public int hashCode() { | ||
345 | return Objects.hash(index, literal); | ||
346 | } | ||
347 | } | ||
348 | |||
349 | public sealed interface Result permits ClauseResult, ConstantResult { | ||
350 | } | ||
351 | |||
352 | public record ClauseResult(DnfClause clause) implements Result { | ||
353 | } | ||
354 | |||
355 | public enum ConstantResult implements Result { | ||
356 | ALWAYS_TRUE, | ||
357 | ALWAYS_FALSE | ||
358 | } | ||
359 | |||
360 | public record ParameterInfo(ParameterDirection direction, int index) { | ||
361 | } | ||
362 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/Dnf.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/Dnf.java deleted file mode 100644 index 86a1b6b2..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/Dnf.java +++ /dev/null | |||
@@ -1,235 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.dnf; | ||
7 | |||
8 | import tools.refinery.store.query.Constraint; | ||
9 | import tools.refinery.store.query.InvalidQueryException; | ||
10 | import tools.refinery.store.query.equality.DnfEqualityChecker; | ||
11 | import tools.refinery.store.query.equality.LiteralEqualityHelper; | ||
12 | import tools.refinery.store.query.equality.SubstitutingLiteralEqualityHelper; | ||
13 | import tools.refinery.store.query.equality.SubstitutingLiteralHashCodeHelper; | ||
14 | import tools.refinery.store.query.literal.Reduction; | ||
15 | import tools.refinery.store.query.term.Parameter; | ||
16 | import tools.refinery.store.query.term.Variable; | ||
17 | |||
18 | import java.util.Collection; | ||
19 | import java.util.Collections; | ||
20 | import java.util.List; | ||
21 | import java.util.Set; | ||
22 | import java.util.function.Consumer; | ||
23 | import java.util.stream.Collectors; | ||
24 | |||
25 | public final class Dnf implements Constraint { | ||
26 | private static final String INDENTATION = " "; | ||
27 | |||
28 | private final String name; | ||
29 | private final String uniqueName; | ||
30 | private final List<SymbolicParameter> symbolicParameters; | ||
31 | private final List<FunctionalDependency<Variable>> functionalDependencies; | ||
32 | private final List<DnfClause> clauses; | ||
33 | |||
34 | Dnf(String name, List<SymbolicParameter> symbolicParameters, | ||
35 | List<FunctionalDependency<Variable>> functionalDependencies, List<DnfClause> clauses) { | ||
36 | validateFunctionalDependencies(symbolicParameters, functionalDependencies); | ||
37 | this.name = name; | ||
38 | this.uniqueName = DnfUtils.generateUniqueName(name); | ||
39 | this.symbolicParameters = symbolicParameters; | ||
40 | this.functionalDependencies = functionalDependencies; | ||
41 | this.clauses = clauses; | ||
42 | } | ||
43 | |||
44 | private static void validateFunctionalDependencies( | ||
45 | Collection<SymbolicParameter> symbolicParameters, | ||
46 | Collection<FunctionalDependency<Variable>> functionalDependencies) { | ||
47 | var parameterSet = symbolicParameters.stream().map(SymbolicParameter::getVariable).collect(Collectors.toSet()); | ||
48 | for (var functionalDependency : functionalDependencies) { | ||
49 | validateParameters(symbolicParameters, parameterSet, functionalDependency.forEach(), functionalDependency); | ||
50 | validateParameters(symbolicParameters, parameterSet, functionalDependency.unique(), functionalDependency); | ||
51 | } | ||
52 | } | ||
53 | |||
54 | private static void validateParameters(Collection<SymbolicParameter> symbolicParameters, | ||
55 | Set<Variable> parameterSet, Collection<Variable> toValidate, | ||
56 | FunctionalDependency<Variable> functionalDependency) { | ||
57 | for (var variable : toValidate) { | ||
58 | if (!parameterSet.contains(variable)) { | ||
59 | throw new InvalidQueryException( | ||
60 | "Variable %s of functional dependency %s does not appear in the parameter list %s" | ||
61 | .formatted(variable, functionalDependency, symbolicParameters)); | ||
62 | } | ||
63 | } | ||
64 | } | ||
65 | |||
66 | @Override | ||
67 | public String name() { | ||
68 | return name == null ? uniqueName : name; | ||
69 | } | ||
70 | |||
71 | public boolean isExplicitlyNamed() { | ||
72 | return name != null; | ||
73 | } | ||
74 | |||
75 | public String getUniqueName() { | ||
76 | return uniqueName; | ||
77 | } | ||
78 | |||
79 | public List<SymbolicParameter> getSymbolicParameters() { | ||
80 | return symbolicParameters; | ||
81 | } | ||
82 | |||
83 | public List<Parameter> getParameters() { | ||
84 | return Collections.unmodifiableList(symbolicParameters); | ||
85 | } | ||
86 | |||
87 | public List<FunctionalDependency<Variable>> getFunctionalDependencies() { | ||
88 | return functionalDependencies; | ||
89 | } | ||
90 | |||
91 | @Override | ||
92 | public int arity() { | ||
93 | return symbolicParameters.size(); | ||
94 | } | ||
95 | |||
96 | public List<DnfClause> getClauses() { | ||
97 | return clauses; | ||
98 | } | ||
99 | |||
100 | public RelationalQuery asRelation() { | ||
101 | return new RelationalQuery(this); | ||
102 | } | ||
103 | |||
104 | public <T> FunctionalQuery<T> asFunction(Class<T> type) { | ||
105 | return new FunctionalQuery<>(this, type); | ||
106 | } | ||
107 | |||
108 | @Override | ||
109 | public Reduction getReduction() { | ||
110 | if (clauses.isEmpty()) { | ||
111 | return Reduction.ALWAYS_FALSE; | ||
112 | } | ||
113 | for (var clause : clauses) { | ||
114 | if (clause.literals().isEmpty()) { | ||
115 | return Reduction.ALWAYS_TRUE; | ||
116 | } | ||
117 | } | ||
118 | return Reduction.NOT_REDUCIBLE; | ||
119 | } | ||
120 | |||
121 | public boolean equalsWithSubstitution(DnfEqualityChecker callEqualityChecker, Dnf other) { | ||
122 | if (arity() != other.arity()) { | ||
123 | return false; | ||
124 | } | ||
125 | for (int i = 0; i < arity(); i++) { | ||
126 | if (!symbolicParameters.get(i).getDirection().equals(other.getSymbolicParameters().get(i).getDirection())) { | ||
127 | return false; | ||
128 | } | ||
129 | } | ||
130 | int numClauses = clauses.size(); | ||
131 | if (numClauses != other.clauses.size()) { | ||
132 | return false; | ||
133 | } | ||
134 | for (int i = 0; i < numClauses; i++) { | ||
135 | var literalEqualityHelper = new SubstitutingLiteralEqualityHelper(callEqualityChecker, symbolicParameters, | ||
136 | other.symbolicParameters); | ||
137 | if (!clauses.get(i).equalsWithSubstitution(literalEqualityHelper, other.clauses.get(i))) { | ||
138 | return false; | ||
139 | } | ||
140 | } | ||
141 | return true; | ||
142 | } | ||
143 | |||
144 | @Override | ||
145 | public boolean equals(LiteralEqualityHelper helper, Constraint other) { | ||
146 | if (other instanceof Dnf otherDnf) { | ||
147 | return helper.dnfEqual(this, otherDnf); | ||
148 | } | ||
149 | return false; | ||
150 | } | ||
151 | |||
152 | public int hashCodeWithSubstitution() { | ||
153 | var helper = new SubstitutingLiteralHashCodeHelper(); | ||
154 | int result = 0; | ||
155 | for (var symbolicParameter : symbolicParameters) { | ||
156 | result = result * 31 + symbolicParameter.hashCodeWithSubstitution(helper); | ||
157 | } | ||
158 | for (var clause : clauses) { | ||
159 | result = result * 31 + clause.hashCodeWithSubstitution(helper); | ||
160 | } | ||
161 | return result; | ||
162 | } | ||
163 | |||
164 | @Override | ||
165 | public String toString() { | ||
166 | return "%s/%d".formatted(name(), arity()); | ||
167 | } | ||
168 | |||
169 | @Override | ||
170 | public String toReferenceString() { | ||
171 | return "@Dnf " + name(); | ||
172 | } | ||
173 | |||
174 | public String toDefinitionString() { | ||
175 | var builder = new StringBuilder(); | ||
176 | builder.append("pred ").append(name()).append("("); | ||
177 | var parameterIterator = symbolicParameters.iterator(); | ||
178 | if (parameterIterator.hasNext()) { | ||
179 | builder.append(parameterIterator.next()); | ||
180 | while (parameterIterator.hasNext()) { | ||
181 | builder.append(", ").append(parameterIterator.next()); | ||
182 | } | ||
183 | } | ||
184 | builder.append(") <->"); | ||
185 | var clauseIterator = clauses.iterator(); | ||
186 | if (clauseIterator.hasNext()) { | ||
187 | appendClause(clauseIterator.next(), builder); | ||
188 | while (clauseIterator.hasNext()) { | ||
189 | builder.append("\n;"); | ||
190 | appendClause(clauseIterator.next(), builder); | ||
191 | } | ||
192 | } else { | ||
193 | builder.append("\n").append(INDENTATION).append("<no clauses>"); | ||
194 | } | ||
195 | builder.append(".\n"); | ||
196 | return builder.toString(); | ||
197 | } | ||
198 | |||
199 | private static void appendClause(DnfClause clause, StringBuilder builder) { | ||
200 | var iterator = clause.literals().iterator(); | ||
201 | if (!iterator.hasNext()) { | ||
202 | builder.append("\n").append(INDENTATION).append("<empty>"); | ||
203 | return; | ||
204 | } | ||
205 | builder.append("\n").append(INDENTATION).append(iterator.next()); | ||
206 | while (iterator.hasNext()) { | ||
207 | builder.append(",\n").append(INDENTATION).append(iterator.next()); | ||
208 | } | ||
209 | } | ||
210 | |||
211 | public static DnfBuilder builder() { | ||
212 | return builder(null); | ||
213 | } | ||
214 | |||
215 | public static DnfBuilder builder(String name) { | ||
216 | return new DnfBuilder(name); | ||
217 | } | ||
218 | |||
219 | public static DnfBuilder builderFrom(Dnf original) { | ||
220 | var builder = builder(original.name()); | ||
221 | builder.symbolicParameters(original.getSymbolicParameters()); | ||
222 | builder.functionalDependencies(original.getFunctionalDependencies()); | ||
223 | return builder; | ||
224 | } | ||
225 | |||
226 | public static Dnf of(Consumer<DnfBuilder> callback) { | ||
227 | return of(null, callback); | ||
228 | } | ||
229 | |||
230 | public static Dnf of(String name, Consumer<DnfBuilder> callback) { | ||
231 | var builder = builder(name); | ||
232 | callback.accept(builder); | ||
233 | return builder.build(); | ||
234 | } | ||
235 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/DnfBuilder.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/DnfBuilder.java deleted file mode 100644 index 0f9fd366..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/DnfBuilder.java +++ /dev/null | |||
@@ -1,225 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.dnf; | ||
7 | |||
8 | import tools.refinery.store.query.InvalidQueryException; | ||
9 | import tools.refinery.store.query.dnf.callback.*; | ||
10 | import tools.refinery.store.query.literal.Literal; | ||
11 | import tools.refinery.store.query.term.*; | ||
12 | |||
13 | import java.util.*; | ||
14 | |||
15 | @SuppressWarnings("UnusedReturnValue") | ||
16 | public final class DnfBuilder { | ||
17 | private final String name; | ||
18 | private final Set<Variable> parameterVariables = new LinkedHashSet<>(); | ||
19 | private final List<SymbolicParameter> parameters = new ArrayList<>(); | ||
20 | private final List<FunctionalDependency<Variable>> functionalDependencies = new ArrayList<>(); | ||
21 | private final List<List<Literal>> clauses = new ArrayList<>(); | ||
22 | |||
23 | DnfBuilder(String name) { | ||
24 | this.name = name; | ||
25 | } | ||
26 | |||
27 | public NodeVariable parameter() { | ||
28 | return parameter((String) null); | ||
29 | } | ||
30 | |||
31 | public NodeVariable parameter(String name) { | ||
32 | return parameter(name, ParameterDirection.OUT); | ||
33 | } | ||
34 | |||
35 | public NodeVariable parameter(ParameterDirection direction) { | ||
36 | return parameter((String) null, direction); | ||
37 | } | ||
38 | |||
39 | public NodeVariable parameter(String name, ParameterDirection direction) { | ||
40 | var variable = Variable.of(name); | ||
41 | parameter(variable, direction); | ||
42 | return variable; | ||
43 | } | ||
44 | |||
45 | public <T> DataVariable<T> parameter(Class<T> type) { | ||
46 | return parameter(null, type); | ||
47 | } | ||
48 | |||
49 | public <T> DataVariable<T> parameter(String name, Class<T> type) { | ||
50 | return parameter(name, type, ParameterDirection.OUT); | ||
51 | } | ||
52 | |||
53 | public <T> DataVariable<T> parameter(Class<T> type, ParameterDirection direction) { | ||
54 | return parameter(null, type, direction); | ||
55 | } | ||
56 | |||
57 | public <T> DataVariable<T> parameter(String name, Class<T> type, ParameterDirection direction) { | ||
58 | var variable = Variable.of(name, type); | ||
59 | parameter(variable, direction); | ||
60 | return variable; | ||
61 | } | ||
62 | |||
63 | public Variable parameter(Parameter parameter) { | ||
64 | return parameter(null, parameter); | ||
65 | } | ||
66 | |||
67 | public Variable parameter(String name, Parameter parameter) { | ||
68 | var type = parameter.tryGetType(); | ||
69 | if (type.isPresent()) { | ||
70 | return parameter(name, type.get(), parameter.getDirection()); | ||
71 | } | ||
72 | return parameter(name, parameter.getDirection()); | ||
73 | } | ||
74 | |||
75 | public DnfBuilder parameter(Variable variable) { | ||
76 | return parameter(variable, ParameterDirection.OUT); | ||
77 | } | ||
78 | |||
79 | public DnfBuilder parameter(Variable variable, ParameterDirection direction) { | ||
80 | return symbolicParameter(new SymbolicParameter(variable, direction)); | ||
81 | } | ||
82 | |||
83 | public DnfBuilder parameters(Variable... variables) { | ||
84 | return parameters(List.of(variables)); | ||
85 | } | ||
86 | |||
87 | public DnfBuilder parameters(Collection<? extends Variable> variables) { | ||
88 | return parameters(variables, ParameterDirection.OUT); | ||
89 | } | ||
90 | |||
91 | public DnfBuilder parameters(Collection<? extends Variable> variables, ParameterDirection direction) { | ||
92 | for (var variable : variables) { | ||
93 | parameter(variable, direction); | ||
94 | } | ||
95 | return this; | ||
96 | } | ||
97 | |||
98 | public DnfBuilder symbolicParameter(SymbolicParameter symbolicParameter) { | ||
99 | var variable = symbolicParameter.getVariable(); | ||
100 | if (!parameterVariables.add(variable)) { | ||
101 | throw new InvalidQueryException("Variable %s is already on the parameter list %s" | ||
102 | .formatted(variable, parameters)); | ||
103 | } | ||
104 | parameters.add(symbolicParameter); | ||
105 | return this; | ||
106 | } | ||
107 | |||
108 | public DnfBuilder symbolicParameters(SymbolicParameter... symbolicParameters) { | ||
109 | return symbolicParameters(List.of(symbolicParameters)); | ||
110 | } | ||
111 | |||
112 | public DnfBuilder symbolicParameters(Collection<SymbolicParameter> symbolicParameters) { | ||
113 | for (var symbolicParameter : symbolicParameters) { | ||
114 | symbolicParameter(symbolicParameter); | ||
115 | } | ||
116 | return this; | ||
117 | } | ||
118 | |||
119 | public DnfBuilder functionalDependencies(Collection<FunctionalDependency<Variable>> functionalDependencies) { | ||
120 | this.functionalDependencies.addAll(functionalDependencies); | ||
121 | return this; | ||
122 | } | ||
123 | |||
124 | public DnfBuilder functionalDependency(FunctionalDependency<Variable> functionalDependency) { | ||
125 | functionalDependencies.add(functionalDependency); | ||
126 | return this; | ||
127 | } | ||
128 | |||
129 | public DnfBuilder functionalDependency(Set<? extends Variable> forEach, Set<? extends Variable> unique) { | ||
130 | return functionalDependency(new FunctionalDependency<>(Set.copyOf(forEach), Set.copyOf(unique))); | ||
131 | } | ||
132 | |||
133 | public DnfBuilder clause(ClauseCallback0 callback) { | ||
134 | return clause(callback.toLiterals()); | ||
135 | } | ||
136 | |||
137 | public DnfBuilder clause(ClauseCallback1Data0 callback) { | ||
138 | return clause(callback.toLiterals(Variable.of("v1"))); | ||
139 | } | ||
140 | |||
141 | public <T> DnfBuilder clause(Class<T> type1, ClauseCallback1Data1<T> callback) { | ||
142 | return clause(callback.toLiterals(Variable.of("d1", type1))); | ||
143 | } | ||
144 | |||
145 | public DnfBuilder clause(ClauseCallback2Data0 callback) { | ||
146 | return clause(callback.toLiterals(Variable.of("v1"), Variable.of("v2"))); | ||
147 | } | ||
148 | |||
149 | public <T> DnfBuilder clause(Class<T> type1, ClauseCallback2Data1<T> callback) { | ||
150 | return clause(callback.toLiterals(Variable.of("v1"), Variable.of("d1", type1))); | ||
151 | } | ||
152 | |||
153 | public <T1, T2> DnfBuilder clause(Class<T1> type1, Class<T2> type2, ClauseCallback2Data2<T1, T2> callback) { | ||
154 | return clause(callback.toLiterals(Variable.of("d1", type1), Variable.of("d2", type2))); | ||
155 | } | ||
156 | |||
157 | public DnfBuilder clause(ClauseCallback3Data0 callback) { | ||
158 | return clause(callback.toLiterals(Variable.of("v1"), Variable.of("v2"), Variable.of("v3"))); | ||
159 | } | ||
160 | |||
161 | public <T> DnfBuilder clause(Class<T> type1, ClauseCallback3Data1<T> callback) { | ||
162 | return clause(callback.toLiterals(Variable.of("v1"), Variable.of("v2"), Variable.of("d1", type1))); | ||
163 | } | ||
164 | |||
165 | public <T1, T2> DnfBuilder clause(Class<T1> type1, Class<T2> type2, ClauseCallback3Data2<T1, T2> callback) { | ||
166 | return clause(callback.toLiterals(Variable.of("v1"), Variable.of("d1", type1), Variable.of("d2", type2))); | ||
167 | } | ||
168 | |||
169 | public <T1, T2, T3> DnfBuilder clause(Class<T1> type1, Class<T2> type2, Class<T3> type3, | ||
170 | ClauseCallback3Data3<T1, T2, T3> callback) { | ||
171 | return clause(callback.toLiterals(Variable.of("d1", type1), Variable.of("d2", type2), | ||
172 | Variable.of("d3", type3))); | ||
173 | } | ||
174 | |||
175 | public DnfBuilder clause(ClauseCallback4Data0 callback) { | ||
176 | return clause(callback.toLiterals(Variable.of("v1"), Variable.of("v2"), Variable.of("v3"), Variable.of("v4"))); | ||
177 | } | ||
178 | |||
179 | public <T> DnfBuilder clause(Class<T> type1, ClauseCallback4Data1<T> callback) { | ||
180 | return clause(callback.toLiterals(Variable.of("v1"), Variable.of("v2"), Variable.of("v3"), Variable.of("d1", | ||
181 | type1))); | ||
182 | } | ||
183 | |||
184 | public <T1, T2> DnfBuilder clause(Class<T1> type1, Class<T2> type2, ClauseCallback4Data2<T1, T2> callback) { | ||
185 | return clause(callback.toLiterals(Variable.of("v1"), Variable.of("v2"), Variable.of("d1", type1), | ||
186 | Variable.of("d2", type2))); | ||
187 | } | ||
188 | |||
189 | public <T1, T2, T3> DnfBuilder clause(Class<T1> type1, Class<T2> type2, Class<T3> type3, | ||
190 | ClauseCallback4Data3<T1, T2, T3> callback) { | ||
191 | return clause(callback.toLiterals(Variable.of("v1"), Variable.of("d1", type1), Variable.of("d2", type2), | ||
192 | Variable.of("d3", type3))); | ||
193 | } | ||
194 | |||
195 | public <T1, T2, T3, T4> DnfBuilder clause(Class<T1> type1, Class<T2> type2, Class<T3> type3, Class<T4> type4, | ||
196 | ClauseCallback4Data4<T1, T2, T3, T4> callback) { | ||
197 | return clause(callback.toLiterals(Variable.of("d1", type1), Variable.of("d2", type2), | ||
198 | Variable.of("d3", type3), Variable.of("d4", type4))); | ||
199 | } | ||
200 | |||
201 | public DnfBuilder clause(Literal... literals) { | ||
202 | clause(List.of(literals)); | ||
203 | return this; | ||
204 | } | ||
205 | |||
206 | public DnfBuilder clause(Collection<? extends Literal> literals) { | ||
207 | clauses.add(List.copyOf(literals)); | ||
208 | return this; | ||
209 | } | ||
210 | |||
211 | <T> void output(DataVariable<T> outputVariable) { | ||
212 | // Copy parameter variables to exclude the newly added {@code outputVariable}. | ||
213 | var fromParameters = Set.copyOf(parameterVariables); | ||
214 | parameter(outputVariable, ParameterDirection.OUT); | ||
215 | functionalDependency(fromParameters, Set.of(outputVariable)); | ||
216 | } | ||
217 | |||
218 | public Dnf build() { | ||
219 | var postProcessor = new DnfPostProcessor(parameters, clauses); | ||
220 | var postProcessedClauses = postProcessor.postProcessClauses(); | ||
221 | return new Dnf(name, Collections.unmodifiableList(parameters), | ||
222 | Collections.unmodifiableList(functionalDependencies), | ||
223 | Collections.unmodifiableList(postProcessedClauses)); | ||
224 | } | ||
225 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/DnfClause.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/DnfClause.java deleted file mode 100644 index 94327bad..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/DnfClause.java +++ /dev/null | |||
@@ -1,37 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.dnf; | ||
7 | |||
8 | import tools.refinery.store.query.equality.LiteralEqualityHelper; | ||
9 | import tools.refinery.store.query.equality.LiteralHashCodeHelper; | ||
10 | import tools.refinery.store.query.literal.Literal; | ||
11 | import tools.refinery.store.query.term.Variable; | ||
12 | |||
13 | import java.util.List; | ||
14 | import java.util.Set; | ||
15 | |||
16 | public record DnfClause(Set<Variable> positiveVariables, List<Literal> literals) { | ||
17 | public boolean equalsWithSubstitution(LiteralEqualityHelper helper, DnfClause other) { | ||
18 | int size = literals.size(); | ||
19 | if (size != other.literals.size()) { | ||
20 | return false; | ||
21 | } | ||
22 | for (int i = 0; i < size; i++) { | ||
23 | if (!literals.get(i).equalsWithSubstitution(helper, other.literals.get(i))) { | ||
24 | return false; | ||
25 | } | ||
26 | } | ||
27 | return true; | ||
28 | } | ||
29 | |||
30 | public int hashCodeWithSubstitution(LiteralHashCodeHelper helper) { | ||
31 | int result = 0; | ||
32 | for (var literal : literals) { | ||
33 | result = result * 31 + literal.hashCodeWithSubstitution(helper); | ||
34 | } | ||
35 | return result; | ||
36 | } | ||
37 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/DnfPostProcessor.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/DnfPostProcessor.java deleted file mode 100644 index 50236642..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/DnfPostProcessor.java +++ /dev/null | |||
@@ -1,112 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.dnf; | ||
7 | |||
8 | import tools.refinery.store.query.InvalidQueryException; | ||
9 | import tools.refinery.store.query.equality.DnfEqualityChecker; | ||
10 | import tools.refinery.store.query.equality.SubstitutingLiteralEqualityHelper; | ||
11 | import tools.refinery.store.query.equality.SubstitutingLiteralHashCodeHelper; | ||
12 | import tools.refinery.store.query.literal.Literal; | ||
13 | import tools.refinery.store.query.term.ParameterDirection; | ||
14 | import tools.refinery.store.query.term.Variable; | ||
15 | |||
16 | import java.util.*; | ||
17 | |||
18 | class DnfPostProcessor { | ||
19 | private final List<SymbolicParameter> parameters; | ||
20 | private final List<List<Literal>> clauses; | ||
21 | |||
22 | public DnfPostProcessor(List<SymbolicParameter> parameters, List<List<Literal>> clauses) { | ||
23 | this.parameters = parameters; | ||
24 | this.clauses = clauses; | ||
25 | } | ||
26 | |||
27 | public List<DnfClause> postProcessClauses() { | ||
28 | var parameterInfoMap = getParameterInfoMap(); | ||
29 | var postProcessedClauses = new LinkedHashSet<CanonicalClause>(clauses.size()); | ||
30 | int index = 0; | ||
31 | for (var literals : clauses) { | ||
32 | var postProcessor = new ClausePostProcessor(parameterInfoMap, literals); | ||
33 | ClausePostProcessor.Result result; | ||
34 | try { | ||
35 | result = postProcessor.postProcessClause(); | ||
36 | } catch (InvalidQueryException e) { | ||
37 | throw new InvalidClauseException(index, e); | ||
38 | } | ||
39 | if (result instanceof ClausePostProcessor.ClauseResult clauseResult) { | ||
40 | postProcessedClauses.add(new CanonicalClause(clauseResult.clause())); | ||
41 | } else if (result instanceof ClausePostProcessor.ConstantResult constantResult) { | ||
42 | switch (constantResult) { | ||
43 | case ALWAYS_TRUE -> { | ||
44 | var inputVariables = getInputVariables(); | ||
45 | return List.of(new DnfClause(inputVariables, List.of())); | ||
46 | } | ||
47 | case ALWAYS_FALSE -> { | ||
48 | // Skip this clause because it can never match. | ||
49 | } | ||
50 | default -> throw new IllegalStateException("Unexpected ClausePostProcessor.ConstantResult: " + | ||
51 | constantResult); | ||
52 | } | ||
53 | } else { | ||
54 | throw new IllegalStateException("Unexpected ClausePostProcessor.Result: " + result); | ||
55 | } | ||
56 | index++; | ||
57 | } | ||
58 | return postProcessedClauses.stream().map(CanonicalClause::getDnfClause).toList(); | ||
59 | } | ||
60 | |||
61 | private Map<Variable, ClausePostProcessor.ParameterInfo> getParameterInfoMap() { | ||
62 | var mutableParameterInfoMap = new LinkedHashMap<Variable, ClausePostProcessor.ParameterInfo>(); | ||
63 | int arity = parameters.size(); | ||
64 | for (int i = 0; i < arity; i++) { | ||
65 | var parameter = parameters.get(i); | ||
66 | mutableParameterInfoMap.put(parameter.getVariable(), | ||
67 | new ClausePostProcessor.ParameterInfo(parameter.getDirection(), i)); | ||
68 | } | ||
69 | return Collections.unmodifiableMap(mutableParameterInfoMap); | ||
70 | } | ||
71 | |||
72 | private Set<Variable> getInputVariables() { | ||
73 | var inputParameters = new LinkedHashSet<Variable>(); | ||
74 | for (var parameter : parameters) { | ||
75 | if (parameter.getDirection() == ParameterDirection.IN) { | ||
76 | inputParameters.add(parameter.getVariable()); | ||
77 | } | ||
78 | } | ||
79 | return Collections.unmodifiableSet(inputParameters); | ||
80 | } | ||
81 | |||
82 | private class CanonicalClause { | ||
83 | private final DnfClause dnfClause; | ||
84 | |||
85 | public CanonicalClause(DnfClause dnfClause) { | ||
86 | this.dnfClause = dnfClause; | ||
87 | } | ||
88 | |||
89 | public DnfClause getDnfClause() { | ||
90 | return dnfClause; | ||
91 | } | ||
92 | |||
93 | @Override | ||
94 | public boolean equals(Object obj) { | ||
95 | if (this == obj) { | ||
96 | return true; | ||
97 | } | ||
98 | if (obj == null || getClass() != obj.getClass()) { | ||
99 | return false; | ||
100 | } | ||
101 | var otherCanonicalClause = (CanonicalClause) obj; | ||
102 | var helper = new SubstitutingLiteralEqualityHelper(DnfEqualityChecker.DEFAULT, parameters, parameters); | ||
103 | return dnfClause.equalsWithSubstitution(helper, otherCanonicalClause.dnfClause); | ||
104 | } | ||
105 | |||
106 | @Override | ||
107 | public int hashCode() { | ||
108 | var helper = new SubstitutingLiteralHashCodeHelper(parameters); | ||
109 | return dnfClause.hashCodeWithSubstitution(helper); | ||
110 | } | ||
111 | } | ||
112 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/DnfUtils.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/DnfUtils.java deleted file mode 100644 index 65ab3634..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/DnfUtils.java +++ /dev/null | |||
@@ -1,24 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.dnf; | ||
7 | |||
8 | import java.util.UUID; | ||
9 | |||
10 | public final class DnfUtils { | ||
11 | private DnfUtils() { | ||
12 | throw new IllegalStateException("This is a static utility class and should not be instantiated directly"); | ||
13 | } | ||
14 | |||
15 | public static String generateUniqueName(String originalName) { | ||
16 | UUID uuid = UUID.randomUUID(); | ||
17 | String uniqueString = "_" + uuid.toString().replace('-', '_'); | ||
18 | if (originalName == null) { | ||
19 | return uniqueString; | ||
20 | } else { | ||
21 | return originalName + uniqueString; | ||
22 | } | ||
23 | } | ||
24 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/FunctionalDependency.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/FunctionalDependency.java deleted file mode 100644 index aef07ee3..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/FunctionalDependency.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 | */ | ||
6 | package tools.refinery.store.query.dnf; | ||
7 | |||
8 | import tools.refinery.store.query.InvalidQueryException; | ||
9 | |||
10 | import java.util.HashSet; | ||
11 | import java.util.Set; | ||
12 | |||
13 | public record FunctionalDependency<T>(Set<T> forEach, Set<T> unique) { | ||
14 | public FunctionalDependency { | ||
15 | var uniqueForEach = new HashSet<>(unique); | ||
16 | uniqueForEach.retainAll(forEach); | ||
17 | if (!uniqueForEach.isEmpty()) { | ||
18 | throw new InvalidQueryException("Variables %s appear on both sides of the functional dependency" | ||
19 | .formatted(uniqueForEach)); | ||
20 | } | ||
21 | } | ||
22 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/FunctionalQuery.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/FunctionalQuery.java deleted file mode 100644 index 225f6844..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/FunctionalQuery.java +++ /dev/null | |||
@@ -1,110 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.dnf; | ||
7 | |||
8 | import tools.refinery.store.query.InvalidQueryException; | ||
9 | import tools.refinery.store.query.literal.CallPolarity; | ||
10 | import tools.refinery.store.query.term.Aggregator; | ||
11 | import tools.refinery.store.query.term.AssignedValue; | ||
12 | import tools.refinery.store.query.term.NodeVariable; | ||
13 | import tools.refinery.store.query.term.Variable; | ||
14 | |||
15 | import java.util.ArrayList; | ||
16 | import java.util.List; | ||
17 | import java.util.Objects; | ||
18 | |||
19 | public final class FunctionalQuery<T> extends Query<T> { | ||
20 | private final Class<T> type; | ||
21 | |||
22 | FunctionalQuery(Dnf dnf, Class<T> type) { | ||
23 | super(dnf); | ||
24 | var parameters = dnf.getSymbolicParameters(); | ||
25 | int outputIndex = dnf.arity() - 1; | ||
26 | for (int i = 0; i < outputIndex; i++) { | ||
27 | var parameter = parameters.get(i); | ||
28 | var parameterType = parameter.tryGetType(); | ||
29 | if (parameterType.isPresent()) { | ||
30 | throw new InvalidQueryException("Expected parameter %s of %s to be a node variable, got %s instead" | ||
31 | .formatted(parameter, dnf, parameterType.get().getName())); | ||
32 | } | ||
33 | } | ||
34 | var outputParameter = parameters.get(outputIndex); | ||
35 | var outputParameterType = outputParameter.tryGetType(); | ||
36 | if (outputParameterType.isEmpty() || !outputParameterType.get().equals(type)) { | ||
37 | throw new InvalidQueryException("Expected parameter %s of %s to be %s, but got %s instead".formatted( | ||
38 | outputParameter, dnf, type, outputParameterType.map(Class::getName).orElse("node"))); | ||
39 | } | ||
40 | this.type = type; | ||
41 | } | ||
42 | |||
43 | @Override | ||
44 | public int arity() { | ||
45 | return getDnf().arity() - 1; | ||
46 | } | ||
47 | |||
48 | @Override | ||
49 | public Class<T> valueType() { | ||
50 | return type; | ||
51 | } | ||
52 | |||
53 | @Override | ||
54 | public T defaultValue() { | ||
55 | return null; | ||
56 | } | ||
57 | |||
58 | @Override | ||
59 | protected FunctionalQuery<T> withDnfInternal(Dnf newDnf) { | ||
60 | return newDnf.asFunction(type); | ||
61 | } | ||
62 | |||
63 | @Override | ||
64 | public FunctionalQuery<T> withDnf(Dnf newDnf) { | ||
65 | return (FunctionalQuery<T>) super.withDnf(newDnf); | ||
66 | } | ||
67 | |||
68 | public AssignedValue<T> call(List<NodeVariable> arguments) { | ||
69 | return targetVariable -> { | ||
70 | var argumentsWithTarget = new ArrayList<Variable>(arguments.size() + 1); | ||
71 | argumentsWithTarget.addAll(arguments); | ||
72 | argumentsWithTarget.add(targetVariable); | ||
73 | return getDnf().call(CallPolarity.POSITIVE, argumentsWithTarget); | ||
74 | }; | ||
75 | } | ||
76 | |||
77 | public AssignedValue<T> call(NodeVariable... arguments) { | ||
78 | return call(List.of(arguments)); | ||
79 | } | ||
80 | |||
81 | public <R> AssignedValue<R> aggregate(Aggregator<R, T> aggregator, List<NodeVariable> arguments) { | ||
82 | return targetVariable -> { | ||
83 | var placeholderVariable = Variable.of(type); | ||
84 | var argumentsWithPlaceholder = new ArrayList<Variable>(arguments.size() + 1); | ||
85 | argumentsWithPlaceholder.addAll(arguments); | ||
86 | argumentsWithPlaceholder.add(placeholderVariable); | ||
87 | return getDnf() | ||
88 | .aggregateBy(placeholderVariable, aggregator, argumentsWithPlaceholder) | ||
89 | .toLiteral(targetVariable); | ||
90 | }; | ||
91 | } | ||
92 | |||
93 | public <R> AssignedValue<R> aggregate(Aggregator<R, T> aggregator, NodeVariable... arguments) { | ||
94 | return aggregate(aggregator, List.of(arguments)); | ||
95 | } | ||
96 | |||
97 | @Override | ||
98 | public boolean equals(Object o) { | ||
99 | if (this == o) return true; | ||
100 | if (o == null || getClass() != o.getClass()) return false; | ||
101 | if (!super.equals(o)) return false; | ||
102 | FunctionalQuery<?> that = (FunctionalQuery<?>) o; | ||
103 | return Objects.equals(type, that.type); | ||
104 | } | ||
105 | |||
106 | @Override | ||
107 | public int hashCode() { | ||
108 | return Objects.hash(super.hashCode(), type); | ||
109 | } | ||
110 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/FunctionalQueryBuilder.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/FunctionalQueryBuilder.java deleted file mode 100644 index d1cd7ba8..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/FunctionalQueryBuilder.java +++ /dev/null | |||
@@ -1,29 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.dnf; | ||
7 | |||
8 | import tools.refinery.store.query.term.DataVariable; | ||
9 | |||
10 | public final class FunctionalQueryBuilder<T> extends AbstractQueryBuilder<FunctionalQueryBuilder<T>> { | ||
11 | private final DataVariable<T> outputVariable; | ||
12 | private final Class<T> type; | ||
13 | |||
14 | FunctionalQueryBuilder(DataVariable<T> outputVariable, DnfBuilder dnfBuilder, Class<T> type) { | ||
15 | super(dnfBuilder); | ||
16 | this.outputVariable = outputVariable; | ||
17 | this.type = type; | ||
18 | } | ||
19 | |||
20 | @Override | ||
21 | protected FunctionalQueryBuilder<T> self() { | ||
22 | return this; | ||
23 | } | ||
24 | |||
25 | public FunctionalQuery<T> build() { | ||
26 | dnfBuilder.output(outputVariable); | ||
27 | return dnfBuilder.build().asFunction(type); | ||
28 | } | ||
29 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/InvalidClauseException.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/InvalidClauseException.java deleted file mode 100644 index 747574b9..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/InvalidClauseException.java +++ /dev/null | |||
@@ -1,35 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.dnf; | ||
7 | |||
8 | import tools.refinery.store.query.InvalidQueryException; | ||
9 | |||
10 | public class InvalidClauseException extends InvalidQueryException { | ||
11 | private final int clauseIndex; | ||
12 | |||
13 | public InvalidClauseException(int clauseIndex) { | ||
14 | this.clauseIndex = clauseIndex; | ||
15 | } | ||
16 | |||
17 | public InvalidClauseException(int clauseIndex, String message) { | ||
18 | super(message); | ||
19 | this.clauseIndex = clauseIndex; | ||
20 | } | ||
21 | |||
22 | public InvalidClauseException(int clauseIndex, String message, Throwable cause) { | ||
23 | super(message, cause); | ||
24 | this.clauseIndex = clauseIndex; | ||
25 | } | ||
26 | |||
27 | public InvalidClauseException(int clauseIndex, Throwable cause) { | ||
28 | super(cause); | ||
29 | this.clauseIndex = clauseIndex; | ||
30 | } | ||
31 | |||
32 | public int getClauseIndex() { | ||
33 | return clauseIndex; | ||
34 | } | ||
35 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/Query.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/Query.java deleted file mode 100644 index 83fe6ccd..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/Query.java +++ /dev/null | |||
@@ -1,202 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.dnf; | ||
7 | |||
8 | import tools.refinery.store.query.dnf.callback.*; | ||
9 | import tools.refinery.store.query.term.ParameterDirection; | ||
10 | import tools.refinery.store.query.term.Variable; | ||
11 | |||
12 | import java.util.Objects; | ||
13 | |||
14 | public abstract sealed class Query<T> implements AnyQuery permits FunctionalQuery, RelationalQuery { | ||
15 | private static final String OUTPUT_VARIABLE_NAME = "output"; | ||
16 | |||
17 | private final Dnf dnf; | ||
18 | |||
19 | protected Query(Dnf dnf) { | ||
20 | for (var parameter : dnf.getSymbolicParameters()) { | ||
21 | if (parameter.getDirection() != ParameterDirection.OUT) { | ||
22 | throw new IllegalArgumentException("Query parameter %s with direction %s is not allowed" | ||
23 | .formatted(parameter.getVariable(), parameter.getDirection())); | ||
24 | } | ||
25 | } | ||
26 | this.dnf = dnf; | ||
27 | } | ||
28 | |||
29 | @Override | ||
30 | public String name() { | ||
31 | return dnf.name(); | ||
32 | } | ||
33 | |||
34 | @Override | ||
35 | public Dnf getDnf() { | ||
36 | return dnf; | ||
37 | } | ||
38 | |||
39 | // Allow redeclaration of the method with refined return type. | ||
40 | @SuppressWarnings("squid:S3038") | ||
41 | @Override | ||
42 | public abstract Class<T> valueType(); | ||
43 | |||
44 | public abstract T defaultValue(); | ||
45 | |||
46 | public Query<T> withDnf(Dnf newDnf) { | ||
47 | if (dnf.equals(newDnf)) { | ||
48 | return this; | ||
49 | } | ||
50 | int arity = dnf.arity(); | ||
51 | if (newDnf.arity() != arity) { | ||
52 | throw new IllegalArgumentException("Arity of %s and %s do not match".formatted(dnf, newDnf)); | ||
53 | } | ||
54 | var parameters = dnf.getParameters(); | ||
55 | var newParameters = newDnf.getParameters(); | ||
56 | for (int i = 0; i < arity; i++) { | ||
57 | var parameter = parameters.get(i); | ||
58 | var newParameter = newParameters.get(i); | ||
59 | if (!parameter.matches(newParameter)) { | ||
60 | throw new IllegalArgumentException("Parameter #%d mismatch: %s does not match %s" | ||
61 | .formatted(i, parameter, newParameter)); | ||
62 | } | ||
63 | } | ||
64 | return withDnfInternal(newDnf); | ||
65 | } | ||
66 | |||
67 | protected abstract Query<T> withDnfInternal(Dnf newDnf); | ||
68 | |||
69 | @Override | ||
70 | public boolean equals(Object o) { | ||
71 | if (this == o) return true; | ||
72 | if (o == null || getClass() != o.getClass()) return false; | ||
73 | Query<?> that = (Query<?>) o; | ||
74 | return Objects.equals(dnf, that.dnf); | ||
75 | } | ||
76 | |||
77 | @Override | ||
78 | public int hashCode() { | ||
79 | return Objects.hash(dnf); | ||
80 | } | ||
81 | |||
82 | @Override | ||
83 | public String toString() { | ||
84 | return dnf.toString(); | ||
85 | } | ||
86 | |||
87 | public static QueryBuilder builder() { | ||
88 | return builder(null); | ||
89 | } | ||
90 | |||
91 | public static QueryBuilder builder(String name) { | ||
92 | return new QueryBuilder(name); | ||
93 | } | ||
94 | |||
95 | public static RelationalQuery of(QueryCallback0 callback) { | ||
96 | return of(null, callback); | ||
97 | } | ||
98 | |||
99 | public static RelationalQuery of(String name, QueryCallback0 callback) { | ||
100 | var builder = builder(name); | ||
101 | callback.accept(builder); | ||
102 | return builder.build(); | ||
103 | } | ||
104 | |||
105 | public static RelationalQuery of(QueryCallback1 callback) { | ||
106 | return of(null, callback); | ||
107 | } | ||
108 | |||
109 | public static RelationalQuery of(String name, QueryCallback1 callback) { | ||
110 | var builder = builder(name); | ||
111 | callback.accept(builder, builder.parameter("p1")); | ||
112 | return builder.build(); | ||
113 | } | ||
114 | |||
115 | public static RelationalQuery of(QueryCallback2 callback) { | ||
116 | return of(null, callback); | ||
117 | } | ||
118 | |||
119 | public static RelationalQuery of(String name, QueryCallback2 callback) { | ||
120 | var builder = builder(name); | ||
121 | callback.accept(builder, builder.parameter("p1"), builder.parameter("p2")); | ||
122 | return builder.build(); | ||
123 | } | ||
124 | |||
125 | public static RelationalQuery of(QueryCallback3 callback) { | ||
126 | return of(null, callback); | ||
127 | } | ||
128 | |||
129 | public static RelationalQuery of(String name, QueryCallback3 callback) { | ||
130 | var builder = builder(name); | ||
131 | callback.accept(builder, builder.parameter("p1"), builder.parameter("p2"), builder.parameter("p3")); | ||
132 | return builder.build(); | ||
133 | } | ||
134 | |||
135 | public static RelationalQuery of(QueryCallback4 callback) { | ||
136 | return of(null, callback); | ||
137 | } | ||
138 | |||
139 | public static RelationalQuery of(String name, QueryCallback4 callback) { | ||
140 | var builder = builder(name); | ||
141 | callback.accept(builder, builder.parameter("p1"), builder.parameter("p2"), builder.parameter("p3"), | ||
142 | builder.parameter("p4")); | ||
143 | return builder.build(); | ||
144 | } | ||
145 | |||
146 | public static <T> FunctionalQuery<T> of(Class<T> type, FunctionalQueryCallback0<T> callback) { | ||
147 | return of(null, type, callback); | ||
148 | } | ||
149 | |||
150 | public static <T> FunctionalQuery<T> of(String name, Class<T> type, FunctionalQueryCallback0<T> callback) { | ||
151 | var outputVariable = Variable.of(OUTPUT_VARIABLE_NAME, type); | ||
152 | var builder = builder(name).output(outputVariable); | ||
153 | callback.accept(builder, outputVariable); | ||
154 | return builder.build(); | ||
155 | } | ||
156 | |||
157 | public static <T> FunctionalQuery<T> of(Class<T> type, FunctionalQueryCallback1<T> callback) { | ||
158 | return of(null, type, callback); | ||
159 | } | ||
160 | |||
161 | public static <T> FunctionalQuery<T> of(String name, Class<T> type, FunctionalQueryCallback1<T> callback) { | ||
162 | var outputVariable = Variable.of(OUTPUT_VARIABLE_NAME, type); | ||
163 | var builder = builder(name).output(outputVariable); | ||
164 | callback.accept(builder, builder.parameter("p1"), outputVariable); | ||
165 | return builder.build(); | ||
166 | } | ||
167 | |||
168 | public static <T> FunctionalQuery<T> of(Class<T> type, FunctionalQueryCallback2<T> callback) { | ||
169 | return of(null, type, callback); | ||
170 | } | ||
171 | |||
172 | public static <T> FunctionalQuery<T> of(String name, Class<T> type, FunctionalQueryCallback2<T> callback) { | ||
173 | var outputVariable = Variable.of(OUTPUT_VARIABLE_NAME, type); | ||
174 | var builder = builder(name).output(outputVariable); | ||
175 | callback.accept(builder, builder.parameter("p1"), builder.parameter("p2"), outputVariable); | ||
176 | return builder.build(); | ||
177 | } | ||
178 | |||
179 | public static <T> FunctionalQuery<T> of(Class<T> type, FunctionalQueryCallback3<T> callback) { | ||
180 | return of(null, type, callback); | ||
181 | } | ||
182 | |||
183 | public static <T> FunctionalQuery<T> of(String name, Class<T> type, FunctionalQueryCallback3<T> callback) { | ||
184 | var outputVariable = Variable.of(OUTPUT_VARIABLE_NAME, type); | ||
185 | var builder = builder(name).output(outputVariable); | ||
186 | callback.accept(builder, builder.parameter("p1"), builder.parameter("p2"), builder.parameter("p3"), | ||
187 | outputVariable); | ||
188 | return builder.build(); | ||
189 | } | ||
190 | |||
191 | public static <T> FunctionalQuery<T> of(Class<T> type, FunctionalQueryCallback4<T> callback) { | ||
192 | return of(null, type, callback); | ||
193 | } | ||
194 | |||
195 | public static <T> FunctionalQuery<T> of(String name, Class<T> type, FunctionalQueryCallback4<T> callback) { | ||
196 | var outputVariable = Variable.of(OUTPUT_VARIABLE_NAME, type); | ||
197 | var builder = builder(name).output(outputVariable); | ||
198 | callback.accept(builder, builder.parameter("p1"), builder.parameter("p2"), builder.parameter("p3"), | ||
199 | builder.parameter("p4"), outputVariable); | ||
200 | return builder.build(); | ||
201 | } | ||
202 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/QueryBuilder.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/QueryBuilder.java deleted file mode 100644 index 138911bc..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/QueryBuilder.java +++ /dev/null | |||
@@ -1,27 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.dnf; | ||
7 | |||
8 | import tools.refinery.store.query.term.DataVariable; | ||
9 | |||
10 | public final class QueryBuilder extends AbstractQueryBuilder<QueryBuilder> { | ||
11 | QueryBuilder(String name) { | ||
12 | super(Dnf.builder(name)); | ||
13 | } | ||
14 | |||
15 | @Override | ||
16 | protected QueryBuilder self() { | ||
17 | return this; | ||
18 | } | ||
19 | |||
20 | public <T> FunctionalQueryBuilder<T> output(DataVariable<T> outputVariable) { | ||
21 | return new FunctionalQueryBuilder<>(outputVariable, dnfBuilder, outputVariable.getType()); | ||
22 | } | ||
23 | |||
24 | public RelationalQuery build() { | ||
25 | return dnfBuilder.build().asRelation(); | ||
26 | } | ||
27 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/RelationalQuery.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/RelationalQuery.java deleted file mode 100644 index 98f71e11..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/RelationalQuery.java +++ /dev/null | |||
@@ -1,77 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.dnf; | ||
7 | |||
8 | import tools.refinery.store.query.InvalidQueryException; | ||
9 | import tools.refinery.store.query.literal.CallLiteral; | ||
10 | import tools.refinery.store.query.literal.CallPolarity; | ||
11 | import tools.refinery.store.query.term.AssignedValue; | ||
12 | import tools.refinery.store.query.term.NodeVariable; | ||
13 | |||
14 | import java.util.Collections; | ||
15 | import java.util.List; | ||
16 | |||
17 | public final class RelationalQuery extends Query<Boolean> { | ||
18 | RelationalQuery(Dnf dnf) { | ||
19 | super(dnf); | ||
20 | for (var parameter : dnf.getSymbolicParameters()) { | ||
21 | var parameterType = parameter.tryGetType(); | ||
22 | if (parameterType.isPresent()) { | ||
23 | throw new InvalidQueryException("Expected parameter %s of %s to be a node variable, got %s instead" | ||
24 | .formatted(parameter, dnf, parameterType.get().getName())); | ||
25 | } | ||
26 | } | ||
27 | } | ||
28 | |||
29 | @Override | ||
30 | public int arity() { | ||
31 | return getDnf().arity(); | ||
32 | } | ||
33 | |||
34 | @Override | ||
35 | public Class<Boolean> valueType() { | ||
36 | return Boolean.class; | ||
37 | } | ||
38 | |||
39 | @Override | ||
40 | public Boolean defaultValue() { | ||
41 | return false; | ||
42 | } | ||
43 | |||
44 | @Override | ||
45 | protected RelationalQuery withDnfInternal(Dnf newDnf) { | ||
46 | return newDnf.asRelation(); | ||
47 | } | ||
48 | |||
49 | @Override | ||
50 | public RelationalQuery withDnf(Dnf newDnf) { | ||
51 | return (RelationalQuery) super.withDnf(newDnf); | ||
52 | } | ||
53 | |||
54 | public CallLiteral call(CallPolarity polarity, List<NodeVariable> arguments) { | ||
55 | return getDnf().call(polarity, Collections.unmodifiableList(arguments)); | ||
56 | } | ||
57 | |||
58 | public CallLiteral call(CallPolarity polarity, NodeVariable... arguments) { | ||
59 | return getDnf().call(polarity, arguments); | ||
60 | } | ||
61 | |||
62 | public CallLiteral call(NodeVariable... arguments) { | ||
63 | return getDnf().call(arguments); | ||
64 | } | ||
65 | |||
66 | public CallLiteral callTransitive(NodeVariable left, NodeVariable right) { | ||
67 | return getDnf().callTransitive(left, right); | ||
68 | } | ||
69 | |||
70 | public AssignedValue<Integer> count(List<NodeVariable> arguments) { | ||
71 | return getDnf().count(Collections.unmodifiableList(arguments)); | ||
72 | } | ||
73 | |||
74 | public AssignedValue<Integer> count(NodeVariable... arguments) { | ||
75 | return getDnf().count(arguments); | ||
76 | } | ||
77 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/SymbolicParameter.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/SymbolicParameter.java deleted file mode 100644 index fe9cefcc..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/SymbolicParameter.java +++ /dev/null | |||
@@ -1,53 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.dnf; | ||
7 | |||
8 | import tools.refinery.store.query.equality.LiteralHashCodeHelper; | ||
9 | import tools.refinery.store.query.term.Parameter; | ||
10 | import tools.refinery.store.query.term.ParameterDirection; | ||
11 | import tools.refinery.store.query.term.Variable; | ||
12 | |||
13 | import java.util.Objects; | ||
14 | |||
15 | public final class SymbolicParameter extends Parameter { | ||
16 | private final Variable variable; | ||
17 | |||
18 | public SymbolicParameter(Variable variable, ParameterDirection direction) { | ||
19 | super(variable.tryGetType().orElse(null), direction); | ||
20 | this.variable = variable; | ||
21 | } | ||
22 | |||
23 | public Variable getVariable() { | ||
24 | return variable; | ||
25 | } | ||
26 | |||
27 | public int hashCodeWithSubstitution(LiteralHashCodeHelper helper) { | ||
28 | return Objects.hash(super.hashCode(), helper.getVariableHashCode(variable)); | ||
29 | } | ||
30 | |||
31 | @Override | ||
32 | public String toString() { | ||
33 | var direction = getDirection(); | ||
34 | if (direction == ParameterDirection.OUT) { | ||
35 | return variable.toString(); | ||
36 | } | ||
37 | return "%s %s".formatted(getDirection(), variable); | ||
38 | } | ||
39 | |||
40 | @Override | ||
41 | public boolean equals(Object o) { | ||
42 | if (this == o) return true; | ||
43 | if (o == null || getClass() != o.getClass()) return false; | ||
44 | if (!super.equals(o)) return false; | ||
45 | SymbolicParameter that = (SymbolicParameter) o; | ||
46 | return Objects.equals(variable, that.variable); | ||
47 | } | ||
48 | |||
49 | @Override | ||
50 | public int hashCode() { | ||
51 | return Objects.hash(super.hashCode(), variable); | ||
52 | } | ||
53 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/ClauseCallback0.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/ClauseCallback0.java deleted file mode 100644 index d98dda2e..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/ClauseCallback0.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 | */ | ||
6 | package tools.refinery.store.query.dnf.callback; | ||
7 | |||
8 | import tools.refinery.store.query.literal.Literal; | ||
9 | |||
10 | import java.util.Collection; | ||
11 | |||
12 | @FunctionalInterface | ||
13 | public interface ClauseCallback0 { | ||
14 | Collection<Literal> toLiterals(); | ||
15 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/ClauseCallback1Data0.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/ClauseCallback1Data0.java deleted file mode 100644 index 4c01a527..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/ClauseCallback1Data0.java +++ /dev/null | |||
@@ -1,16 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.dnf.callback; | ||
7 | |||
8 | import tools.refinery.store.query.literal.Literal; | ||
9 | import tools.refinery.store.query.term.NodeVariable; | ||
10 | |||
11 | import java.util.Collection; | ||
12 | |||
13 | @FunctionalInterface | ||
14 | public interface ClauseCallback1Data0 { | ||
15 | Collection<Literal> toLiterals(NodeVariable v1); | ||
16 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/ClauseCallback1Data1.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/ClauseCallback1Data1.java deleted file mode 100644 index 2c0cb6eb..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/ClauseCallback1Data1.java +++ /dev/null | |||
@@ -1,16 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.dnf.callback; | ||
7 | |||
8 | import tools.refinery.store.query.literal.Literal; | ||
9 | import tools.refinery.store.query.term.DataVariable; | ||
10 | |||
11 | import java.util.Collection; | ||
12 | |||
13 | @FunctionalInterface | ||
14 | public interface ClauseCallback1Data1<T> { | ||
15 | Collection<Literal> toLiterals(DataVariable<T> d1); | ||
16 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/ClauseCallback2Data0.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/ClauseCallback2Data0.java deleted file mode 100644 index d764bdba..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/ClauseCallback2Data0.java +++ /dev/null | |||
@@ -1,16 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.dnf.callback; | ||
7 | |||
8 | import tools.refinery.store.query.literal.Literal; | ||
9 | import tools.refinery.store.query.term.NodeVariable; | ||
10 | |||
11 | import java.util.Collection; | ||
12 | |||
13 | @FunctionalInterface | ||
14 | public interface ClauseCallback2Data0 { | ||
15 | Collection<Literal> toLiterals(NodeVariable v1, NodeVariable v2); | ||
16 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/ClauseCallback2Data1.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/ClauseCallback2Data1.java deleted file mode 100644 index 140af03a..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/ClauseCallback2Data1.java +++ /dev/null | |||
@@ -1,17 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.dnf.callback; | ||
7 | |||
8 | import tools.refinery.store.query.literal.Literal; | ||
9 | import tools.refinery.store.query.term.DataVariable; | ||
10 | import tools.refinery.store.query.term.NodeVariable; | ||
11 | |||
12 | import java.util.Collection; | ||
13 | |||
14 | @FunctionalInterface | ||
15 | public interface ClauseCallback2Data1<T> { | ||
16 | Collection<Literal> toLiterals(NodeVariable v1, DataVariable<T> x1); | ||
17 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/ClauseCallback2Data2.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/ClauseCallback2Data2.java deleted file mode 100644 index bfc8637c..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/ClauseCallback2Data2.java +++ /dev/null | |||
@@ -1,16 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.dnf.callback; | ||
7 | |||
8 | import tools.refinery.store.query.literal.Literal; | ||
9 | import tools.refinery.store.query.term.DataVariable; | ||
10 | |||
11 | import java.util.Collection; | ||
12 | |||
13 | @FunctionalInterface | ||
14 | public interface ClauseCallback2Data2<T1, T2> { | ||
15 | Collection<Literal> toLiterals(DataVariable<T1> x1, DataVariable<T2> x2); | ||
16 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/ClauseCallback3Data0.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/ClauseCallback3Data0.java deleted file mode 100644 index 074df65b..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/ClauseCallback3Data0.java +++ /dev/null | |||
@@ -1,16 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.dnf.callback; | ||
7 | |||
8 | import tools.refinery.store.query.literal.Literal; | ||
9 | import tools.refinery.store.query.term.NodeVariable; | ||
10 | |||
11 | import java.util.Collection; | ||
12 | |||
13 | @FunctionalInterface | ||
14 | public interface ClauseCallback3Data0 { | ||
15 | Collection<Literal> toLiterals(NodeVariable v1, NodeVariable v2, NodeVariable v3); | ||
16 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/ClauseCallback3Data1.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/ClauseCallback3Data1.java deleted file mode 100644 index 24ba5187..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/ClauseCallback3Data1.java +++ /dev/null | |||
@@ -1,17 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.dnf.callback; | ||
7 | |||
8 | import tools.refinery.store.query.literal.Literal; | ||
9 | import tools.refinery.store.query.term.DataVariable; | ||
10 | import tools.refinery.store.query.term.NodeVariable; | ||
11 | |||
12 | import java.util.Collection; | ||
13 | |||
14 | @FunctionalInterface | ||
15 | public interface ClauseCallback3Data1<T> { | ||
16 | Collection<Literal> toLiterals(NodeVariable v1, NodeVariable v2, DataVariable<T> d1); | ||
17 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/ClauseCallback3Data2.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/ClauseCallback3Data2.java deleted file mode 100644 index 2a2e837a..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/ClauseCallback3Data2.java +++ /dev/null | |||
@@ -1,17 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.dnf.callback; | ||
7 | |||
8 | import tools.refinery.store.query.literal.Literal; | ||
9 | import tools.refinery.store.query.term.DataVariable; | ||
10 | import tools.refinery.store.query.term.NodeVariable; | ||
11 | |||
12 | import java.util.Collection; | ||
13 | |||
14 | @FunctionalInterface | ||
15 | public interface ClauseCallback3Data2<T1, T2> { | ||
16 | Collection<Literal> toLiterals(NodeVariable v1, DataVariable<T1> d1, DataVariable<T2> d2); | ||
17 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/ClauseCallback3Data3.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/ClauseCallback3Data3.java deleted file mode 100644 index 8f4bdd01..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/ClauseCallback3Data3.java +++ /dev/null | |||
@@ -1,16 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.dnf.callback; | ||
7 | |||
8 | import tools.refinery.store.query.literal.Literal; | ||
9 | import tools.refinery.store.query.term.DataVariable; | ||
10 | |||
11 | import java.util.Collection; | ||
12 | |||
13 | @FunctionalInterface | ||
14 | public interface ClauseCallback3Data3<T1, T2, T3> { | ||
15 | Collection<Literal> toLiterals(DataVariable<T1> d1, DataVariable<T2> d2, DataVariable<T3> d3); | ||
16 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/ClauseCallback4Data0.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/ClauseCallback4Data0.java deleted file mode 100644 index ed0f87b2..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/ClauseCallback4Data0.java +++ /dev/null | |||
@@ -1,16 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.dnf.callback; | ||
7 | |||
8 | import tools.refinery.store.query.literal.Literal; | ||
9 | import tools.refinery.store.query.term.NodeVariable; | ||
10 | |||
11 | import java.util.Collection; | ||
12 | |||
13 | @FunctionalInterface | ||
14 | public interface ClauseCallback4Data0 { | ||
15 | Collection<Literal> toLiterals(NodeVariable v1, NodeVariable v2, NodeVariable v3, NodeVariable v4); | ||
16 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/ClauseCallback4Data1.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/ClauseCallback4Data1.java deleted file mode 100644 index 9b27e2e1..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/ClauseCallback4Data1.java +++ /dev/null | |||
@@ -1,17 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.dnf.callback; | ||
7 | |||
8 | import tools.refinery.store.query.literal.Literal; | ||
9 | import tools.refinery.store.query.term.DataVariable; | ||
10 | import tools.refinery.store.query.term.NodeVariable; | ||
11 | |||
12 | import java.util.Collection; | ||
13 | |||
14 | @FunctionalInterface | ||
15 | public interface ClauseCallback4Data1<T> { | ||
16 | Collection<Literal> toLiterals(NodeVariable v1, NodeVariable v2, NodeVariable v3, DataVariable<T> d1); | ||
17 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/ClauseCallback4Data2.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/ClauseCallback4Data2.java deleted file mode 100644 index cbc4808e..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/ClauseCallback4Data2.java +++ /dev/null | |||
@@ -1,17 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.dnf.callback; | ||
7 | |||
8 | import tools.refinery.store.query.literal.Literal; | ||
9 | import tools.refinery.store.query.term.DataVariable; | ||
10 | import tools.refinery.store.query.term.NodeVariable; | ||
11 | |||
12 | import java.util.Collection; | ||
13 | |||
14 | @FunctionalInterface | ||
15 | public interface ClauseCallback4Data2<T1, T2> { | ||
16 | Collection<Literal> toLiterals(NodeVariable v1, NodeVariable v2, DataVariable<T1> d1, DataVariable<T2> d2); | ||
17 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/ClauseCallback4Data3.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/ClauseCallback4Data3.java deleted file mode 100644 index a6258f36..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/ClauseCallback4Data3.java +++ /dev/null | |||
@@ -1,17 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.dnf.callback; | ||
7 | |||
8 | import tools.refinery.store.query.literal.Literal; | ||
9 | import tools.refinery.store.query.term.DataVariable; | ||
10 | import tools.refinery.store.query.term.NodeVariable; | ||
11 | |||
12 | import java.util.Collection; | ||
13 | |||
14 | @FunctionalInterface | ||
15 | public interface ClauseCallback4Data3<T1, T2, T3> { | ||
16 | Collection<Literal> toLiterals(NodeVariable v1, DataVariable<T1> d1, DataVariable<T2> d2, DataVariable<T3> d3); | ||
17 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/ClauseCallback4Data4.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/ClauseCallback4Data4.java deleted file mode 100644 index b52a911a..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/ClauseCallback4Data4.java +++ /dev/null | |||
@@ -1,16 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.dnf.callback; | ||
7 | |||
8 | import tools.refinery.store.query.literal.Literal; | ||
9 | import tools.refinery.store.query.term.DataVariable; | ||
10 | |||
11 | import java.util.Collection; | ||
12 | |||
13 | @FunctionalInterface | ||
14 | public interface ClauseCallback4Data4<T1, T2, T3, T4> { | ||
15 | Collection<Literal> toLiterals(DataVariable<T1> d1, DataVariable<T2> d2, DataVariable<T3> d3, DataVariable<T4> d4); | ||
16 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/FunctionalQueryCallback0.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/FunctionalQueryCallback0.java deleted file mode 100644 index 63b3eee6..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/FunctionalQueryCallback0.java +++ /dev/null | |||
@@ -1,14 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.dnf.callback; | ||
7 | |||
8 | import tools.refinery.store.query.dnf.FunctionalQueryBuilder; | ||
9 | import tools.refinery.store.query.term.DataVariable; | ||
10 | |||
11 | @FunctionalInterface | ||
12 | public interface FunctionalQueryCallback0<T> { | ||
13 | void accept(FunctionalQueryBuilder<T> builder, DataVariable<T> output); | ||
14 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/FunctionalQueryCallback1.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/FunctionalQueryCallback1.java deleted file mode 100644 index 1295a118..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/FunctionalQueryCallback1.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 | */ | ||
6 | package tools.refinery.store.query.dnf.callback; | ||
7 | |||
8 | import tools.refinery.store.query.dnf.FunctionalQueryBuilder; | ||
9 | import tools.refinery.store.query.term.DataVariable; | ||
10 | import tools.refinery.store.query.term.NodeVariable; | ||
11 | |||
12 | @FunctionalInterface | ||
13 | public interface FunctionalQueryCallback1<T> { | ||
14 | void accept(FunctionalQueryBuilder<T> builder, NodeVariable p1, DataVariable<T> output); | ||
15 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/FunctionalQueryCallback2.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/FunctionalQueryCallback2.java deleted file mode 100644 index d5b7f9ff..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/FunctionalQueryCallback2.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 | */ | ||
6 | package tools.refinery.store.query.dnf.callback; | ||
7 | |||
8 | import tools.refinery.store.query.dnf.FunctionalQueryBuilder; | ||
9 | import tools.refinery.store.query.term.DataVariable; | ||
10 | import tools.refinery.store.query.term.NodeVariable; | ||
11 | |||
12 | @FunctionalInterface | ||
13 | public interface FunctionalQueryCallback2<T> { | ||
14 | void accept(FunctionalQueryBuilder<T> builder, NodeVariable p1, NodeVariable p2, DataVariable<T> output); | ||
15 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/FunctionalQueryCallback3.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/FunctionalQueryCallback3.java deleted file mode 100644 index dc8404a0..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/FunctionalQueryCallback3.java +++ /dev/null | |||
@@ -1,16 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.dnf.callback; | ||
7 | |||
8 | import tools.refinery.store.query.dnf.FunctionalQueryBuilder; | ||
9 | import tools.refinery.store.query.term.DataVariable; | ||
10 | import tools.refinery.store.query.term.NodeVariable; | ||
11 | |||
12 | @FunctionalInterface | ||
13 | public interface FunctionalQueryCallback3<T> { | ||
14 | void accept(FunctionalQueryBuilder<T> builder, NodeVariable p1, NodeVariable p2, NodeVariable p3, | ||
15 | DataVariable<T> output); | ||
16 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/FunctionalQueryCallback4.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/FunctionalQueryCallback4.java deleted file mode 100644 index b6d3ddb0..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/FunctionalQueryCallback4.java +++ /dev/null | |||
@@ -1,16 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.dnf.callback; | ||
7 | |||
8 | import tools.refinery.store.query.dnf.FunctionalQueryBuilder; | ||
9 | import tools.refinery.store.query.term.DataVariable; | ||
10 | import tools.refinery.store.query.term.NodeVariable; | ||
11 | |||
12 | @FunctionalInterface | ||
13 | public interface FunctionalQueryCallback4<T> { | ||
14 | void accept(FunctionalQueryBuilder<T> builder, NodeVariable p1, NodeVariable p2, NodeVariable p3, NodeVariable p4, | ||
15 | DataVariable<T> output); | ||
16 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/QueryCallback0.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/QueryCallback0.java deleted file mode 100644 index 3cf1de48..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/QueryCallback0.java +++ /dev/null | |||
@@ -1,13 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.dnf.callback; | ||
7 | |||
8 | import tools.refinery.store.query.dnf.QueryBuilder; | ||
9 | |||
10 | @FunctionalInterface | ||
11 | public interface QueryCallback0 { | ||
12 | void accept(QueryBuilder builder); | ||
13 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/QueryCallback1.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/QueryCallback1.java deleted file mode 100644 index 0a150955..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/QueryCallback1.java +++ /dev/null | |||
@@ -1,14 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.dnf.callback; | ||
7 | |||
8 | import tools.refinery.store.query.dnf.QueryBuilder; | ||
9 | import tools.refinery.store.query.term.NodeVariable; | ||
10 | |||
11 | @FunctionalInterface | ||
12 | public interface QueryCallback1 { | ||
13 | void accept(QueryBuilder builder, NodeVariable p1); | ||
14 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/QueryCallback2.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/QueryCallback2.java deleted file mode 100644 index 9493a7b4..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/QueryCallback2.java +++ /dev/null | |||
@@ -1,14 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.dnf.callback; | ||
7 | |||
8 | import tools.refinery.store.query.dnf.QueryBuilder; | ||
9 | import tools.refinery.store.query.term.NodeVariable; | ||
10 | |||
11 | @FunctionalInterface | ||
12 | public interface QueryCallback2 { | ||
13 | void accept(QueryBuilder builder, NodeVariable p1, NodeVariable p2); | ||
14 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/QueryCallback3.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/QueryCallback3.java deleted file mode 100644 index 358c7da7..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/QueryCallback3.java +++ /dev/null | |||
@@ -1,14 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.dnf.callback; | ||
7 | |||
8 | import tools.refinery.store.query.dnf.QueryBuilder; | ||
9 | import tools.refinery.store.query.term.NodeVariable; | ||
10 | |||
11 | @FunctionalInterface | ||
12 | public interface QueryCallback3 { | ||
13 | void accept(QueryBuilder builder, NodeVariable p1, NodeVariable p2, NodeVariable p3); | ||
14 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/QueryCallback4.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/QueryCallback4.java deleted file mode 100644 index 890dda16..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/QueryCallback4.java +++ /dev/null | |||
@@ -1,14 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.dnf.callback; | ||
7 | |||
8 | import tools.refinery.store.query.dnf.QueryBuilder; | ||
9 | import tools.refinery.store.query.term.NodeVariable; | ||
10 | |||
11 | @FunctionalInterface | ||
12 | public interface QueryCallback4 { | ||
13 | void accept(QueryBuilder builder, NodeVariable p1, NodeVariable p2, NodeVariable p3, NodeVariable p4); | ||
14 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/equality/DeepDnfEqualityChecker.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/equality/DeepDnfEqualityChecker.java deleted file mode 100644 index d6171314..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/equality/DeepDnfEqualityChecker.java +++ /dev/null | |||
@@ -1,77 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.equality; | ||
7 | |||
8 | import tools.refinery.store.query.dnf.Dnf; | ||
9 | import tools.refinery.store.query.dnf.DnfClause; | ||
10 | import tools.refinery.store.query.dnf.SymbolicParameter; | ||
11 | import tools.refinery.store.query.literal.Literal; | ||
12 | import tools.refinery.store.util.CycleDetectingMapper; | ||
13 | |||
14 | import java.util.List; | ||
15 | |||
16 | public class DeepDnfEqualityChecker implements DnfEqualityChecker { | ||
17 | private final CycleDetectingMapper<Pair, Boolean> mapper = new CycleDetectingMapper<>(this::doCheckEqual); | ||
18 | |||
19 | @Override | ||
20 | public boolean dnfEqual(Dnf left, Dnf right) { | ||
21 | return mapper.map(new Pair(left, right)); | ||
22 | } | ||
23 | |||
24 | public boolean dnfEqualRaw(List<SymbolicParameter> symbolicParameters, | ||
25 | List<? extends List<? extends Literal>> clauses, Dnf other) { | ||
26 | int arity = symbolicParameters.size(); | ||
27 | if (arity != other.arity()) { | ||
28 | return false; | ||
29 | } | ||
30 | for (int i = 0; i < arity; i++) { | ||
31 | if (!symbolicParameters.get(i).getDirection().equals(other.getSymbolicParameters().get(i).getDirection())) { | ||
32 | return false; | ||
33 | } | ||
34 | } | ||
35 | int numClauses = clauses.size(); | ||
36 | if (numClauses != other.getClauses().size()) { | ||
37 | return false; | ||
38 | } | ||
39 | for (int i = 0; i < numClauses; i++) { | ||
40 | var literalEqualityHelper = new SubstitutingLiteralEqualityHelper(this, symbolicParameters, | ||
41 | other.getSymbolicParameters()); | ||
42 | if (!equalsWithSubstitutionRaw(literalEqualityHelper, clauses.get(i), other.getClauses().get(i))) { | ||
43 | return false; | ||
44 | } | ||
45 | } | ||
46 | return true; | ||
47 | } | ||
48 | |||
49 | private boolean equalsWithSubstitutionRaw(LiteralEqualityHelper helper, List<? extends Literal> literals, | ||
50 | DnfClause other) { | ||
51 | int size = literals.size(); | ||
52 | if (size != other.literals().size()) { | ||
53 | return false; | ||
54 | } | ||
55 | for (int i = 0; i < size; i++) { | ||
56 | if (!literals.get(i).equalsWithSubstitution(helper, other.literals().get(i))) { | ||
57 | return false; | ||
58 | } | ||
59 | } | ||
60 | return true; | ||
61 | } | ||
62 | |||
63 | protected boolean doCheckEqual(Pair pair) { | ||
64 | return pair.left.equalsWithSubstitution(this, pair.right); | ||
65 | } | ||
66 | |||
67 | protected List<Pair> getInProgress() { | ||
68 | return mapper.getInProgress(); | ||
69 | } | ||
70 | |||
71 | protected record Pair(Dnf left, Dnf right) { | ||
72 | @Override | ||
73 | public String toString() { | ||
74 | return "(%s, %s)".formatted(left.name(), right.name()); | ||
75 | } | ||
76 | } | ||
77 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/equality/DnfEqualityChecker.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/equality/DnfEqualityChecker.java deleted file mode 100644 index e2cfd79b..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/equality/DnfEqualityChecker.java +++ /dev/null | |||
@@ -1,17 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.equality; | ||
7 | |||
8 | import tools.refinery.store.query.dnf.Dnf; | ||
9 | |||
10 | import java.util.Objects; | ||
11 | |||
12 | @FunctionalInterface | ||
13 | public interface DnfEqualityChecker { | ||
14 | DnfEqualityChecker DEFAULT = Objects::equals; | ||
15 | |||
16 | boolean dnfEqual(Dnf left, Dnf right); | ||
17 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/equality/LiteralEqualityHelper.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/equality/LiteralEqualityHelper.java deleted file mode 100644 index 5abc76ce..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/equality/LiteralEqualityHelper.java +++ /dev/null | |||
@@ -1,27 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.equality; | ||
7 | |||
8 | import tools.refinery.store.query.dnf.Dnf; | ||
9 | import tools.refinery.store.query.term.Variable; | ||
10 | |||
11 | import java.util.Objects; | ||
12 | |||
13 | public interface LiteralEqualityHelper extends DnfEqualityChecker { | ||
14 | LiteralEqualityHelper DEFAULT = new LiteralEqualityHelper() { | ||
15 | @Override | ||
16 | public boolean variableEqual(Variable left, Variable right) { | ||
17 | return Objects.equals(left, right); | ||
18 | } | ||
19 | |||
20 | @Override | ||
21 | public boolean dnfEqual(Dnf left, Dnf right) { | ||
22 | return DnfEqualityChecker.DEFAULT.dnfEqual(left, right); | ||
23 | } | ||
24 | }; | ||
25 | |||
26 | boolean variableEqual(Variable left, Variable right); | ||
27 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/equality/LiteralHashCodeHelper.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/equality/LiteralHashCodeHelper.java deleted file mode 100644 index 5495160a..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/equality/LiteralHashCodeHelper.java +++ /dev/null | |||
@@ -1,17 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.equality; | ||
7 | |||
8 | import tools.refinery.store.query.term.Variable; | ||
9 | |||
10 | import java.util.Objects; | ||
11 | |||
12 | @FunctionalInterface | ||
13 | public interface LiteralHashCodeHelper { | ||
14 | LiteralHashCodeHelper DEFAULT = Objects::hashCode; | ||
15 | |||
16 | int getVariableHashCode(Variable variable); | ||
17 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/equality/SubstitutingLiteralEqualityHelper.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/equality/SubstitutingLiteralEqualityHelper.java deleted file mode 100644 index 50a79e07..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/equality/SubstitutingLiteralEqualityHelper.java +++ /dev/null | |||
@@ -1,59 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.equality; | ||
7 | |||
8 | import tools.refinery.store.query.dnf.Dnf; | ||
9 | import tools.refinery.store.query.dnf.SymbolicParameter; | ||
10 | import tools.refinery.store.query.term.Variable; | ||
11 | |||
12 | import java.util.HashMap; | ||
13 | import java.util.List; | ||
14 | import java.util.Map; | ||
15 | |||
16 | public class SubstitutingLiteralEqualityHelper implements LiteralEqualityHelper { | ||
17 | private final DnfEqualityChecker dnfEqualityChecker; | ||
18 | private final Map<Variable, Variable> leftToRight; | ||
19 | private final Map<Variable, Variable> rightToLeft; | ||
20 | |||
21 | public SubstitutingLiteralEqualityHelper(DnfEqualityChecker dnfEqualityChecker, | ||
22 | List<SymbolicParameter> leftParameters, | ||
23 | List<SymbolicParameter> rightParameters) { | ||
24 | this.dnfEqualityChecker = dnfEqualityChecker; | ||
25 | var arity = leftParameters.size(); | ||
26 | if (arity != rightParameters.size()) { | ||
27 | throw new IllegalArgumentException("Parameter lists have unequal length"); | ||
28 | } | ||
29 | leftToRight = new HashMap<>(arity); | ||
30 | rightToLeft = new HashMap<>(arity); | ||
31 | for (int i = 0; i < arity; i++) { | ||
32 | if (!variableEqual(leftParameters.get(i).getVariable(), rightParameters.get(i).getVariable())) { | ||
33 | throw new IllegalArgumentException("Parameter lists cannot be unified: duplicate parameter " + i); | ||
34 | } | ||
35 | } | ||
36 | } | ||
37 | |||
38 | @Override | ||
39 | public boolean dnfEqual(Dnf left, Dnf right) { | ||
40 | return dnfEqualityChecker.dnfEqual(left, right); | ||
41 | } | ||
42 | |||
43 | @Override | ||
44 | public boolean variableEqual(Variable left, Variable right) { | ||
45 | if (left.tryGetType().equals(right.tryGetType()) && | ||
46 | checkMapping(leftToRight, left, right) && | ||
47 | checkMapping(rightToLeft, right, left)) { | ||
48 | leftToRight.put(left, right); | ||
49 | rightToLeft.put(right, left); | ||
50 | return true; | ||
51 | } | ||
52 | return false; | ||
53 | } | ||
54 | |||
55 | private static boolean checkMapping(Map<Variable, Variable> map, Variable key, Variable expectedValue) { | ||
56 | var currentValue = map.get(key); | ||
57 | return currentValue == null || currentValue.equals(expectedValue); | ||
58 | } | ||
59 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/equality/SubstitutingLiteralHashCodeHelper.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/equality/SubstitutingLiteralHashCodeHelper.java deleted file mode 100644 index 754f6976..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/equality/SubstitutingLiteralHashCodeHelper.java +++ /dev/null | |||
@@ -1,42 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.equality; | ||
7 | |||
8 | import tools.refinery.store.query.dnf.SymbolicParameter; | ||
9 | import tools.refinery.store.query.term.Variable; | ||
10 | |||
11 | import java.util.LinkedHashMap; | ||
12 | import java.util.List; | ||
13 | import java.util.Map; | ||
14 | |||
15 | public class SubstitutingLiteralHashCodeHelper implements LiteralHashCodeHelper { | ||
16 | private final Map<Variable, Integer> assignedHashCodes = new LinkedHashMap<>(); | ||
17 | |||
18 | // 0 is for {@code null}, so we start with 1. | ||
19 | private int next = 1; | ||
20 | |||
21 | public SubstitutingLiteralHashCodeHelper() { | ||
22 | this(List.of()); | ||
23 | } | ||
24 | |||
25 | public SubstitutingLiteralHashCodeHelper(List<SymbolicParameter> parameters) { | ||
26 | for (var parameter : parameters) { | ||
27 | getVariableHashCode(parameter.getVariable()); | ||
28 | } | ||
29 | } | ||
30 | |||
31 | @Override | ||
32 | public int getVariableHashCode(Variable variable) { | ||
33 | if (variable == null) { | ||
34 | return 0; | ||
35 | } | ||
36 | return assignedHashCodes.computeIfAbsent(variable, key -> { | ||
37 | int sequenceNumber = next; | ||
38 | next++; | ||
39 | return variable.hashCodeWithSubstitution(sequenceNumber); | ||
40 | }); | ||
41 | } | ||
42 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/AbstractCallLiteral.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/AbstractCallLiteral.java deleted file mode 100644 index 0e99d441..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/AbstractCallLiteral.java +++ /dev/null | |||
@@ -1,135 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.literal; | ||
7 | |||
8 | import tools.refinery.store.query.Constraint; | ||
9 | import tools.refinery.store.query.InvalidQueryException; | ||
10 | import tools.refinery.store.query.equality.LiteralEqualityHelper; | ||
11 | import tools.refinery.store.query.equality.LiteralHashCodeHelper; | ||
12 | import tools.refinery.store.query.substitution.Substitution; | ||
13 | import tools.refinery.store.query.term.ParameterDirection; | ||
14 | import tools.refinery.store.query.term.Variable; | ||
15 | |||
16 | import java.util.*; | ||
17 | |||
18 | // {@link Object#equals(Object)} is implemented by {@link AbstractLiteral}. | ||
19 | @SuppressWarnings("squid:S2160") | ||
20 | public abstract class AbstractCallLiteral extends AbstractLiteral { | ||
21 | private final Constraint target; | ||
22 | private final List<Variable> arguments; | ||
23 | private final Set<Variable> inArguments; | ||
24 | private final Set<Variable> outArguments; | ||
25 | |||
26 | // Use exhaustive switch over enums. | ||
27 | @SuppressWarnings("squid:S1301") | ||
28 | protected AbstractCallLiteral(Constraint target, List<Variable> arguments) { | ||
29 | int arity = target.arity(); | ||
30 | if (arguments.size() != arity) { | ||
31 | throw new InvalidQueryException("%s needs %d arguments, but got %s".formatted(target.name(), | ||
32 | target.arity(), arguments.size())); | ||
33 | } | ||
34 | this.target = target; | ||
35 | this.arguments = arguments; | ||
36 | var mutableInArguments = new LinkedHashSet<Variable>(); | ||
37 | var mutableOutArguments = new LinkedHashSet<Variable>(); | ||
38 | var parameters = target.getParameters(); | ||
39 | for (int i = 0; i < arity; i++) { | ||
40 | var argument = arguments.get(i); | ||
41 | var parameter = parameters.get(i); | ||
42 | if (!parameter.isAssignable(argument)) { | ||
43 | throw new InvalidQueryException("Argument %d of %s is not assignable to parameter %s" | ||
44 | .formatted(i, target, parameter)); | ||
45 | } | ||
46 | switch (parameter.getDirection()) { | ||
47 | case IN -> { | ||
48 | mutableOutArguments.remove(argument); | ||
49 | mutableInArguments.add(argument); | ||
50 | } | ||
51 | case OUT -> { | ||
52 | if (!mutableInArguments.contains(argument)) { | ||
53 | mutableOutArguments.add(argument); | ||
54 | } | ||
55 | } | ||
56 | } | ||
57 | } | ||
58 | inArguments = Collections.unmodifiableSet(mutableInArguments); | ||
59 | outArguments = Collections.unmodifiableSet(mutableOutArguments); | ||
60 | } | ||
61 | |||
62 | public Constraint getTarget() { | ||
63 | return target; | ||
64 | } | ||
65 | |||
66 | public List<Variable> getArguments() { | ||
67 | return arguments; | ||
68 | } | ||
69 | |||
70 | protected Set<Variable> getArgumentsOfDirection(ParameterDirection direction) { | ||
71 | return switch (direction) { | ||
72 | case IN -> inArguments; | ||
73 | case OUT -> outArguments; | ||
74 | }; | ||
75 | } | ||
76 | |||
77 | @Override | ||
78 | public Set<Variable> getInputVariables(Set<? extends Variable> positiveVariablesInClause) { | ||
79 | var inputVariables = new LinkedHashSet<>(getArgumentsOfDirection(ParameterDirection.OUT)); | ||
80 | inputVariables.retainAll(positiveVariablesInClause); | ||
81 | inputVariables.addAll(getArgumentsOfDirection(ParameterDirection.IN)); | ||
82 | return Collections.unmodifiableSet(inputVariables); | ||
83 | } | ||
84 | |||
85 | @Override | ||
86 | public Set<Variable> getPrivateVariables(Set<? extends Variable> positiveVariablesInClause) { | ||
87 | var privateVariables = new LinkedHashSet<>(getArgumentsOfDirection(ParameterDirection.OUT)); | ||
88 | privateVariables.removeAll(positiveVariablesInClause); | ||
89 | return Collections.unmodifiableSet(privateVariables); | ||
90 | } | ||
91 | |||
92 | @Override | ||
93 | public Literal substitute(Substitution substitution) { | ||
94 | var substitutedArguments = arguments.stream().map(substitution::getSubstitute).toList(); | ||
95 | return doSubstitute(substitution, substitutedArguments); | ||
96 | } | ||
97 | |||
98 | protected abstract Literal doSubstitute(Substitution substitution, List<Variable> substitutedArguments); | ||
99 | |||
100 | public AbstractCallLiteral withTarget(Constraint newTarget) { | ||
101 | if (Objects.equals(target, newTarget)) { | ||
102 | return this; | ||
103 | } | ||
104 | return withArguments(newTarget, arguments); | ||
105 | } | ||
106 | |||
107 | public abstract AbstractCallLiteral withArguments(Constraint newTarget, List<Variable> newArguments); | ||
108 | |||
109 | @Override | ||
110 | public boolean equalsWithSubstitution(LiteralEqualityHelper helper, Literal other) { | ||
111 | if (!super.equalsWithSubstitution(helper, other)) { | ||
112 | return false; | ||
113 | } | ||
114 | var otherCallLiteral = (AbstractCallLiteral) other; | ||
115 | var arity = arguments.size(); | ||
116 | if (arity != otherCallLiteral.arguments.size()) { | ||
117 | return false; | ||
118 | } | ||
119 | for (int i = 0; i < arity; i++) { | ||
120 | if (!helper.variableEqual(arguments.get(i), otherCallLiteral.arguments.get(i))) { | ||
121 | return false; | ||
122 | } | ||
123 | } | ||
124 | return target.equals(helper, otherCallLiteral.target); | ||
125 | } | ||
126 | |||
127 | @Override | ||
128 | public int hashCodeWithSubstitution(LiteralHashCodeHelper helper) { | ||
129 | int result = super.hashCodeWithSubstitution(helper) * 31 + target.hashCode(); | ||
130 | for (var argument : arguments) { | ||
131 | result = result * 31 + helper.getVariableHashCode(argument); | ||
132 | } | ||
133 | return result; | ||
134 | } | ||
135 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/AbstractCountLiteral.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/AbstractCountLiteral.java deleted file mode 100644 index 9bb572c0..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/AbstractCountLiteral.java +++ /dev/null | |||
@@ -1,107 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.literal; | ||
7 | |||
8 | import tools.refinery.store.query.Constraint; | ||
9 | import tools.refinery.store.query.InvalidQueryException; | ||
10 | import tools.refinery.store.query.equality.LiteralEqualityHelper; | ||
11 | import tools.refinery.store.query.equality.LiteralHashCodeHelper; | ||
12 | import tools.refinery.store.query.term.ConstantTerm; | ||
13 | import tools.refinery.store.query.term.DataVariable; | ||
14 | import tools.refinery.store.query.term.Variable; | ||
15 | |||
16 | import java.util.List; | ||
17 | import java.util.Objects; | ||
18 | import java.util.Set; | ||
19 | |||
20 | // {@link Object#equals(Object)} is implemented by {@link AbstractLiteral}. | ||
21 | @SuppressWarnings("squid:S2160") | ||
22 | public abstract class AbstractCountLiteral<T> extends AbstractCallLiteral { | ||
23 | private final Class<T> resultType; | ||
24 | private final DataVariable<T> resultVariable; | ||
25 | |||
26 | protected AbstractCountLiteral(Class<T> resultType, DataVariable<T> resultVariable, Constraint target, | ||
27 | List<Variable> arguments) { | ||
28 | super(target, arguments); | ||
29 | if (!resultVariable.getType().equals(resultType)) { | ||
30 | throw new InvalidQueryException("Count result variable %s must be of type %s, got %s instead".formatted( | ||
31 | resultVariable, resultType, resultVariable.getType().getName())); | ||
32 | } | ||
33 | if (arguments.contains(resultVariable)) { | ||
34 | throw new InvalidQueryException("Count result variable %s must not appear in the argument list" | ||
35 | .formatted(resultVariable)); | ||
36 | } | ||
37 | this.resultType = resultType; | ||
38 | this.resultVariable = resultVariable; | ||
39 | } | ||
40 | |||
41 | public Class<T> getResultType() { | ||
42 | return resultType; | ||
43 | } | ||
44 | |||
45 | public DataVariable<T> getResultVariable() { | ||
46 | return resultVariable; | ||
47 | } | ||
48 | |||
49 | @Override | ||
50 | public Set<Variable> getOutputVariables() { | ||
51 | return Set.of(resultVariable); | ||
52 | } | ||
53 | |||
54 | protected abstract T zero(); | ||
55 | |||
56 | protected abstract T one(); | ||
57 | |||
58 | @Override | ||
59 | public Literal reduce() { | ||
60 | var reduction = getTarget().getReduction(); | ||
61 | return switch (reduction) { | ||
62 | case ALWAYS_FALSE -> getResultVariable().assign(new ConstantTerm<>(resultType, zero())); | ||
63 | // The only way a constant {@code true} predicate can be called in a negative position is to have all of | ||
64 | // its arguments bound as input variables. Thus, there will only be a single match. | ||
65 | case ALWAYS_TRUE -> getResultVariable().assign(new ConstantTerm<>(resultType, one())); | ||
66 | case NOT_REDUCIBLE -> this; | ||
67 | }; | ||
68 | } | ||
69 | |||
70 | @Override | ||
71 | public boolean equalsWithSubstitution(LiteralEqualityHelper helper, Literal other) { | ||
72 | if (!super.equalsWithSubstitution(helper, other)) { | ||
73 | return false; | ||
74 | } | ||
75 | var otherCountLiteral = (AbstractCountLiteral<?>) other; | ||
76 | return Objects.equals(resultType, otherCountLiteral.resultType) && | ||
77 | helper.variableEqual(resultVariable, otherCountLiteral.resultVariable); | ||
78 | } | ||
79 | |||
80 | @Override | ||
81 | public int hashCodeWithSubstitution(LiteralHashCodeHelper helper) { | ||
82 | return Objects.hash(super.hashCodeWithSubstitution(helper), resultType, | ||
83 | helper.getVariableHashCode(resultVariable)); | ||
84 | } | ||
85 | |||
86 | protected abstract String operatorName(); | ||
87 | |||
88 | @Override | ||
89 | public String toString() { | ||
90 | var builder = new StringBuilder(); | ||
91 | builder.append(resultVariable); | ||
92 | builder.append(" is "); | ||
93 | builder.append(operatorName()); | ||
94 | builder.append(' '); | ||
95 | builder.append(getTarget().toReferenceString()); | ||
96 | builder.append('('); | ||
97 | var argumentIterator = getArguments().iterator(); | ||
98 | if (argumentIterator.hasNext()) { | ||
99 | builder.append(argumentIterator.next()); | ||
100 | while (argumentIterator.hasNext()) { | ||
101 | builder.append(", ").append(argumentIterator.next()); | ||
102 | } | ||
103 | } | ||
104 | builder.append(')'); | ||
105 | return builder.toString(); | ||
106 | } | ||
107 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/AbstractLiteral.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/AbstractLiteral.java deleted file mode 100644 index 7d3cabd7..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/AbstractLiteral.java +++ /dev/null | |||
@@ -1,34 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.literal; | ||
7 | |||
8 | import tools.refinery.store.query.equality.LiteralEqualityHelper; | ||
9 | import tools.refinery.store.query.equality.LiteralHashCodeHelper; | ||
10 | |||
11 | public abstract class AbstractLiteral implements Literal { | ||
12 | @Override | ||
13 | public boolean equalsWithSubstitution(LiteralEqualityHelper helper, Literal other) { | ||
14 | return other != null && getClass() == other.getClass(); | ||
15 | } | ||
16 | |||
17 | @Override | ||
18 | public int hashCodeWithSubstitution(LiteralHashCodeHelper helper) { | ||
19 | return getClass().hashCode(); | ||
20 | } | ||
21 | |||
22 | @Override | ||
23 | public boolean equals(Object o) { | ||
24 | if (this == o) return true; | ||
25 | if (o == null || getClass() != o.getClass()) return false; | ||
26 | AbstractLiteral that = (AbstractLiteral) o; | ||
27 | return equalsWithSubstitution(LiteralEqualityHelper.DEFAULT, that); | ||
28 | } | ||
29 | |||
30 | @Override | ||
31 | public int hashCode() { | ||
32 | return hashCodeWithSubstitution(LiteralHashCodeHelper.DEFAULT); | ||
33 | } | ||
34 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/AggregationLiteral.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/AggregationLiteral.java deleted file mode 100644 index e3acfacc..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/AggregationLiteral.java +++ /dev/null | |||
@@ -1,138 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.literal; | ||
7 | |||
8 | import tools.refinery.store.query.Constraint; | ||
9 | import tools.refinery.store.query.InvalidQueryException; | ||
10 | import tools.refinery.store.query.equality.LiteralEqualityHelper; | ||
11 | import tools.refinery.store.query.equality.LiteralHashCodeHelper; | ||
12 | import tools.refinery.store.query.substitution.Substitution; | ||
13 | import tools.refinery.store.query.term.*; | ||
14 | |||
15 | import java.util.List; | ||
16 | import java.util.Objects; | ||
17 | import java.util.Set; | ||
18 | |||
19 | // {@link Object#equals(Object)} is implemented by {@link AbstractLiteral}. | ||
20 | @SuppressWarnings("squid:S2160") | ||
21 | public class AggregationLiteral<R, T> extends AbstractCallLiteral { | ||
22 | private final DataVariable<R> resultVariable; | ||
23 | private final DataVariable<T> inputVariable; | ||
24 | private final Aggregator<R, T> aggregator; | ||
25 | |||
26 | public AggregationLiteral(DataVariable<R> resultVariable, Aggregator<R, T> aggregator, | ||
27 | DataVariable<T> inputVariable, Constraint target, List<Variable> arguments) { | ||
28 | super(target, arguments); | ||
29 | if (!inputVariable.getType().equals(aggregator.getInputType())) { | ||
30 | throw new InvalidQueryException("Input variable %s must of type %s, got %s instead".formatted( | ||
31 | inputVariable, aggregator.getInputType().getName(), inputVariable.getType().getName())); | ||
32 | } | ||
33 | if (!getArgumentsOfDirection(ParameterDirection.OUT).contains(inputVariable)) { | ||
34 | throw new InvalidQueryException("Input variable %s must be bound with direction %s in the argument list" | ||
35 | .formatted(inputVariable, ParameterDirection.OUT)); | ||
36 | } | ||
37 | if (!resultVariable.getType().equals(aggregator.getResultType())) { | ||
38 | throw new InvalidQueryException("Result variable %s must of type %s, got %s instead".formatted( | ||
39 | resultVariable, aggregator.getResultType().getName(), resultVariable.getType().getName())); | ||
40 | } | ||
41 | if (arguments.contains(resultVariable)) { | ||
42 | throw new InvalidQueryException("Result variable %s must not appear in the argument list".formatted( | ||
43 | resultVariable)); | ||
44 | } | ||
45 | this.resultVariable = resultVariable; | ||
46 | this.inputVariable = inputVariable; | ||
47 | this.aggregator = aggregator; | ||
48 | } | ||
49 | |||
50 | public DataVariable<R> getResultVariable() { | ||
51 | return resultVariable; | ||
52 | } | ||
53 | |||
54 | public DataVariable<T> getInputVariable() { | ||
55 | return inputVariable; | ||
56 | } | ||
57 | |||
58 | public Aggregator<R, T> getAggregator() { | ||
59 | return aggregator; | ||
60 | } | ||
61 | |||
62 | @Override | ||
63 | public Set<Variable> getOutputVariables() { | ||
64 | return Set.of(resultVariable); | ||
65 | } | ||
66 | |||
67 | @Override | ||
68 | public Set<Variable> getInputVariables(Set<? extends Variable> positiveVariablesInClause) { | ||
69 | if (positiveVariablesInClause.contains(inputVariable)) { | ||
70 | throw new InvalidQueryException("Aggregation variable %s must not be bound".formatted(inputVariable)); | ||
71 | } | ||
72 | return super.getInputVariables(positiveVariablesInClause); | ||
73 | } | ||
74 | |||
75 | @Override | ||
76 | public Literal reduce() { | ||
77 | var reduction = getTarget().getReduction(); | ||
78 | return switch (reduction) { | ||
79 | case ALWAYS_FALSE -> { | ||
80 | var emptyValue = aggregator.getEmptyResult(); | ||
81 | yield emptyValue == null ? BooleanLiteral.FALSE : | ||
82 | resultVariable.assign(new ConstantTerm<>(resultVariable.getType(), emptyValue)); | ||
83 | } | ||
84 | case ALWAYS_TRUE -> throw new InvalidQueryException("Trying to aggregate over an infinite set"); | ||
85 | case NOT_REDUCIBLE -> this; | ||
86 | }; | ||
87 | } | ||
88 | |||
89 | @Override | ||
90 | protected Literal doSubstitute(Substitution substitution, List<Variable> substitutedArguments) { | ||
91 | return new AggregationLiteral<>(substitution.getTypeSafeSubstitute(resultVariable), aggregator, | ||
92 | substitution.getTypeSafeSubstitute(inputVariable), getTarget(), substitutedArguments); | ||
93 | } | ||
94 | |||
95 | @Override | ||
96 | public AbstractCallLiteral withArguments(Constraint newTarget, List<Variable> newArguments) { | ||
97 | return new AggregationLiteral<>(resultVariable, aggregator, inputVariable, newTarget, newArguments); | ||
98 | } | ||
99 | |||
100 | @Override | ||
101 | public boolean equalsWithSubstitution(LiteralEqualityHelper helper, Literal other) { | ||
102 | if (!super.equalsWithSubstitution(helper, other)) { | ||
103 | return false; | ||
104 | } | ||
105 | var otherAggregationLiteral = (AggregationLiteral<?, ?>) other; | ||
106 | return helper.variableEqual(resultVariable, otherAggregationLiteral.resultVariable) && | ||
107 | aggregator.equals(otherAggregationLiteral.aggregator) && | ||
108 | helper.variableEqual(inputVariable, otherAggregationLiteral.inputVariable); | ||
109 | } | ||
110 | |||
111 | @Override | ||
112 | public int hashCodeWithSubstitution(LiteralHashCodeHelper helper) { | ||
113 | return Objects.hash(super.hashCodeWithSubstitution(helper), helper.getVariableHashCode(resultVariable), | ||
114 | helper.getVariableHashCode(inputVariable), aggregator); | ||
115 | } | ||
116 | |||
117 | @Override | ||
118 | public String toString() { | ||
119 | var builder = new StringBuilder(); | ||
120 | builder.append(resultVariable); | ||
121 | builder.append(" is "); | ||
122 | builder.append(getTarget().toReferenceString()); | ||
123 | builder.append("("); | ||
124 | var argumentIterator = getArguments().iterator(); | ||
125 | if (argumentIterator.hasNext()) { | ||
126 | var argument = argumentIterator.next(); | ||
127 | if (inputVariable.equals(argument)) { | ||
128 | builder.append("@Aggregate(\"").append(aggregator).append("\") "); | ||
129 | } | ||
130 | builder.append(argument); | ||
131 | while (argumentIterator.hasNext()) { | ||
132 | builder.append(", ").append(argumentIterator.next()); | ||
133 | } | ||
134 | } | ||
135 | builder.append(")"); | ||
136 | return builder.toString(); | ||
137 | } | ||
138 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/AssignLiteral.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/AssignLiteral.java deleted file mode 100644 index dadf487f..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/AssignLiteral.java +++ /dev/null | |||
@@ -1,88 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.literal; | ||
7 | |||
8 | import tools.refinery.store.query.InvalidQueryException; | ||
9 | import tools.refinery.store.query.equality.LiteralEqualityHelper; | ||
10 | import tools.refinery.store.query.equality.LiteralHashCodeHelper; | ||
11 | import tools.refinery.store.query.substitution.Substitution; | ||
12 | import tools.refinery.store.query.term.DataVariable; | ||
13 | import tools.refinery.store.query.term.Term; | ||
14 | import tools.refinery.store.query.term.Variable; | ||
15 | |||
16 | import java.util.Collections; | ||
17 | import java.util.Objects; | ||
18 | import java.util.Set; | ||
19 | |||
20 | // {@link Object#equals(Object)} is implemented by {@link AbstractLiteral}. | ||
21 | @SuppressWarnings("squid:S2160") | ||
22 | public class AssignLiteral<T> extends AbstractLiteral { | ||
23 | private final DataVariable<T> variable; | ||
24 | private final Term<T> term; | ||
25 | |||
26 | public AssignLiteral(DataVariable<T> variable, Term<T> term) { | ||
27 | if (!term.getType().equals(variable.getType())) { | ||
28 | throw new InvalidQueryException("Term %s must be of type %s, got %s instead".formatted( | ||
29 | term, variable.getType().getName(), term.getType().getName())); | ||
30 | } | ||
31 | var inputVariables = term.getInputVariables(); | ||
32 | if (inputVariables.contains(variable)) { | ||
33 | throw new InvalidQueryException("Result variable %s must not appear in the term %s".formatted( | ||
34 | variable, term)); | ||
35 | } | ||
36 | this.variable = variable; | ||
37 | this.term = term; | ||
38 | } | ||
39 | |||
40 | public DataVariable<T> getVariable() { | ||
41 | return variable; | ||
42 | } | ||
43 | |||
44 | public Term<T> getTerm() { | ||
45 | return term; | ||
46 | } | ||
47 | |||
48 | @Override | ||
49 | public Set<Variable> getOutputVariables() { | ||
50 | return Set.of(variable); | ||
51 | } | ||
52 | |||
53 | @Override | ||
54 | public Set<Variable> getInputVariables(Set<? extends Variable> positiveVariablesInClause) { | ||
55 | return Collections.unmodifiableSet(term.getInputVariables()); | ||
56 | } | ||
57 | |||
58 | @Override | ||
59 | public Set<Variable> getPrivateVariables(Set<? extends Variable> positiveVariablesInClause) { | ||
60 | return Set.of(); | ||
61 | } | ||
62 | |||
63 | @Override | ||
64 | public Literal substitute(Substitution substitution) { | ||
65 | return new AssignLiteral<>(substitution.getTypeSafeSubstitute(variable), term.substitute(substitution)); | ||
66 | } | ||
67 | |||
68 | @Override | ||
69 | public boolean equalsWithSubstitution(LiteralEqualityHelper helper, Literal other) { | ||
70 | if (other == null || getClass() != other.getClass()) { | ||
71 | return false; | ||
72 | } | ||
73 | var otherAssignLiteral = (AssignLiteral<?>) other; | ||
74 | return helper.variableEqual(variable, otherAssignLiteral.variable) && | ||
75 | term.equalsWithSubstitution(helper, otherAssignLiteral.term); | ||
76 | } | ||
77 | |||
78 | @Override | ||
79 | public int hashCodeWithSubstitution(LiteralHashCodeHelper helper) { | ||
80 | return Objects.hash(super.hashCodeWithSubstitution(helper), helper.getVariableHashCode(variable), | ||
81 | term.hashCodeWithSubstitution(helper)); | ||
82 | } | ||
83 | |||
84 | @Override | ||
85 | public String toString() { | ||
86 | return "%s is (%s)".formatted(variable, term); | ||
87 | } | ||
88 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/BooleanLiteral.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/BooleanLiteral.java deleted file mode 100644 index 6cd320da..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/BooleanLiteral.java +++ /dev/null | |||
@@ -1,69 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.literal; | ||
7 | |||
8 | import tools.refinery.store.query.equality.LiteralEqualityHelper; | ||
9 | import tools.refinery.store.query.equality.LiteralHashCodeHelper; | ||
10 | import tools.refinery.store.query.substitution.Substitution; | ||
11 | import tools.refinery.store.query.term.Variable; | ||
12 | |||
13 | import java.util.Set; | ||
14 | |||
15 | public enum BooleanLiteral implements CanNegate<BooleanLiteral> { | ||
16 | TRUE(true), | ||
17 | FALSE(false); | ||
18 | |||
19 | private final boolean value; | ||
20 | |||
21 | BooleanLiteral(boolean value) { | ||
22 | this.value = value; | ||
23 | } | ||
24 | |||
25 | @Override | ||
26 | public Set<Variable> getOutputVariables() { | ||
27 | return Set.of(); | ||
28 | } | ||
29 | |||
30 | @Override | ||
31 | public Set<Variable> getInputVariables(Set<? extends Variable> positiveVariablesInClause) { | ||
32 | return Set.of(); | ||
33 | } | ||
34 | |||
35 | @Override | ||
36 | public Set<Variable> getPrivateVariables(Set<? extends Variable> positiveVariablesInClause) { | ||
37 | return Set.of(); | ||
38 | } | ||
39 | |||
40 | @Override | ||
41 | public Literal substitute(Substitution substitution) { | ||
42 | // No variables to substitute. | ||
43 | return this; | ||
44 | } | ||
45 | |||
46 | @Override | ||
47 | public BooleanLiteral negate() { | ||
48 | return fromBoolean(!value); | ||
49 | } | ||
50 | |||
51 | @Override | ||
52 | public boolean equalsWithSubstitution(LiteralEqualityHelper helper, Literal other) { | ||
53 | return equals(other); | ||
54 | } | ||
55 | |||
56 | @Override | ||
57 | public int hashCodeWithSubstitution(LiteralHashCodeHelper helper) { | ||
58 | return hashCode(); | ||
59 | } | ||
60 | |||
61 | @Override | ||
62 | public String toString() { | ||
63 | return Boolean.toString(value); | ||
64 | } | ||
65 | |||
66 | public static BooleanLiteral fromBoolean(boolean value) { | ||
67 | return value ? TRUE : FALSE; | ||
68 | } | ||
69 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/CallLiteral.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/CallLiteral.java deleted file mode 100644 index 2d0e4e97..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/CallLiteral.java +++ /dev/null | |||
@@ -1,134 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.literal; | ||
7 | |||
8 | import tools.refinery.store.query.Constraint; | ||
9 | import tools.refinery.store.query.InvalidQueryException; | ||
10 | import tools.refinery.store.query.equality.LiteralEqualityHelper; | ||
11 | import tools.refinery.store.query.equality.LiteralHashCodeHelper; | ||
12 | import tools.refinery.store.query.substitution.Substitution; | ||
13 | import tools.refinery.store.query.term.ParameterDirection; | ||
14 | import tools.refinery.store.query.term.Variable; | ||
15 | |||
16 | import java.util.*; | ||
17 | |||
18 | // {@link Object#equals(Object)} is implemented by {@link AbstractLiteral}. | ||
19 | @SuppressWarnings("squid:S2160") | ||
20 | public final class CallLiteral extends AbstractCallLiteral implements CanNegate<CallLiteral> { | ||
21 | private final CallPolarity polarity; | ||
22 | |||
23 | public CallLiteral(CallPolarity polarity, Constraint target, List<Variable> arguments) { | ||
24 | super(target, arguments); | ||
25 | var parameters = target.getParameters(); | ||
26 | int arity = target.arity(); | ||
27 | if (polarity.isTransitive()) { | ||
28 | if (arity != 2) { | ||
29 | throw new InvalidQueryException("Transitive closures can only take binary relations"); | ||
30 | } | ||
31 | if (parameters.get(0).isDataVariable() || parameters.get(1).isDataVariable()) { | ||
32 | throw new InvalidQueryException("Transitive closures can only be computed over nodes"); | ||
33 | } | ||
34 | if (parameters.get(0).getDirection() != ParameterDirection.OUT || | ||
35 | parameters.get(1).getDirection() != ParameterDirection.OUT) { | ||
36 | throw new InvalidQueryException("Transitive closures cannot take input parameters"); | ||
37 | } | ||
38 | } | ||
39 | this.polarity = polarity; | ||
40 | } | ||
41 | |||
42 | public CallPolarity getPolarity() { | ||
43 | return polarity; | ||
44 | } | ||
45 | |||
46 | @Override | ||
47 | protected Literal doSubstitute(Substitution substitution, List<Variable> substitutedArguments) { | ||
48 | return new CallLiteral(polarity, getTarget(), substitutedArguments); | ||
49 | } | ||
50 | |||
51 | @Override | ||
52 | public Set<Variable> getOutputVariables() { | ||
53 | if (polarity.isPositive()) { | ||
54 | return getArgumentsOfDirection(ParameterDirection.OUT); | ||
55 | } | ||
56 | return Set.of(); | ||
57 | } | ||
58 | |||
59 | @Override | ||
60 | public Set<Variable> getInputVariables(Set<? extends Variable> positiveVariablesInClause) { | ||
61 | if (polarity.isPositive()) { | ||
62 | return getArgumentsOfDirection(ParameterDirection.IN); | ||
63 | } | ||
64 | return super.getInputVariables(positiveVariablesInClause); | ||
65 | } | ||
66 | |||
67 | @Override | ||
68 | public Set<Variable> getPrivateVariables(Set<? extends Variable> positiveVariablesInClause) { | ||
69 | if (polarity.isPositive()) { | ||
70 | return Set.of(); | ||
71 | } | ||
72 | return super.getPrivateVariables(positiveVariablesInClause); | ||
73 | } | ||
74 | |||
75 | @Override | ||
76 | public Literal reduce() { | ||
77 | var reduction = getTarget().getReduction(); | ||
78 | var negatedReduction = polarity.isPositive() ? reduction : reduction.negate(); | ||
79 | return switch (negatedReduction) { | ||
80 | case ALWAYS_TRUE -> BooleanLiteral.TRUE; | ||
81 | case ALWAYS_FALSE -> BooleanLiteral.FALSE; | ||
82 | default -> this; | ||
83 | }; | ||
84 | } | ||
85 | |||
86 | @Override | ||
87 | public boolean equalsWithSubstitution(LiteralEqualityHelper helper, Literal other) { | ||
88 | if (!super.equalsWithSubstitution(helper, other)) { | ||
89 | return false; | ||
90 | } | ||
91 | var otherCallLiteral = (CallLiteral) other; | ||
92 | return polarity.equals(otherCallLiteral.polarity); | ||
93 | } | ||
94 | |||
95 | @Override | ||
96 | public int hashCodeWithSubstitution(LiteralHashCodeHelper helper) { | ||
97 | return Objects.hash(super.hashCodeWithSubstitution(helper), polarity); | ||
98 | } | ||
99 | |||
100 | @Override | ||
101 | public CallLiteral negate() { | ||
102 | return new CallLiteral(polarity.negate(), getTarget(), getArguments()); | ||
103 | } | ||
104 | |||
105 | @Override | ||
106 | public AbstractCallLiteral withArguments(Constraint newTarget, List<Variable> newArguments) { | ||
107 | return new CallLiteral(polarity, newTarget, newArguments); | ||
108 | } | ||
109 | |||
110 | @Override | ||
111 | public String toString() { | ||
112 | var builder = new StringBuilder(); | ||
113 | if (!polarity.isPositive()) { | ||
114 | builder.append("!("); | ||
115 | } | ||
116 | builder.append(getTarget().toReferenceString()); | ||
117 | if (polarity.isTransitive()) { | ||
118 | builder.append("+"); | ||
119 | } | ||
120 | builder.append("("); | ||
121 | var argumentIterator = getArguments().iterator(); | ||
122 | if (argumentIterator.hasNext()) { | ||
123 | builder.append(argumentIterator.next()); | ||
124 | while (argumentIterator.hasNext()) { | ||
125 | builder.append(", ").append(argumentIterator.next()); | ||
126 | } | ||
127 | } | ||
128 | builder.append(")"); | ||
129 | if (!polarity.isPositive()) { | ||
130 | builder.append(")"); | ||
131 | } | ||
132 | return builder.toString(); | ||
133 | } | ||
134 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/CallPolarity.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/CallPolarity.java deleted file mode 100644 index 716c7109..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/CallPolarity.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 | */ | ||
6 | package tools.refinery.store.query.literal; | ||
7 | |||
8 | import tools.refinery.store.query.InvalidQueryException; | ||
9 | |||
10 | public enum CallPolarity { | ||
11 | POSITIVE(true, false), | ||
12 | NEGATIVE(false, false), | ||
13 | TRANSITIVE(true, true); | ||
14 | |||
15 | private final boolean positive; | ||
16 | |||
17 | private final boolean transitive; | ||
18 | |||
19 | CallPolarity(boolean positive, boolean transitive) { | ||
20 | this.positive = positive; | ||
21 | this.transitive = transitive; | ||
22 | } | ||
23 | |||
24 | public boolean isPositive() { | ||
25 | return positive; | ||
26 | } | ||
27 | |||
28 | public boolean isTransitive() { | ||
29 | return transitive; | ||
30 | } | ||
31 | |||
32 | public CallPolarity negate() { | ||
33 | return switch (this) { | ||
34 | case POSITIVE -> NEGATIVE; | ||
35 | case NEGATIVE -> POSITIVE; | ||
36 | case TRANSITIVE -> throw new InvalidQueryException("Transitive polarity cannot be negated"); | ||
37 | }; | ||
38 | } | ||
39 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/CanNegate.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/CanNegate.java deleted file mode 100644 index 35dcb3fb..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/CanNegate.java +++ /dev/null | |||
@@ -1,10 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.literal; | ||
7 | |||
8 | public interface CanNegate<T extends CanNegate<T>> extends Literal { | ||
9 | T negate(); | ||
10 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/CheckLiteral.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/CheckLiteral.java deleted file mode 100644 index dfedd2cb..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/CheckLiteral.java +++ /dev/null | |||
@@ -1,95 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.literal; | ||
7 | |||
8 | import tools.refinery.store.query.InvalidQueryException; | ||
9 | import tools.refinery.store.query.equality.LiteralEqualityHelper; | ||
10 | import tools.refinery.store.query.equality.LiteralHashCodeHelper; | ||
11 | import tools.refinery.store.query.substitution.Substitution; | ||
12 | import tools.refinery.store.query.term.ConstantTerm; | ||
13 | import tools.refinery.store.query.term.Term; | ||
14 | import tools.refinery.store.query.term.Variable; | ||
15 | import tools.refinery.store.query.term.bool.BoolNotTerm; | ||
16 | import tools.refinery.store.query.term.bool.BoolTerms; | ||
17 | |||
18 | import java.util.Collections; | ||
19 | import java.util.Objects; | ||
20 | import java.util.Set; | ||
21 | |||
22 | // {@link Object#equals(Object)} is implemented by {@link AbstractLiteral}. | ||
23 | @SuppressWarnings("squid:S2160") | ||
24 | public class CheckLiteral extends AbstractLiteral implements CanNegate<CheckLiteral> { | ||
25 | private final Term<Boolean> term; | ||
26 | |||
27 | public CheckLiteral(Term<Boolean> term) { | ||
28 | if (!term.getType().equals(Boolean.class)) { | ||
29 | throw new InvalidQueryException("Term %s must be of type %s, got %s instead".formatted( | ||
30 | term, Boolean.class.getName(), term.getType().getName())); | ||
31 | } | ||
32 | this.term = term; | ||
33 | } | ||
34 | |||
35 | public Term<Boolean> getTerm() { | ||
36 | return term; | ||
37 | } | ||
38 | |||
39 | @Override | ||
40 | public Set<Variable> getOutputVariables() { | ||
41 | return Set.of(); | ||
42 | } | ||
43 | |||
44 | @Override | ||
45 | public Set<Variable> getInputVariables(Set<? extends Variable> positiveVariablesInClause) { | ||
46 | return Collections.unmodifiableSet(term.getInputVariables()); | ||
47 | } | ||
48 | |||
49 | @Override | ||
50 | public Set<Variable> getPrivateVariables(Set<? extends Variable> positiveVariablesInClause) { | ||
51 | return Set.of(); | ||
52 | } | ||
53 | |||
54 | @Override | ||
55 | public Literal substitute(Substitution substitution) { | ||
56 | return new CheckLiteral(term.substitute(substitution)); | ||
57 | } | ||
58 | |||
59 | @Override | ||
60 | public CheckLiteral negate() { | ||
61 | if (term instanceof BoolNotTerm notTerm) { | ||
62 | return new CheckLiteral(notTerm.getBody()); | ||
63 | } | ||
64 | return new CheckLiteral(BoolTerms.not(term)); | ||
65 | } | ||
66 | |||
67 | @Override | ||
68 | public boolean equalsWithSubstitution(LiteralEqualityHelper helper, Literal other) { | ||
69 | if (other == null || getClass() != other.getClass()) { | ||
70 | return false; | ||
71 | } | ||
72 | var otherAssumeLiteral = (CheckLiteral) other; | ||
73 | return term.equalsWithSubstitution(helper, otherAssumeLiteral.term); | ||
74 | } | ||
75 | |||
76 | @Override | ||
77 | public int hashCodeWithSubstitution(LiteralHashCodeHelper helper) { | ||
78 | return Objects.hash(super.hashCodeWithSubstitution(helper), term.hashCodeWithSubstitution(helper)); | ||
79 | } | ||
80 | |||
81 | @Override | ||
82 | public Literal reduce() { | ||
83 | if (term instanceof ConstantTerm<Boolean> constantTerm) { | ||
84 | // Return {@link BooleanLiteral#FALSE} for {@code false} or {@code null} literals. | ||
85 | return Boolean.TRUE.equals(constantTerm.getValue()) ? BooleanLiteral.TRUE : | ||
86 | BooleanLiteral.FALSE; | ||
87 | } | ||
88 | return this; | ||
89 | } | ||
90 | |||
91 | @Override | ||
92 | public String toString() { | ||
93 | return "(%s)".formatted(term); | ||
94 | } | ||
95 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/Connectivity.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/Connectivity.java deleted file mode 100644 index a058094d..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/Connectivity.java +++ /dev/null | |||
@@ -1,18 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.literal; | ||
7 | |||
8 | import java.util.Locale; | ||
9 | |||
10 | public enum Connectivity { | ||
11 | WEAK, | ||
12 | STRONG; | ||
13 | |||
14 | @Override | ||
15 | public String toString() { | ||
16 | return name().toLowerCase(Locale.ROOT); | ||
17 | } | ||
18 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/ConstantLiteral.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/ConstantLiteral.java deleted file mode 100644 index d83bd584..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/ConstantLiteral.java +++ /dev/null | |||
@@ -1,73 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.literal; | ||
7 | |||
8 | import tools.refinery.store.query.equality.LiteralEqualityHelper; | ||
9 | import tools.refinery.store.query.equality.LiteralHashCodeHelper; | ||
10 | import tools.refinery.store.query.substitution.Substitution; | ||
11 | import tools.refinery.store.query.term.NodeVariable; | ||
12 | import tools.refinery.store.query.term.Variable; | ||
13 | |||
14 | import java.util.Objects; | ||
15 | import java.util.Set; | ||
16 | |||
17 | public class ConstantLiteral extends AbstractLiteral { | ||
18 | private final NodeVariable variable; | ||
19 | private final int nodeId; | ||
20 | |||
21 | public ConstantLiteral(NodeVariable variable, int nodeId) { | ||
22 | this.variable = variable; | ||
23 | this.nodeId = nodeId; | ||
24 | } | ||
25 | |||
26 | public NodeVariable getVariable() { | ||
27 | return variable; | ||
28 | } | ||
29 | |||
30 | public int getNodeId() { | ||
31 | return nodeId; | ||
32 | } | ||
33 | |||
34 | |||
35 | @Override | ||
36 | public Set<Variable> getOutputVariables() { | ||
37 | return Set.of(variable); | ||
38 | } | ||
39 | |||
40 | @Override | ||
41 | public Set<Variable> getInputVariables(Set<? extends Variable> positiveVariablesInClause) { | ||
42 | return Set.of(); | ||
43 | } | ||
44 | |||
45 | @Override | ||
46 | public Set<Variable> getPrivateVariables(Set<? extends Variable> positiveVariablesInClause) { | ||
47 | return Set.of(); | ||
48 | } | ||
49 | |||
50 | @Override | ||
51 | public ConstantLiteral substitute(Substitution substitution) { | ||
52 | return new ConstantLiteral(substitution.getTypeSafeSubstitute(variable), nodeId); | ||
53 | } | ||
54 | |||
55 | @Override | ||
56 | public boolean equalsWithSubstitution(LiteralEqualityHelper helper, Literal other) { | ||
57 | if (other.getClass() != getClass()) { | ||
58 | return false; | ||
59 | } | ||
60 | var otherConstantLiteral = (ConstantLiteral) other; | ||
61 | return helper.variableEqual(variable, otherConstantLiteral.variable) && nodeId == otherConstantLiteral.nodeId; | ||
62 | } | ||
63 | |||
64 | @Override | ||
65 | public int hashCodeWithSubstitution(LiteralHashCodeHelper helper) { | ||
66 | return Objects.hash(super.hashCodeWithSubstitution(helper), helper.getVariableHashCode(variable), nodeId); | ||
67 | } | ||
68 | |||
69 | @Override | ||
70 | public String toString() { | ||
71 | return "%s === @Constant %d".formatted(variable, nodeId); | ||
72 | } | ||
73 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/CountLiteral.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/CountLiteral.java deleted file mode 100644 index 3d078d89..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/CountLiteral.java +++ /dev/null | |||
@@ -1,45 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.literal; | ||
7 | |||
8 | import tools.refinery.store.query.Constraint; | ||
9 | import tools.refinery.store.query.substitution.Substitution; | ||
10 | import tools.refinery.store.query.term.DataVariable; | ||
11 | import tools.refinery.store.query.term.Variable; | ||
12 | |||
13 | import java.util.List; | ||
14 | |||
15 | public class CountLiteral extends AbstractCountLiteral<Integer> { | ||
16 | public CountLiteral(DataVariable<Integer> resultVariable, Constraint target, List<Variable> arguments) { | ||
17 | super(Integer.class, resultVariable, target, arguments); | ||
18 | } | ||
19 | |||
20 | @Override | ||
21 | protected Integer zero() { | ||
22 | return 0; | ||
23 | } | ||
24 | |||
25 | @Override | ||
26 | protected Integer one() { | ||
27 | return 1; | ||
28 | } | ||
29 | |||
30 | @Override | ||
31 | protected Literal doSubstitute(Substitution substitution, List<Variable> substitutedArguments) { | ||
32 | return new CountLiteral(substitution.getTypeSafeSubstitute(getResultVariable()), getTarget(), | ||
33 | substitutedArguments); | ||
34 | } | ||
35 | |||
36 | @Override | ||
37 | public AbstractCallLiteral withArguments(Constraint newTarget, List<Variable> newArguments) { | ||
38 | return new CountLiteral(getResultVariable(), newTarget, newArguments); | ||
39 | } | ||
40 | |||
41 | @Override | ||
42 | protected String operatorName() { | ||
43 | return "count"; | ||
44 | } | ||
45 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/EquivalenceLiteral.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/EquivalenceLiteral.java deleted file mode 100644 index 7343f709..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/EquivalenceLiteral.java +++ /dev/null | |||
@@ -1,100 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.literal; | ||
7 | |||
8 | import tools.refinery.store.query.InvalidQueryException; | ||
9 | import tools.refinery.store.query.equality.LiteralEqualityHelper; | ||
10 | import tools.refinery.store.query.equality.LiteralHashCodeHelper; | ||
11 | import tools.refinery.store.query.substitution.Substitution; | ||
12 | import tools.refinery.store.query.term.Variable; | ||
13 | |||
14 | import java.util.Objects; | ||
15 | import java.util.Set; | ||
16 | |||
17 | // {@link Object#equals(Object)} is implemented by {@link AbstractLiteral}. | ||
18 | @SuppressWarnings("squid:S2160") | ||
19 | public final class EquivalenceLiteral extends AbstractLiteral implements CanNegate<EquivalenceLiteral> { | ||
20 | private final boolean positive; | ||
21 | private final Variable left; | ||
22 | private final Variable right; | ||
23 | |||
24 | public EquivalenceLiteral(boolean positive, Variable left, Variable right) { | ||
25 | if (!left.tryGetType().equals(right.tryGetType())) { | ||
26 | throw new InvalidQueryException("Variables %s and %s of different type cannot be equivalent" | ||
27 | .formatted(left, right)); | ||
28 | } | ||
29 | this.positive = positive; | ||
30 | this.left = left; | ||
31 | this.right = right; | ||
32 | } | ||
33 | |||
34 | public boolean isPositive() { | ||
35 | return positive; | ||
36 | } | ||
37 | |||
38 | public Variable getLeft() { | ||
39 | return left; | ||
40 | } | ||
41 | |||
42 | public Variable getRight() { | ||
43 | return right; | ||
44 | } | ||
45 | |||
46 | @Override | ||
47 | public Set<Variable> getOutputVariables() { | ||
48 | return Set.of(left); | ||
49 | } | ||
50 | |||
51 | @Override | ||
52 | public Set<Variable> getInputVariables(Set<? extends Variable> positiveVariablesInClause) { | ||
53 | return Set.of(right); | ||
54 | } | ||
55 | |||
56 | @Override | ||
57 | public Set<Variable> getPrivateVariables(Set<? extends Variable> positiveVariablesInClause) { | ||
58 | return Set.of(); | ||
59 | } | ||
60 | |||
61 | @Override | ||
62 | public EquivalenceLiteral negate() { | ||
63 | return new EquivalenceLiteral(!positive, left, right); | ||
64 | } | ||
65 | |||
66 | @Override | ||
67 | public EquivalenceLiteral substitute(Substitution substitution) { | ||
68 | return new EquivalenceLiteral(positive, substitution.getSubstitute(left), | ||
69 | substitution.getSubstitute(right)); | ||
70 | } | ||
71 | |||
72 | @Override | ||
73 | public Literal reduce() { | ||
74 | if (left.equals(right)) { | ||
75 | return positive ? BooleanLiteral.TRUE : BooleanLiteral.FALSE; | ||
76 | } | ||
77 | return this; | ||
78 | } | ||
79 | |||
80 | @Override | ||
81 | public boolean equalsWithSubstitution(LiteralEqualityHelper helper, Literal other) { | ||
82 | if (other.getClass() != getClass()) { | ||
83 | return false; | ||
84 | } | ||
85 | var otherEquivalenceLiteral = (EquivalenceLiteral) other; | ||
86 | return helper.variableEqual(left, otherEquivalenceLiteral.left) && | ||
87 | helper.variableEqual(right, otherEquivalenceLiteral.right); | ||
88 | } | ||
89 | |||
90 | @Override | ||
91 | public int hashCodeWithSubstitution(LiteralHashCodeHelper helper) { | ||
92 | return Objects.hash(super.hashCodeWithSubstitution(helper), helper.getVariableHashCode(left), | ||
93 | helper.getVariableHashCode(right)); | ||
94 | } | ||
95 | |||
96 | @Override | ||
97 | public String toString() { | ||
98 | return "%s %s %s".formatted(left, positive ? "===" : "!==", right); | ||
99 | } | ||
100 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/Literal.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/Literal.java deleted file mode 100644 index cb16ab00..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/Literal.java +++ /dev/null | |||
@@ -1,32 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.literal; | ||
7 | |||
8 | import tools.refinery.store.query.equality.LiteralEqualityHelper; | ||
9 | import tools.refinery.store.query.equality.LiteralHashCodeHelper; | ||
10 | import tools.refinery.store.query.substitution.Substitution; | ||
11 | import tools.refinery.store.query.term.Variable; | ||
12 | |||
13 | import java.util.Set; | ||
14 | |||
15 | public interface Literal { | ||
16 | Set<Variable> getOutputVariables(); | ||
17 | |||
18 | Set<Variable> getInputVariables(Set<? extends Variable> positiveVariablesInClause); | ||
19 | |||
20 | Set<Variable> getPrivateVariables(Set<? extends Variable> positiveVariablesInClause); | ||
21 | |||
22 | Literal substitute(Substitution substitution); | ||
23 | |||
24 | default Literal reduce() { | ||
25 | return this; | ||
26 | } | ||
27 | |||
28 | @SuppressWarnings("BooleanMethodIsAlwaysInverted") | ||
29 | boolean equalsWithSubstitution(LiteralEqualityHelper helper, Literal other); | ||
30 | |||
31 | int hashCodeWithSubstitution(LiteralHashCodeHelper helper); | ||
32 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/Literals.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/Literals.java deleted file mode 100644 index 6056da45..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/Literals.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 | */ | ||
6 | package tools.refinery.store.query.literal; | ||
7 | |||
8 | import tools.refinery.store.query.term.Term; | ||
9 | |||
10 | public final class Literals { | ||
11 | private Literals() { | ||
12 | throw new IllegalStateException("This is a static utility class and should not be instantiated directly"); | ||
13 | } | ||
14 | |||
15 | public static <T extends CanNegate<T>> T not(CanNegate<T> literal) { | ||
16 | return literal.negate(); | ||
17 | } | ||
18 | |||
19 | public static CheckLiteral check(Term<Boolean> term) { | ||
20 | return new CheckLiteral(term); | ||
21 | } | ||
22 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/Reduction.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/Reduction.java deleted file mode 100644 index ee155a9a..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/Reduction.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 | */ | ||
6 | package tools.refinery.store.query.literal; | ||
7 | |||
8 | public enum Reduction { | ||
9 | /** | ||
10 | * Signifies that a literal should be preserved in the clause. | ||
11 | */ | ||
12 | NOT_REDUCIBLE, | ||
13 | |||
14 | /** | ||
15 | * Signifies that the literal may be omitted from the cause (if the model being queried is nonempty). | ||
16 | */ | ||
17 | ALWAYS_TRUE, | ||
18 | |||
19 | /** | ||
20 | * Signifies that the clause with the literal may be omitted entirely. | ||
21 | */ | ||
22 | ALWAYS_FALSE; | ||
23 | |||
24 | public Reduction negate() { | ||
25 | return switch (this) { | ||
26 | case NOT_REDUCIBLE -> NOT_REDUCIBLE; | ||
27 | case ALWAYS_TRUE -> ALWAYS_FALSE; | ||
28 | case ALWAYS_FALSE -> ALWAYS_TRUE; | ||
29 | }; | ||
30 | } | ||
31 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/RepresentativeElectionLiteral.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/RepresentativeElectionLiteral.java deleted file mode 100644 index f7323947..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/RepresentativeElectionLiteral.java +++ /dev/null | |||
@@ -1,119 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.literal; | ||
7 | |||
8 | import tools.refinery.store.query.Constraint; | ||
9 | import tools.refinery.store.query.InvalidQueryException; | ||
10 | import tools.refinery.store.query.equality.LiteralEqualityHelper; | ||
11 | import tools.refinery.store.query.equality.LiteralHashCodeHelper; | ||
12 | import tools.refinery.store.query.substitution.Substitution; | ||
13 | import tools.refinery.store.query.term.NodeVariable; | ||
14 | import tools.refinery.store.query.term.ParameterDirection; | ||
15 | import tools.refinery.store.query.term.Variable; | ||
16 | |||
17 | import java.util.List; | ||
18 | import java.util.Set; | ||
19 | |||
20 | // {@link Object#equals(Object)} is implemented by {@link AbstractLiteral}. | ||
21 | @SuppressWarnings("squid:S2160") | ||
22 | public class RepresentativeElectionLiteral extends AbstractCallLiteral { | ||
23 | private final Connectivity connectivity; | ||
24 | |||
25 | public RepresentativeElectionLiteral(Connectivity connectivity, Constraint target, NodeVariable specific, | ||
26 | NodeVariable representative) { | ||
27 | this(connectivity, target, List.of(specific, representative)); | ||
28 | } | ||
29 | |||
30 | private RepresentativeElectionLiteral(Connectivity connectivity, Constraint target, List<Variable> arguments) { | ||
31 | super(target, arguments); | ||
32 | this.connectivity = connectivity; | ||
33 | var parameters = target.getParameters(); | ||
34 | int arity = target.arity(); | ||
35 | if (arity != 2) { | ||
36 | throw new InvalidQueryException("SCCs can only take binary relations"); | ||
37 | } | ||
38 | if (parameters.get(0).isDataVariable() || parameters.get(1).isDataVariable()) { | ||
39 | throw new InvalidQueryException("SCCs can only be computed over nodes"); | ||
40 | } | ||
41 | if (parameters.get(0).getDirection() != ParameterDirection.OUT || | ||
42 | parameters.get(1).getDirection() != ParameterDirection.OUT) { | ||
43 | throw new InvalidQueryException("SCCs cannot take input parameters"); | ||
44 | } | ||
45 | } | ||
46 | |||
47 | public Connectivity getConnectivity() { | ||
48 | return connectivity; | ||
49 | } | ||
50 | |||
51 | @Override | ||
52 | protected Literal doSubstitute(Substitution substitution, List<Variable> substitutedArguments) { | ||
53 | return new RepresentativeElectionLiteral(connectivity, getTarget(), substitutedArguments); | ||
54 | } | ||
55 | |||
56 | @Override | ||
57 | public Set<Variable> getOutputVariables() { | ||
58 | return getArgumentsOfDirection(ParameterDirection.OUT); | ||
59 | } | ||
60 | |||
61 | @Override | ||
62 | public Set<Variable> getInputVariables(Set<? extends Variable> positiveVariablesInClause) { | ||
63 | return Set.of(); | ||
64 | } | ||
65 | |||
66 | @Override | ||
67 | public Set<Variable> getPrivateVariables(Set<? extends Variable> positiveVariablesInClause) { | ||
68 | return Set.of(); | ||
69 | } | ||
70 | |||
71 | @Override | ||
72 | public Literal reduce() { | ||
73 | var reduction = getTarget().getReduction(); | ||
74 | return switch (reduction) { | ||
75 | case ALWAYS_FALSE -> BooleanLiteral.FALSE; | ||
76 | case ALWAYS_TRUE -> throw new InvalidQueryException( | ||
77 | "Trying to elect representatives over an infinite set"); | ||
78 | case NOT_REDUCIBLE -> this; | ||
79 | }; | ||
80 | } | ||
81 | |||
82 | @Override | ||
83 | public AbstractCallLiteral withArguments(Constraint newTarget, List<Variable> newArguments) { | ||
84 | return new RepresentativeElectionLiteral(connectivity, newTarget, newArguments); | ||
85 | } | ||
86 | |||
87 | @Override | ||
88 | public boolean equalsWithSubstitution(LiteralEqualityHelper helper, Literal other) { | ||
89 | if (!super.equalsWithSubstitution(helper, other)) { | ||
90 | return false; | ||
91 | } | ||
92 | var otherRepresentativeElectionLiteral = (RepresentativeElectionLiteral) other; | ||
93 | return connectivity.equals(otherRepresentativeElectionLiteral.connectivity); | ||
94 | } | ||
95 | |||
96 | @Override | ||
97 | public int hashCodeWithSubstitution(LiteralHashCodeHelper helper) { | ||
98 | return super.hashCodeWithSubstitution(helper) * 31 + connectivity.hashCode(); | ||
99 | } | ||
100 | |||
101 | @Override | ||
102 | public String toString() { | ||
103 | var builder = new StringBuilder(); | ||
104 | builder.append("@Representative(\""); | ||
105 | builder.append(connectivity); | ||
106 | builder.append("\") "); | ||
107 | builder.append(getTarget().toReferenceString()); | ||
108 | builder.append("("); | ||
109 | var argumentIterator = getArguments().iterator(); | ||
110 | if (argumentIterator.hasNext()) { | ||
111 | builder.append(argumentIterator.next()); | ||
112 | while (argumentIterator.hasNext()) { | ||
113 | builder.append(", ").append(argumentIterator.next()); | ||
114 | } | ||
115 | } | ||
116 | builder.append(")"); | ||
117 | return builder.toString(); | ||
118 | } | ||
119 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/resultset/AbstractResultSet.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/resultset/AbstractResultSet.java index dcfe6cc5..f8290b48 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/resultset/AbstractResultSet.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/resultset/AbstractResultSet.java | |||
@@ -6,7 +6,7 @@ | |||
6 | package tools.refinery.store.query.resultset; | 6 | package tools.refinery.store.query.resultset; |
7 | 7 | ||
8 | import tools.refinery.store.query.ModelQueryAdapter; | 8 | import tools.refinery.store.query.ModelQueryAdapter; |
9 | import tools.refinery.store.query.dnf.Query; | 9 | import tools.refinery.logic.dnf.Query; |
10 | import tools.refinery.store.tuple.Tuple; | 10 | import tools.refinery.store.tuple.Tuple; |
11 | 11 | ||
12 | import java.util.ArrayList; | 12 | import java.util.ArrayList; |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/resultset/AnyResultSet.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/resultset/AnyResultSet.java index 5b75b103..038ca7f9 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/resultset/AnyResultSet.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/resultset/AnyResultSet.java | |||
@@ -6,7 +6,7 @@ | |||
6 | package tools.refinery.store.query.resultset; | 6 | package tools.refinery.store.query.resultset; |
7 | 7 | ||
8 | import tools.refinery.store.query.ModelQueryAdapter; | 8 | import tools.refinery.store.query.ModelQueryAdapter; |
9 | import tools.refinery.store.query.dnf.AnyQuery; | 9 | import tools.refinery.logic.dnf.AnyQuery; |
10 | 10 | ||
11 | public sealed interface AnyResultSet permits ResultSet { | 11 | public sealed interface AnyResultSet permits ResultSet { |
12 | ModelQueryAdapter getAdapter(); | 12 | ModelQueryAdapter getAdapter(); |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/resultset/EmptyResultSet.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/resultset/EmptyResultSet.java index 991b1e32..daebfe7c 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/resultset/EmptyResultSet.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/resultset/EmptyResultSet.java | |||
@@ -8,7 +8,7 @@ package tools.refinery.store.query.resultset; | |||
8 | import tools.refinery.store.map.Cursor; | 8 | import tools.refinery.store.map.Cursor; |
9 | import tools.refinery.store.map.Cursors; | 9 | import tools.refinery.store.map.Cursors; |
10 | import tools.refinery.store.query.ModelQueryAdapter; | 10 | import tools.refinery.store.query.ModelQueryAdapter; |
11 | import tools.refinery.store.query.dnf.Query; | 11 | import tools.refinery.logic.dnf.Query; |
12 | import tools.refinery.store.tuple.Tuple; | 12 | import tools.refinery.store.tuple.Tuple; |
13 | 13 | ||
14 | public record EmptyResultSet<T>(ModelQueryAdapter adapter, Query<T> query) implements ResultSet<T> { | 14 | public record EmptyResultSet<T>(ModelQueryAdapter adapter, Query<T> query) implements ResultSet<T> { |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/resultset/OrderedResultSet.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/resultset/OrderedResultSet.java index df12b967..606e197c 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/resultset/OrderedResultSet.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/resultset/OrderedResultSet.java | |||
@@ -7,7 +7,7 @@ package tools.refinery.store.query.resultset; | |||
7 | 7 | ||
8 | import tools.refinery.store.map.Cursor; | 8 | import tools.refinery.store.map.Cursor; |
9 | import tools.refinery.store.query.ModelQueryAdapter; | 9 | import tools.refinery.store.query.ModelQueryAdapter; |
10 | import tools.refinery.store.query.dnf.Query; | 10 | import tools.refinery.logic.dnf.Query; |
11 | import tools.refinery.store.query.utils.OrderStatisticTree; | 11 | import tools.refinery.store.query.utils.OrderStatisticTree; |
12 | import tools.refinery.store.tuple.Tuple; | 12 | import tools.refinery.store.tuple.Tuple; |
13 | 13 | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/resultset/ResultSet.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/resultset/ResultSet.java index a6e99784..e84634ac 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/resultset/ResultSet.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/resultset/ResultSet.java | |||
@@ -6,7 +6,7 @@ | |||
6 | package tools.refinery.store.query.resultset; | 6 | package tools.refinery.store.query.resultset; |
7 | 7 | ||
8 | import tools.refinery.store.map.Cursor; | 8 | import tools.refinery.store.map.Cursor; |
9 | import tools.refinery.store.query.dnf.Query; | 9 | import tools.refinery.logic.dnf.Query; |
10 | import tools.refinery.store.tuple.Tuple; | 10 | import tools.refinery.store.tuple.Tuple; |
11 | 11 | ||
12 | public non-sealed interface ResultSet<T> extends AnyResultSet { | 12 | public non-sealed interface ResultSet<T> extends AnyResultSet { |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/rewriter/AbstractRecursiveRewriter.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/rewriter/AbstractRecursiveRewriter.java deleted file mode 100644 index fb4c14a7..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/rewriter/AbstractRecursiveRewriter.java +++ /dev/null | |||
@@ -1,26 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.rewriter; | ||
7 | |||
8 | import tools.refinery.store.query.dnf.Dnf; | ||
9 | import tools.refinery.store.query.equality.DnfEqualityChecker; | ||
10 | import tools.refinery.store.util.CycleDetectingMapper; | ||
11 | |||
12 | public abstract class AbstractRecursiveRewriter implements DnfRewriter { | ||
13 | private final CycleDetectingMapper<Dnf, Dnf> mapper = new CycleDetectingMapper<>(Dnf::name, this::map); | ||
14 | |||
15 | @Override | ||
16 | public Dnf rewrite(Dnf dnf) { | ||
17 | return mapper.map(dnf); | ||
18 | } | ||
19 | |||
20 | protected Dnf map(Dnf dnf) { | ||
21 | var result = doRewrite(dnf); | ||
22 | return dnf.equalsWithSubstitution(DnfEqualityChecker.DEFAULT, result) ? dnf : result; | ||
23 | } | ||
24 | |||
25 | protected abstract Dnf doRewrite(Dnf dnf); | ||
26 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/rewriter/ClauseInputParameterResolver.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/rewriter/ClauseInputParameterResolver.java deleted file mode 100644 index aa06a05a..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/rewriter/ClauseInputParameterResolver.java +++ /dev/null | |||
@@ -1,160 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.rewriter; | ||
7 | |||
8 | import tools.refinery.store.query.dnf.Dnf; | ||
9 | import tools.refinery.store.query.dnf.DnfClause; | ||
10 | import tools.refinery.store.query.literal.*; | ||
11 | import tools.refinery.store.query.substitution.Substitution; | ||
12 | import tools.refinery.store.query.term.ParameterDirection; | ||
13 | import tools.refinery.store.query.term.Variable; | ||
14 | |||
15 | import java.util.*; | ||
16 | |||
17 | class ClauseInputParameterResolver { | ||
18 | private final InputParameterResolver rewriter; | ||
19 | private final String dnfName; | ||
20 | private final int clauseIndex; | ||
21 | private final Set<Variable> positiveVariables = new LinkedHashSet<>(); | ||
22 | private final List<Literal> inlinedLiterals = new ArrayList<>(); | ||
23 | private final Deque<Literal> workList; | ||
24 | private int helperIndex = 0; | ||
25 | |||
26 | public ClauseInputParameterResolver(InputParameterResolver rewriter, List<Literal> context, DnfClause clause, | ||
27 | String dnfName, int clauseIndex) { | ||
28 | this.rewriter = rewriter; | ||
29 | this.dnfName = dnfName; | ||
30 | this.clauseIndex = clauseIndex; | ||
31 | workList = new ArrayDeque<>(clause.literals().size() + context.size()); | ||
32 | for (var literal : context) { | ||
33 | workList.addLast(literal); | ||
34 | } | ||
35 | for (var literal : clause.literals()) { | ||
36 | workList.addLast(literal); | ||
37 | } | ||
38 | } | ||
39 | |||
40 | public List<Literal> rewriteClause() { | ||
41 | while (!workList.isEmpty()) { | ||
42 | var literal = workList.removeFirst(); | ||
43 | processLiteral(literal); | ||
44 | } | ||
45 | return inlinedLiterals; | ||
46 | } | ||
47 | |||
48 | private void processLiteral(Literal literal) { | ||
49 | if (!(literal instanceof AbstractCallLiteral abstractCallLiteral) || | ||
50 | !(abstractCallLiteral.getTarget() instanceof Dnf targetDnf)) { | ||
51 | markAsDone(literal); | ||
52 | return; | ||
53 | } | ||
54 | boolean hasInputParameter = hasInputParameter(targetDnf); | ||
55 | if (!hasInputParameter) { | ||
56 | targetDnf = rewriter.rewrite(targetDnf); | ||
57 | } | ||
58 | if (inlinePositiveClause(abstractCallLiteral, targetDnf)) { | ||
59 | return; | ||
60 | } | ||
61 | if (eliminateDoubleNegation(abstractCallLiteral, targetDnf)) { | ||
62 | return; | ||
63 | } | ||
64 | if (hasInputParameter) { | ||
65 | rewriteWithCurrentContext(abstractCallLiteral, targetDnf); | ||
66 | return; | ||
67 | } | ||
68 | markAsDone(abstractCallLiteral.withTarget(targetDnf)); | ||
69 | } | ||
70 | |||
71 | private void markAsDone(Literal literal) { | ||
72 | positiveVariables.addAll(literal.getOutputVariables()); | ||
73 | inlinedLiterals.add(literal); | ||
74 | } | ||
75 | |||
76 | private boolean inlinePositiveClause(AbstractCallLiteral abstractCallLiteral, Dnf targetDnf) { | ||
77 | var targetLiteral = getSingleLiteral(abstractCallLiteral, targetDnf, CallPolarity.POSITIVE); | ||
78 | if (targetLiteral == null) { | ||
79 | return false; | ||
80 | } | ||
81 | var substitution = asSubstitution(abstractCallLiteral, targetDnf); | ||
82 | var substitutedLiteral = targetLiteral.substitute(substitution); | ||
83 | workList.addFirst(substitutedLiteral); | ||
84 | return true; | ||
85 | } | ||
86 | |||
87 | private boolean eliminateDoubleNegation(AbstractCallLiteral abstractCallLiteral, Dnf targetDnf) { | ||
88 | var targetLiteral = getSingleLiteral(abstractCallLiteral, targetDnf, CallPolarity.NEGATIVE); | ||
89 | if (!(targetLiteral instanceof CallLiteral targetCallLiteral) || | ||
90 | targetCallLiteral.getPolarity() != CallPolarity.NEGATIVE) { | ||
91 | return false; | ||
92 | } | ||
93 | var substitution = asSubstitution(abstractCallLiteral, targetDnf); | ||
94 | var substitutedLiteral = (CallLiteral) targetCallLiteral.substitute(substitution); | ||
95 | workList.addFirst(substitutedLiteral.negate()); | ||
96 | return true; | ||
97 | } | ||
98 | |||
99 | private void rewriteWithCurrentContext(AbstractCallLiteral abstractCallLiteral, Dnf targetDnf) { | ||
100 | var contextBuilder = Dnf.builder("%s#clause%d#helper%d".formatted(dnfName, clauseIndex, helperIndex)); | ||
101 | helperIndex++; | ||
102 | contextBuilder.parameters(positiveVariables, ParameterDirection.OUT); | ||
103 | contextBuilder.clause(inlinedLiterals); | ||
104 | var contextDnf = contextBuilder.build(); | ||
105 | var contextCall = new CallLiteral(CallPolarity.POSITIVE, contextDnf, List.copyOf(positiveVariables)); | ||
106 | inlinedLiterals.clear(); | ||
107 | var substitution = Substitution.builder().renewing().build(); | ||
108 | var context = new ArrayList<Literal>(); | ||
109 | context.add(contextCall.substitute(substitution)); | ||
110 | int arity = targetDnf.arity(); | ||
111 | for (int i = 0; i < arity; i++) { | ||
112 | var parameter = targetDnf.getSymbolicParameters().get(i).getVariable(); | ||
113 | var argument = abstractCallLiteral.getArguments().get(i); | ||
114 | context.add(new EquivalenceLiteral(true, parameter, substitution.getSubstitute(argument))); | ||
115 | } | ||
116 | var rewrittenDnf = rewriter.rewriteWithContext(context, targetDnf); | ||
117 | workList.addFirst(abstractCallLiteral.withTarget(rewrittenDnf)); | ||
118 | workList.addFirst(contextCall); | ||
119 | } | ||
120 | |||
121 | private static boolean hasInputParameter(Dnf targetDnf) { | ||
122 | for (var parameter : targetDnf.getParameters()) { | ||
123 | if (parameter.getDirection() != ParameterDirection.OUT) { | ||
124 | return true; | ||
125 | } | ||
126 | } | ||
127 | return false; | ||
128 | } | ||
129 | |||
130 | private static Literal getSingleLiteral(AbstractCallLiteral abstractCallLiteral, Dnf targetDnf, | ||
131 | CallPolarity polarity) { | ||
132 | if (!(abstractCallLiteral instanceof CallLiteral callLiteral) || | ||
133 | callLiteral.getPolarity() != polarity) { | ||
134 | return null; | ||
135 | } | ||
136 | var clauses = targetDnf.getClauses(); | ||
137 | if (clauses.size() != 1) { | ||
138 | return null; | ||
139 | } | ||
140 | var targetLiterals = clauses.get(0).literals(); | ||
141 | if (targetLiterals.size() != 1) { | ||
142 | return null; | ||
143 | } | ||
144 | return targetLiterals.get(0); | ||
145 | } | ||
146 | |||
147 | private static Substitution asSubstitution(AbstractCallLiteral callLiteral, Dnf targetDnf) { | ||
148 | var builder = Substitution.builder().renewing(); | ||
149 | var arguments = callLiteral.getArguments(); | ||
150 | var parameters = targetDnf.getSymbolicParameters(); | ||
151 | int arity = arguments.size(); | ||
152 | if (parameters.size() != arity) { | ||
153 | throw new IllegalArgumentException("Call %s of %s arity mismatch".formatted(callLiteral, targetDnf)); | ||
154 | } | ||
155 | for (int i = 0; i < arity; i++) { | ||
156 | builder.putChecked(parameters.get(i).getVariable(), arguments.get(i)); | ||
157 | } | ||
158 | return builder.build(); | ||
159 | } | ||
160 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/rewriter/CompositeRewriter.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/rewriter/CompositeRewriter.java deleted file mode 100644 index 5b4f65e5..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/rewriter/CompositeRewriter.java +++ /dev/null | |||
@@ -1,29 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.rewriter; | ||
7 | |||
8 | import tools.refinery.store.query.dnf.Dnf; | ||
9 | |||
10 | import java.util.ArrayList; | ||
11 | import java.util.List; | ||
12 | |||
13 | public class CompositeRewriter implements DnfRewriter { | ||
14 | private final List<DnfRewriter> rewriterList = new ArrayList<>(); | ||
15 | |||
16 | public void addFirst(DnfRewriter rewriter) { | ||
17 | rewriterList.add(rewriter); | ||
18 | } | ||
19 | |||
20 | @Override | ||
21 | public Dnf rewrite(Dnf dnf) { | ||
22 | Dnf rewrittenDnf = dnf; | ||
23 | for (int i = rewriterList.size() - 1; i >= 0; i--) { | ||
24 | var rewriter = rewriterList.get(i); | ||
25 | rewrittenDnf = rewriter.rewrite(rewrittenDnf); | ||
26 | } | ||
27 | return rewrittenDnf; | ||
28 | } | ||
29 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/rewriter/DnfRewriter.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/rewriter/DnfRewriter.java deleted file mode 100644 index 5d8359d1..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/rewriter/DnfRewriter.java +++ /dev/null | |||
@@ -1,24 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.rewriter; | ||
7 | |||
8 | import tools.refinery.store.query.dnf.AnyQuery; | ||
9 | import tools.refinery.store.query.dnf.Dnf; | ||
10 | import tools.refinery.store.query.dnf.Query; | ||
11 | |||
12 | @FunctionalInterface | ||
13 | public interface DnfRewriter { | ||
14 | Dnf rewrite(Dnf dnf); | ||
15 | |||
16 | default AnyQuery rewrite(AnyQuery query) { | ||
17 | return rewrite((Query<?>) query); | ||
18 | } | ||
19 | |||
20 | default <T> Query<T> rewrite(Query<T> query) { | ||
21 | var rewrittenDnf = rewrite(query.getDnf()); | ||
22 | return query.withDnf(rewrittenDnf); | ||
23 | } | ||
24 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/rewriter/DuplicateDnfRemover.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/rewriter/DuplicateDnfRemover.java deleted file mode 100644 index 0c786470..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/rewriter/DuplicateDnfRemover.java +++ /dev/null | |||
@@ -1,98 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.rewriter; | ||
7 | |||
8 | import tools.refinery.store.query.dnf.Dnf; | ||
9 | import tools.refinery.store.query.dnf.DnfClause; | ||
10 | import tools.refinery.store.query.dnf.Query; | ||
11 | import tools.refinery.store.query.equality.DnfEqualityChecker; | ||
12 | import tools.refinery.store.query.literal.AbstractCallLiteral; | ||
13 | import tools.refinery.store.query.literal.Literal; | ||
14 | |||
15 | import java.util.ArrayList; | ||
16 | import java.util.HashMap; | ||
17 | import java.util.List; | ||
18 | import java.util.Map; | ||
19 | |||
20 | public class DuplicateDnfRemover extends AbstractRecursiveRewriter { | ||
21 | private final Map<CanonicalDnf, Dnf> dnfCache = new HashMap<>(); | ||
22 | private final Map<Dnf, Query<?>> queryCache = new HashMap<>(); | ||
23 | |||
24 | @Override | ||
25 | protected Dnf map(Dnf dnf) { | ||
26 | var result = super.map(dnf); | ||
27 | return dnfCache.computeIfAbsent(new CanonicalDnf(result), CanonicalDnf::getDnf); | ||
28 | } | ||
29 | |||
30 | @Override | ||
31 | protected Dnf doRewrite(Dnf dnf) { | ||
32 | var builder = Dnf.builderFrom(dnf); | ||
33 | for (var clause : dnf.getClauses()) { | ||
34 | builder.clause(rewriteClause(clause)); | ||
35 | } | ||
36 | return builder.build(); | ||
37 | } | ||
38 | |||
39 | private List<Literal> rewriteClause(DnfClause clause) { | ||
40 | var originalLiterals = clause.literals(); | ||
41 | var literals = new ArrayList<Literal>(originalLiterals.size()); | ||
42 | for (var literal : originalLiterals) { | ||
43 | var rewrittenLiteral = literal; | ||
44 | if (literal instanceof AbstractCallLiteral abstractCallLiteral && | ||
45 | abstractCallLiteral.getTarget() instanceof Dnf targetDnf) { | ||
46 | var rewrittenTarget = rewrite(targetDnf); | ||
47 | rewrittenLiteral = abstractCallLiteral.withTarget(rewrittenTarget); | ||
48 | } | ||
49 | literals.add(rewrittenLiteral); | ||
50 | } | ||
51 | return literals; | ||
52 | } | ||
53 | |||
54 | @Override | ||
55 | public <T> Query<T> rewrite(Query<T> query) { | ||
56 | var rewrittenDnf = rewrite(query.getDnf()); | ||
57 | // {@code withDnf} will always return the appropriate type. | ||
58 | @SuppressWarnings("unchecked") | ||
59 | var rewrittenQuery = (Query<T>) queryCache.computeIfAbsent(rewrittenDnf, query::withDnf); | ||
60 | return rewrittenQuery; | ||
61 | } | ||
62 | |||
63 | private static class CanonicalDnf { | ||
64 | private final Dnf dnf; | ||
65 | private final int hash; | ||
66 | |||
67 | public CanonicalDnf(Dnf dnf) { | ||
68 | this.dnf = dnf; | ||
69 | hash = dnf.hashCodeWithSubstitution(); | ||
70 | } | ||
71 | |||
72 | public Dnf getDnf() { | ||
73 | return dnf; | ||
74 | } | ||
75 | |||
76 | @Override | ||
77 | public boolean equals(Object obj) { | ||
78 | if (this == obj) { | ||
79 | return true; | ||
80 | } | ||
81 | if (obj == null || getClass() != obj.getClass()) { | ||
82 | return false; | ||
83 | } | ||
84 | var otherCanonicalDnf = (CanonicalDnf) obj; | ||
85 | return dnf.equalsWithSubstitution(DnfEqualityChecker.DEFAULT, otherCanonicalDnf.dnf); | ||
86 | } | ||
87 | |||
88 | @Override | ||
89 | public int hashCode() { | ||
90 | return hash; | ||
91 | } | ||
92 | |||
93 | @Override | ||
94 | public String toString() { | ||
95 | return dnf.name(); | ||
96 | } | ||
97 | } | ||
98 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/rewriter/InputParameterResolver.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/rewriter/InputParameterResolver.java deleted file mode 100644 index cd8a2e7d..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/rewriter/InputParameterResolver.java +++ /dev/null | |||
@@ -1,51 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.rewriter; | ||
7 | |||
8 | import tools.refinery.store.query.dnf.Dnf; | ||
9 | import tools.refinery.store.query.dnf.DnfBuilder; | ||
10 | import tools.refinery.store.query.literal.Literal; | ||
11 | import tools.refinery.store.query.term.ParameterDirection; | ||
12 | import tools.refinery.store.query.term.Variable; | ||
13 | |||
14 | import java.util.HashSet; | ||
15 | import java.util.List; | ||
16 | |||
17 | public class InputParameterResolver extends AbstractRecursiveRewriter { | ||
18 | @Override | ||
19 | protected Dnf doRewrite(Dnf dnf) { | ||
20 | return rewriteWithContext(List.of(), dnf); | ||
21 | } | ||
22 | |||
23 | Dnf rewriteWithContext(List<Literal> context, Dnf dnf) { | ||
24 | var dnfName = dnf.name(); | ||
25 | var builder = Dnf.builder(dnfName); | ||
26 | createSymbolicParameters(context, dnf, builder); | ||
27 | builder.functionalDependencies(dnf.getFunctionalDependencies()); | ||
28 | var clauses = dnf.getClauses(); | ||
29 | int clauseCount = clauses.size(); | ||
30 | for (int i = 0; i < clauseCount; i++) { | ||
31 | var clause = clauses.get(i); | ||
32 | var clauseRewriter = new ClauseInputParameterResolver(this, context, clause, dnfName, i); | ||
33 | builder.clause(clauseRewriter.rewriteClause()); | ||
34 | } | ||
35 | return builder.build(); | ||
36 | } | ||
37 | |||
38 | private static void createSymbolicParameters(List<Literal> context, Dnf dnf, DnfBuilder builder) { | ||
39 | var positiveInContext = new HashSet<Variable>(); | ||
40 | for (var literal : context) { | ||
41 | positiveInContext.addAll(literal.getOutputVariables()); | ||
42 | } | ||
43 | for (var symbolicParameter : dnf.getSymbolicParameters()) { | ||
44 | var variable = symbolicParameter.getVariable(); | ||
45 | var isOutput = symbolicParameter.getDirection() == ParameterDirection.OUT || | ||
46 | positiveInContext.contains(variable); | ||
47 | var direction = isOutput ? ParameterDirection.OUT : ParameterDirection.IN; | ||
48 | builder.parameter(variable, direction); | ||
49 | } | ||
50 | } | ||
51 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/substitution/MapBasedSubstitution.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/substitution/MapBasedSubstitution.java deleted file mode 100644 index a8201eef..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/substitution/MapBasedSubstitution.java +++ /dev/null | |||
@@ -1,18 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.substitution; | ||
7 | |||
8 | import tools.refinery.store.query.term.Variable; | ||
9 | |||
10 | import java.util.Map; | ||
11 | |||
12 | public record MapBasedSubstitution(Map<Variable, Variable> map, Substitution fallback) implements Substitution { | ||
13 | @Override | ||
14 | public Variable getSubstitute(Variable variable) { | ||
15 | var value = map.get(variable); | ||
16 | return value == null ? fallback.getSubstitute(variable) : value; | ||
17 | } | ||
18 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/substitution/RenewingSubstitution.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/substitution/RenewingSubstitution.java deleted file mode 100644 index 9b737ceb..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/substitution/RenewingSubstitution.java +++ /dev/null | |||
@@ -1,20 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.substitution; | ||
7 | |||
8 | import tools.refinery.store.query.term.Variable; | ||
9 | |||
10 | import java.util.HashMap; | ||
11 | import java.util.Map; | ||
12 | |||
13 | public class RenewingSubstitution implements Substitution { | ||
14 | private final Map<Variable, Variable> alreadyRenewed = new HashMap<>(); | ||
15 | |||
16 | @Override | ||
17 | public Variable getSubstitute(Variable variable) { | ||
18 | return alreadyRenewed.computeIfAbsent(variable, Variable::renew); | ||
19 | } | ||
20 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/substitution/StatelessSubstitution.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/substitution/StatelessSubstitution.java deleted file mode 100644 index bb3803d3..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/substitution/StatelessSubstitution.java +++ /dev/null | |||
@@ -1,23 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.substitution; | ||
7 | |||
8 | import tools.refinery.store.query.term.Variable; | ||
9 | |||
10 | public enum StatelessSubstitution implements Substitution { | ||
11 | FAILING { | ||
12 | @Override | ||
13 | public Variable getSubstitute(Variable variable) { | ||
14 | throw new IllegalArgumentException("No substitute for " + variable); | ||
15 | } | ||
16 | }, | ||
17 | IDENTITY { | ||
18 | @Override | ||
19 | public Variable getSubstitute(Variable variable) { | ||
20 | return variable; | ||
21 | } | ||
22 | } | ||
23 | } | ||
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 deleted file mode 100644 index 834fce12..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/substitution/Substitution.java +++ /dev/null | |||
@@ -1,29 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.substitution; | ||
7 | |||
8 | import tools.refinery.store.query.term.DataVariable; | ||
9 | import tools.refinery.store.query.term.NodeVariable; | ||
10 | import tools.refinery.store.query.term.Variable; | ||
11 | |||
12 | @FunctionalInterface | ||
13 | public interface Substitution { | ||
14 | Variable getSubstitute(Variable variable); | ||
15 | |||
16 | default NodeVariable getTypeSafeSubstitute(NodeVariable variable) { | ||
17 | var substitute = getSubstitute(variable); | ||
18 | return substitute.asNodeVariable(); | ||
19 | } | ||
20 | |||
21 | default <T> DataVariable<T> getTypeSafeSubstitute(DataVariable<T> variable) { | ||
22 | var substitute = getSubstitute(variable); | ||
23 | return substitute.asDataVariable(variable.getType()); | ||
24 | } | ||
25 | |||
26 | static SubstitutionBuilder builder() { | ||
27 | return new SubstitutionBuilder(); | ||
28 | } | ||
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 deleted file mode 100644 index 37fb6908..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/substitution/SubstitutionBuilder.java +++ /dev/null | |||
@@ -1,79 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.substitution; | ||
7 | |||
8 | import tools.refinery.store.query.term.DataVariable; | ||
9 | import tools.refinery.store.query.term.NodeVariable; | ||
10 | import tools.refinery.store.query.term.Variable; | ||
11 | |||
12 | import java.util.Collections; | ||
13 | import java.util.HashMap; | ||
14 | import java.util.List; | ||
15 | import java.util.Map; | ||
16 | |||
17 | @SuppressWarnings("UnusedReturnValue") | ||
18 | public 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.tryGetType().equals(substitute.tryGetType())) { | ||
36 | throw new IllegalArgumentException("Cannot substitute variable %s of sort %s with variable %s of sort %s" | ||
37 | .formatted(original, original.tryGetType().map(Class::getName).orElse("node"), substitute, | ||
38 | substitute.tryGetType().map(Class::getName).orElse("node"))); | ||
39 | } | ||
40 | if (map.containsKey(original)) { | ||
41 | throw new IllegalArgumentException("Already has substitution for variable %s".formatted(original)); | ||
42 | } | ||
43 | map.put(original, substitute); | ||
44 | return this; | ||
45 | } | ||
46 | |||
47 | public SubstitutionBuilder putManyChecked(List<Variable> originals, List<Variable> substitutes) { | ||
48 | int size = originals.size(); | ||
49 | if (size != substitutes.size()) { | ||
50 | throw new IllegalArgumentException("Cannot substitute %d variables %s with %d variables %s" | ||
51 | .formatted(size, originals, substitutes.size(), substitutes)); | ||
52 | } | ||
53 | for (int i = 0; i < size; i++) { | ||
54 | putChecked(originals.get(i), substitutes.get(i)); | ||
55 | } | ||
56 | return this; | ||
57 | } | ||
58 | |||
59 | public SubstitutionBuilder fallback(Substitution newFallback) { | ||
60 | fallback = newFallback; | ||
61 | return this; | ||
62 | } | ||
63 | |||
64 | public SubstitutionBuilder total() { | ||
65 | return fallback(StatelessSubstitution.FAILING); | ||
66 | } | ||
67 | |||
68 | public SubstitutionBuilder partial() { | ||
69 | return fallback(StatelessSubstitution.IDENTITY); | ||
70 | } | ||
71 | |||
72 | public SubstitutionBuilder renewing() { | ||
73 | return fallback(new RenewingSubstitution()); | ||
74 | } | ||
75 | |||
76 | public Substitution build() { | ||
77 | return map.isEmpty() ? fallback : new MapBasedSubstitution(Collections.unmodifiableMap(map), fallback); | ||
78 | } | ||
79 | } | ||
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 deleted file mode 100644 index 5cecc35b..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/AbstractTerm.java +++ /dev/null | |||
@@ -1,47 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.term; | ||
7 | |||
8 | import tools.refinery.store.query.equality.LiteralEqualityHelper; | ||
9 | import tools.refinery.store.query.equality.LiteralHashCodeHelper; | ||
10 | |||
11 | import java.util.Objects; | ||
12 | |||
13 | public abstract class AbstractTerm<T> implements Term<T> { | ||
14 | private final Class<T> type; | ||
15 | |||
16 | protected AbstractTerm(Class<T> type) { | ||
17 | this.type = type; | ||
18 | } | ||
19 | |||
20 | @Override | ||
21 | public Class<T> getType() { | ||
22 | return type; | ||
23 | } | ||
24 | |||
25 | @Override | ||
26 | public boolean equalsWithSubstitution(LiteralEqualityHelper helper, AnyTerm other) { | ||
27 | return other != null && getClass() == other.getClass() && type.equals(other.getType()); | ||
28 | } | ||
29 | |||
30 | @Override | ||
31 | public int hashCodeWithSubstitution(LiteralHashCodeHelper helper) { | ||
32 | return Objects.hash(getClass(), type); | ||
33 | } | ||
34 | |||
35 | @Override | ||
36 | public boolean equals(Object o) { | ||
37 | if (this == o) return true; | ||
38 | if (o == null || getClass() != o.getClass()) return false; | ||
39 | AbstractTerm<?> that = (AbstractTerm<?>) o; | ||
40 | return equalsWithSubstitution(LiteralEqualityHelper.DEFAULT, that); | ||
41 | } | ||
42 | |||
43 | @Override | ||
44 | public int hashCode() { | ||
45 | return hashCodeWithSubstitution(LiteralHashCodeHelper.DEFAULT); | ||
46 | } | ||
47 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/Aggregator.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/Aggregator.java deleted file mode 100644 index 0684a9d9..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/Aggregator.java +++ /dev/null | |||
@@ -1,18 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.term; | ||
7 | |||
8 | import java.util.stream.Stream; | ||
9 | |||
10 | public interface Aggregator<R, T> { | ||
11 | Class<R> getResultType(); | ||
12 | |||
13 | Class<T> getInputType(); | ||
14 | |||
15 | R aggregateStream(Stream<T> stream); | ||
16 | |||
17 | R getEmptyResult(); | ||
18 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/AnyDataVariable.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/AnyDataVariable.java deleted file mode 100644 index 3801bc11..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/AnyDataVariable.java +++ /dev/null | |||
@@ -1,55 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.term; | ||
7 | |||
8 | import org.jetbrains.annotations.Nullable; | ||
9 | import tools.refinery.store.query.InvalidQueryException; | ||
10 | import tools.refinery.store.query.equality.LiteralEqualityHelper; | ||
11 | |||
12 | import java.util.Optional; | ||
13 | import java.util.Set; | ||
14 | |||
15 | public abstract sealed class AnyDataVariable extends Variable implements AnyTerm permits DataVariable { | ||
16 | protected AnyDataVariable(String name) { | ||
17 | super(name); | ||
18 | } | ||
19 | |||
20 | @Override | ||
21 | public Optional<Class<?>> tryGetType() { | ||
22 | return Optional.of(getType()); | ||
23 | } | ||
24 | |||
25 | @Override | ||
26 | public boolean isNodeVariable() { | ||
27 | return false; | ||
28 | } | ||
29 | |||
30 | @Override | ||
31 | public boolean isDataVariable() { | ||
32 | return true; | ||
33 | } | ||
34 | |||
35 | @Override | ||
36 | public NodeVariable asNodeVariable() { | ||
37 | throw new InvalidQueryException("%s is a data variable".formatted(this)); | ||
38 | } | ||
39 | |||
40 | @Override | ||
41 | public boolean equalsWithSubstitution(LiteralEqualityHelper helper, AnyTerm other) { | ||
42 | return other instanceof AnyDataVariable dataVariable && helper.variableEqual(this, dataVariable); | ||
43 | } | ||
44 | |||
45 | @Override | ||
46 | public Set<AnyDataVariable> getInputVariables() { | ||
47 | return Set.of(this); | ||
48 | } | ||
49 | |||
50 | @Override | ||
51 | public abstract AnyDataVariable renew(@Nullable String name); | ||
52 | |||
53 | @Override | ||
54 | public abstract AnyDataVariable renew(); | ||
55 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/AnyTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/AnyTerm.java deleted file mode 100644 index f136b68d..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/AnyTerm.java +++ /dev/null | |||
@@ -1,24 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.term; | ||
7 | |||
8 | import tools.refinery.store.query.equality.LiteralEqualityHelper; | ||
9 | import tools.refinery.store.query.equality.LiteralHashCodeHelper; | ||
10 | import tools.refinery.store.query.substitution.Substitution; | ||
11 | |||
12 | import java.util.Set; | ||
13 | |||
14 | public sealed interface AnyTerm permits AnyDataVariable, Term { | ||
15 | Class<?> getType(); | ||
16 | |||
17 | AnyTerm substitute(Substitution substitution); | ||
18 | |||
19 | boolean equalsWithSubstitution(LiteralEqualityHelper helper, AnyTerm other); | ||
20 | |||
21 | int hashCodeWithSubstitution(LiteralHashCodeHelper helper); | ||
22 | |||
23 | Set<AnyDataVariable> getInputVariables(); | ||
24 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/AssignedValue.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/AssignedValue.java deleted file mode 100644 index 0cf30aa6..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/AssignedValue.java +++ /dev/null | |||
@@ -1,13 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.term; | ||
7 | |||
8 | import tools.refinery.store.query.literal.Literal; | ||
9 | |||
10 | @FunctionalInterface | ||
11 | public interface AssignedValue<T> { | ||
12 | Literal toLiteral(DataVariable<T> targetVariable); | ||
13 | } | ||
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 deleted file mode 100644 index cdbf592a..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/BinaryTerm.java +++ /dev/null | |||
@@ -1,106 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.term; | ||
7 | |||
8 | import tools.refinery.store.query.InvalidQueryException; | ||
9 | import tools.refinery.store.query.equality.LiteralEqualityHelper; | ||
10 | import tools.refinery.store.query.equality.LiteralHashCodeHelper; | ||
11 | import tools.refinery.store.query.substitution.Substitution; | ||
12 | import tools.refinery.store.query.valuation.Valuation; | ||
13 | |||
14 | import java.util.Collections; | ||
15 | import java.util.HashSet; | ||
16 | import java.util.Objects; | ||
17 | import java.util.Set; | ||
18 | |||
19 | // {@link Object#equals(Object)} is implemented by {@link AbstractTerm}. | ||
20 | @SuppressWarnings("squid:S2160") | ||
21 | public abstract class BinaryTerm<R, T1, T2> extends AbstractTerm<R> { | ||
22 | private final Class<T1> leftType; | ||
23 | private final Class<T2> rightType; | ||
24 | private final Term<T1> left; | ||
25 | private final Term<T2> right; | ||
26 | |||
27 | protected BinaryTerm(Class<R> type, Class<T1> leftType, Class<T2> rightType, Term<T1> left, Term<T2> right) { | ||
28 | super(type); | ||
29 | if (!left.getType().equals(leftType)) { | ||
30 | throw new InvalidQueryException("Expected left %s to be of type %s, got %s instead".formatted( | ||
31 | left, leftType.getName(), left.getType().getName())); | ||
32 | } | ||
33 | if (!right.getType().equals(rightType)) { | ||
34 | throw new InvalidQueryException("Expected right %s to be of type %s, got %s instead".formatted( | ||
35 | right, rightType.getName(), right.getType().getName())); | ||
36 | } | ||
37 | this.leftType = leftType; | ||
38 | this.rightType = rightType; | ||
39 | this.left = left; | ||
40 | this.right = right; | ||
41 | } | ||
42 | |||
43 | public Class<T1> getLeftType() { | ||
44 | return leftType; | ||
45 | } | ||
46 | |||
47 | public Class<T2> getRightType() { | ||
48 | return rightType; | ||
49 | } | ||
50 | |||
51 | public Term<T1> getLeft() { | ||
52 | return left; | ||
53 | } | ||
54 | |||
55 | public Term<T2> getRight() { | ||
56 | return right; | ||
57 | } | ||
58 | |||
59 | @Override | ||
60 | public R evaluate(Valuation valuation) { | ||
61 | var leftValue = left.evaluate(valuation); | ||
62 | if (leftValue == null) { | ||
63 | return null; | ||
64 | } | ||
65 | var rightValue = right.evaluate(valuation); | ||
66 | if (rightValue == null) { | ||
67 | return null; | ||
68 | } | ||
69 | return doEvaluate(leftValue, rightValue); | ||
70 | } | ||
71 | |||
72 | protected abstract R doEvaluate(T1 leftValue, T2 rightValue); | ||
73 | |||
74 | @Override | ||
75 | public boolean equalsWithSubstitution(LiteralEqualityHelper helper, AnyTerm other) { | ||
76 | if (!super.equalsWithSubstitution(helper, other)) { | ||
77 | return false; | ||
78 | } | ||
79 | var otherBinaryTerm = (BinaryTerm<?, ?, ?>) other; | ||
80 | return leftType.equals(otherBinaryTerm.leftType) && | ||
81 | rightType.equals(otherBinaryTerm.rightType) && | ||
82 | left.equalsWithSubstitution(helper, otherBinaryTerm.left) && | ||
83 | right.equalsWithSubstitution(helper, otherBinaryTerm.right); | ||
84 | } | ||
85 | |||
86 | @Override | ||
87 | public int hashCodeWithSubstitution(LiteralHashCodeHelper helper) { | ||
88 | return Objects.hash(super.hashCodeWithSubstitution(helper), leftType.hashCode(), rightType.hashCode(), | ||
89 | left.hashCodeWithSubstitution(helper), right.hashCodeWithSubstitution(helper)); | ||
90 | } | ||
91 | |||
92 | @Override | ||
93 | public Term<R> substitute(Substitution substitution) { | ||
94 | return doSubstitute(substitution, left.substitute(substitution), right.substitute(substitution)); | ||
95 | } | ||
96 | |||
97 | public abstract Term<R> doSubstitute(Substitution substitution, Term<T1> substitutedLeft, | ||
98 | Term<T2> substitutedRight); | ||
99 | |||
100 | @Override | ||
101 | public Set<AnyDataVariable> getInputVariables() { | ||
102 | var inputVariables = new HashSet<>(left.getInputVariables()); | ||
103 | inputVariables.addAll(right.getInputVariables()); | ||
104 | return Collections.unmodifiableSet(inputVariables); | ||
105 | } | ||
106 | } | ||
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 deleted file mode 100644 index 415ae286..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/ConstantTerm.java +++ /dev/null | |||
@@ -1,67 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.term; | ||
7 | |||
8 | import tools.refinery.store.query.InvalidQueryException; | ||
9 | import tools.refinery.store.query.equality.LiteralEqualityHelper; | ||
10 | import tools.refinery.store.query.equality.LiteralHashCodeHelper; | ||
11 | import tools.refinery.store.query.substitution.Substitution; | ||
12 | import tools.refinery.store.query.valuation.Valuation; | ||
13 | |||
14 | import java.util.Objects; | ||
15 | import java.util.Set; | ||
16 | |||
17 | // {@link Object#equals(Object)} is implemented by {@link AbstractTerm}. | ||
18 | @SuppressWarnings("squid:S2160") | ||
19 | public final class ConstantTerm<T> extends AbstractTerm<T> { | ||
20 | private final T value; | ||
21 | |||
22 | public ConstantTerm(Class<T> type, T value) { | ||
23 | super(type); | ||
24 | if (value != null && !type.isInstance(value)) { | ||
25 | throw new InvalidQueryException("Value %s is not an instance of %s".formatted(value, type.getName())); | ||
26 | } | ||
27 | this.value = value; | ||
28 | } | ||
29 | |||
30 | public T getValue() { | ||
31 | return value; | ||
32 | } | ||
33 | |||
34 | @Override | ||
35 | public T evaluate(Valuation valuation) { | ||
36 | return getValue(); | ||
37 | } | ||
38 | |||
39 | @Override | ||
40 | public Term<T> substitute(Substitution substitution) { | ||
41 | return this; | ||
42 | } | ||
43 | |||
44 | @Override | ||
45 | public boolean equalsWithSubstitution(LiteralEqualityHelper helper, AnyTerm other) { | ||
46 | if (!super.equalsWithSubstitution(helper, other)) { | ||
47 | return false; | ||
48 | } | ||
49 | var otherConstantTerm = (ConstantTerm<?>) other; | ||
50 | return Objects.equals(value, otherConstantTerm.value); | ||
51 | } | ||
52 | |||
53 | @Override | ||
54 | public int hashCodeWithSubstitution(LiteralHashCodeHelper helper) { | ||
55 | return Objects.hash(super.hashCodeWithSubstitution(helper), Objects.hash(value)); | ||
56 | } | ||
57 | |||
58 | @Override | ||
59 | public Set<AnyDataVariable> getInputVariables() { | ||
60 | return Set.of(); | ||
61 | } | ||
62 | |||
63 | @Override | ||
64 | public String toString() { | ||
65 | return value.toString(); | ||
66 | } | ||
67 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/DataVariable.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/DataVariable.java deleted file mode 100644 index 2206b522..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/DataVariable.java +++ /dev/null | |||
@@ -1,103 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.term; | ||
7 | |||
8 | import org.jetbrains.annotations.Nullable; | ||
9 | import tools.refinery.store.query.InvalidQueryException; | ||
10 | import tools.refinery.store.query.equality.LiteralEqualityHelper; | ||
11 | import tools.refinery.store.query.equality.LiteralHashCodeHelper; | ||
12 | import tools.refinery.store.query.literal.EquivalenceLiteral; | ||
13 | import tools.refinery.store.query.literal.Literal; | ||
14 | import tools.refinery.store.query.substitution.Substitution; | ||
15 | import tools.refinery.store.query.valuation.Valuation; | ||
16 | |||
17 | import java.util.Objects; | ||
18 | |||
19 | public final class DataVariable<T> extends AnyDataVariable implements Term<T> { | ||
20 | private final Class<T> type; | ||
21 | |||
22 | DataVariable(String name, Class<T> type) { | ||
23 | super(name); | ||
24 | this.type = type; | ||
25 | } | ||
26 | |||
27 | @Override | ||
28 | public Class<T> getType() { | ||
29 | return type; | ||
30 | } | ||
31 | |||
32 | @Override | ||
33 | public DataVariable<T> renew(@Nullable String name) { | ||
34 | return new DataVariable<>(name, type); | ||
35 | } | ||
36 | |||
37 | @Override | ||
38 | public DataVariable<T> renew() { | ||
39 | return renew(getExplicitName()); | ||
40 | } | ||
41 | |||
42 | @Override | ||
43 | public <U> DataVariable<U> asDataVariable(Class<U> newType) { | ||
44 | if (!getType().equals(newType)) { | ||
45 | throw new InvalidQueryException("%s is not of type %s but of type %s" | ||
46 | .formatted(this, newType.getName(), getType().getName())); | ||
47 | } | ||
48 | @SuppressWarnings("unchecked") | ||
49 | var result = (DataVariable<U>) this; | ||
50 | return result; | ||
51 | } | ||
52 | |||
53 | @Override | ||
54 | public T evaluate(Valuation valuation) { | ||
55 | return valuation.getValue(this); | ||
56 | } | ||
57 | |||
58 | @Override | ||
59 | public Term<T> substitute(Substitution substitution) { | ||
60 | return substitution.getTypeSafeSubstitute(this); | ||
61 | } | ||
62 | |||
63 | @Override | ||
64 | public boolean equalsWithSubstitution(LiteralEqualityHelper helper, AnyTerm other) { | ||
65 | return other instanceof DataVariable<?> dataVariable && helper.variableEqual(this, dataVariable); | ||
66 | } | ||
67 | |||
68 | @Override | ||
69 | public int hashCodeWithSubstitution(LiteralHashCodeHelper helper) { | ||
70 | return helper.getVariableHashCode(this); | ||
71 | } | ||
72 | |||
73 | @Override | ||
74 | public int hashCodeWithSubstitution(int sequenceNumber) { | ||
75 | return Objects.hash(type, sequenceNumber); | ||
76 | } | ||
77 | |||
78 | public Literal assign(AssignedValue<T> value) { | ||
79 | return value.toLiteral(this); | ||
80 | } | ||
81 | |||
82 | @Override | ||
83 | public boolean equals(Object o) { | ||
84 | if (this == o) return true; | ||
85 | if (o == null || getClass() != o.getClass()) return false; | ||
86 | if (!super.equals(o)) return false; | ||
87 | DataVariable<?> that = (DataVariable<?>) o; | ||
88 | return type.equals(that.type); | ||
89 | } | ||
90 | |||
91 | @Override | ||
92 | public int hashCode() { | ||
93 | return Objects.hash(super.hashCode(), type); | ||
94 | } | ||
95 | |||
96 | public EquivalenceLiteral isEquivalent(DataVariable<T> other) { | ||
97 | return new EquivalenceLiteral(true, this, other); | ||
98 | } | ||
99 | |||
100 | public EquivalenceLiteral notEquivalent(DataVariable<T> other) { | ||
101 | return new EquivalenceLiteral(false, this, other); | ||
102 | } | ||
103 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/ExtremeValueAggregator.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/ExtremeValueAggregator.java deleted file mode 100644 index 657cb631..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/ExtremeValueAggregator.java +++ /dev/null | |||
@@ -1,108 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.term; | ||
7 | |||
8 | import java.util.Comparator; | ||
9 | import java.util.Objects; | ||
10 | import java.util.SortedMap; | ||
11 | import java.util.TreeMap; | ||
12 | |||
13 | public class ExtremeValueAggregator<T> implements StatefulAggregator<T, T> { | ||
14 | private final Class<T> type; | ||
15 | private final T emptyResult; | ||
16 | private final Comparator<T> comparator; | ||
17 | |||
18 | public ExtremeValueAggregator(Class<T> type, T emptyResult) { | ||
19 | this(type, emptyResult, null); | ||
20 | } | ||
21 | |||
22 | public ExtremeValueAggregator(Class<T> type, T emptyResult, Comparator<T> comparator) { | ||
23 | this.type = type; | ||
24 | this.emptyResult = emptyResult; | ||
25 | this.comparator = comparator; | ||
26 | } | ||
27 | |||
28 | @Override | ||
29 | public Class<T> getResultType() { | ||
30 | return getInputType(); | ||
31 | } | ||
32 | |||
33 | @Override | ||
34 | public Class<T> getInputType() { | ||
35 | return type; | ||
36 | } | ||
37 | |||
38 | @Override | ||
39 | public StatefulAggregate<T, T> createEmptyAggregate() { | ||
40 | return new Aggregate(); | ||
41 | } | ||
42 | |||
43 | @Override | ||
44 | public T getEmptyResult() { | ||
45 | return emptyResult; | ||
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 | ExtremeValueAggregator<?> that = (ExtremeValueAggregator<?>) o; | ||
53 | return type.equals(that.type) && Objects.equals(emptyResult, that.emptyResult) && Objects.equals(comparator, | ||
54 | that.comparator); | ||
55 | } | ||
56 | |||
57 | @Override | ||
58 | public int hashCode() { | ||
59 | return Objects.hash(type, emptyResult, comparator); | ||
60 | } | ||
61 | |||
62 | private class Aggregate implements StatefulAggregate<T, T> { | ||
63 | private final SortedMap<T, Integer> values; | ||
64 | |||
65 | private Aggregate() { | ||
66 | values = new TreeMap<>(comparator); | ||
67 | } | ||
68 | |||
69 | private Aggregate(Aggregate other) { | ||
70 | values = new TreeMap<>(other.values); | ||
71 | } | ||
72 | |||
73 | @Override | ||
74 | public void add(T value) { | ||
75 | values.compute(value, (ignoredValue, currentCount) -> currentCount == null ? 1 : currentCount + 1); | ||
76 | } | ||
77 | |||
78 | @Override | ||
79 | public void remove(T value) { | ||
80 | values.compute(value, (theValue, currentCount) -> { | ||
81 | if (currentCount == null || currentCount <= 0) { | ||
82 | throw new IllegalStateException("Invalid count %d for value %s".formatted(currentCount, theValue)); | ||
83 | } | ||
84 | return currentCount.equals(1) ? null : currentCount - 1; | ||
85 | }); | ||
86 | } | ||
87 | |||
88 | @Override | ||
89 | public T getResult() { | ||
90 | return isEmpty() ? emptyResult : values.firstKey(); | ||
91 | } | ||
92 | |||
93 | @Override | ||
94 | public boolean isEmpty() { | ||
95 | return values.isEmpty(); | ||
96 | } | ||
97 | |||
98 | @Override | ||
99 | public StatefulAggregate<T, T> deepCopy() { | ||
100 | return new Aggregate(this); | ||
101 | } | ||
102 | |||
103 | @Override | ||
104 | public boolean contains(T value) { | ||
105 | return StatefulAggregate.super.contains(value); | ||
106 | } | ||
107 | } | ||
108 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/NodeVariable.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/NodeVariable.java deleted file mode 100644 index 53c32e20..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/NodeVariable.java +++ /dev/null | |||
@@ -1,71 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.term; | ||
7 | |||
8 | import org.jetbrains.annotations.Nullable; | ||
9 | import tools.refinery.store.query.InvalidQueryException; | ||
10 | import tools.refinery.store.query.literal.ConstantLiteral; | ||
11 | import tools.refinery.store.query.literal.EquivalenceLiteral; | ||
12 | |||
13 | import java.util.Optional; | ||
14 | |||
15 | public final class NodeVariable extends Variable { | ||
16 | NodeVariable(@Nullable String name) { | ||
17 | super(name); | ||
18 | } | ||
19 | |||
20 | @Override | ||
21 | public Optional<Class<?>> tryGetType() { | ||
22 | return Optional.empty(); | ||
23 | } | ||
24 | |||
25 | @Override | ||
26 | public NodeVariable renew(@Nullable String name) { | ||
27 | return Variable.of(name); | ||
28 | } | ||
29 | |||
30 | @Override | ||
31 | public NodeVariable renew() { | ||
32 | return renew(getExplicitName()); | ||
33 | } | ||
34 | |||
35 | @Override | ||
36 | public boolean isNodeVariable() { | ||
37 | return true; | ||
38 | } | ||
39 | |||
40 | @Override | ||
41 | public boolean isDataVariable() { | ||
42 | return false; | ||
43 | } | ||
44 | |||
45 | @Override | ||
46 | public NodeVariable asNodeVariable() { | ||
47 | return this; | ||
48 | } | ||
49 | |||
50 | @Override | ||
51 | public <T> DataVariable<T> asDataVariable(Class<T> type) { | ||
52 | throw new InvalidQueryException("%s is a node variable".formatted(this)); | ||
53 | } | ||
54 | |||
55 | @Override | ||
56 | public int hashCodeWithSubstitution(int sequenceNumber) { | ||
57 | return sequenceNumber; | ||
58 | } | ||
59 | |||
60 | public ConstantLiteral isConstant(int value) { | ||
61 | return new ConstantLiteral(this, value); | ||
62 | } | ||
63 | |||
64 | public EquivalenceLiteral isEquivalent(NodeVariable other) { | ||
65 | return new EquivalenceLiteral(true, this, other); | ||
66 | } | ||
67 | |||
68 | public EquivalenceLiteral notEquivalent(NodeVariable other) { | ||
69 | return new EquivalenceLiteral(false, this, other); | ||
70 | } | ||
71 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/Parameter.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/Parameter.java deleted file mode 100644 index 577ac6e0..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/Parameter.java +++ /dev/null | |||
@@ -1,68 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.term; | ||
7 | |||
8 | import java.util.Objects; | ||
9 | import java.util.Optional; | ||
10 | |||
11 | public class Parameter { | ||
12 | public static final Parameter NODE_OUT = new Parameter(null); | ||
13 | |||
14 | private final Class<?> dataType; | ||
15 | private final ParameterDirection direction; | ||
16 | |||
17 | public Parameter(Class<?> dataType) { | ||
18 | this(dataType, ParameterDirection.OUT); | ||
19 | } | ||
20 | |||
21 | public Parameter(Class<?> dataType, ParameterDirection direction) { | ||
22 | this.dataType = dataType; | ||
23 | this.direction = direction; | ||
24 | } | ||
25 | |||
26 | public boolean isNodeVariable() { | ||
27 | return dataType == null; | ||
28 | } | ||
29 | |||
30 | public boolean isDataVariable() { | ||
31 | return !isNodeVariable(); | ||
32 | } | ||
33 | |||
34 | public Optional<Class<?>> tryGetType() { | ||
35 | return Optional.ofNullable(dataType); | ||
36 | } | ||
37 | |||
38 | public ParameterDirection getDirection() { | ||
39 | return direction; | ||
40 | } | ||
41 | |||
42 | public boolean matches(Parameter other) { | ||
43 | return Objects.equals(dataType, other.dataType) && direction == other.direction; | ||
44 | } | ||
45 | |||
46 | public boolean isAssignable(Variable variable) { | ||
47 | if (variable instanceof AnyDataVariable dataVariable) { | ||
48 | return dataVariable.getType().equals(dataType); | ||
49 | } else if (variable instanceof NodeVariable) { | ||
50 | return !isDataVariable(); | ||
51 | } else { | ||
52 | throw new IllegalArgumentException("Unknown variable " + variable); | ||
53 | } | ||
54 | } | ||
55 | |||
56 | @Override | ||
57 | public boolean equals(Object o) { | ||
58 | if (this == o) return true; | ||
59 | if (o == null || getClass() != o.getClass()) return false; | ||
60 | Parameter parameter = (Parameter) o; | ||
61 | return matches(parameter); | ||
62 | } | ||
63 | |||
64 | @Override | ||
65 | public int hashCode() { | ||
66 | return Objects.hash(dataType, direction); | ||
67 | } | ||
68 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/ParameterDirection.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/ParameterDirection.java deleted file mode 100644 index da83f3c3..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/ParameterDirection.java +++ /dev/null | |||
@@ -1,22 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.term; | ||
7 | |||
8 | public enum ParameterDirection { | ||
9 | OUT("out"), | ||
10 | IN("in"); | ||
11 | |||
12 | private final String name; | ||
13 | |||
14 | ParameterDirection(String name) { | ||
15 | this.name = name; | ||
16 | } | ||
17 | |||
18 | @Override | ||
19 | public String toString() { | ||
20 | return name; | ||
21 | } | ||
22 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/StatefulAggregate.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/StatefulAggregate.java deleted file mode 100644 index ab310556..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/StatefulAggregate.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 | */ | ||
6 | package tools.refinery.store.query.term; | ||
7 | |||
8 | public interface StatefulAggregate<R, T> { | ||
9 | void add(T value); | ||
10 | |||
11 | void remove(T value); | ||
12 | |||
13 | R getResult(); | ||
14 | |||
15 | boolean isEmpty(); | ||
16 | |||
17 | StatefulAggregate<R, T> deepCopy(); | ||
18 | |||
19 | default boolean contains(T value) { | ||
20 | throw new UnsupportedOperationException(); | ||
21 | } | ||
22 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/StatefulAggregator.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/StatefulAggregator.java deleted file mode 100644 index df746a90..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/StatefulAggregator.java +++ /dev/null | |||
@@ -1,28 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.term; | ||
7 | |||
8 | import java.util.stream.Stream; | ||
9 | |||
10 | public interface StatefulAggregator<R, T> extends Aggregator<R, T> { | ||
11 | StatefulAggregate<R, T> createEmptyAggregate(); | ||
12 | |||
13 | @Override | ||
14 | default R aggregateStream(Stream<T> stream) { | ||
15 | var accumulator = createEmptyAggregate(); | ||
16 | var iterator = stream.iterator(); | ||
17 | while (iterator.hasNext()) { | ||
18 | var value = iterator.next(); | ||
19 | accumulator.add(value); | ||
20 | } | ||
21 | return accumulator.getResult(); | ||
22 | } | ||
23 | |||
24 | @Override | ||
25 | default R getEmptyResult() { | ||
26 | return createEmptyAggregate().getResult(); | ||
27 | } | ||
28 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/StatelessAggregator.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/StatelessAggregator.java deleted file mode 100644 index a094919e..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/StatelessAggregator.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 | */ | ||
6 | package tools.refinery.store.query.term; | ||
7 | |||
8 | import java.util.stream.Stream; | ||
9 | |||
10 | public interface StatelessAggregator<R, T> extends Aggregator<R, T> { | ||
11 | R add(R current, T value); | ||
12 | |||
13 | R remove(R current, T value); | ||
14 | |||
15 | @Override | ||
16 | default R aggregateStream(Stream<T> stream) { | ||
17 | var accumulator = getEmptyResult(); | ||
18 | var iterator = stream.iterator(); | ||
19 | while (iterator.hasNext()) { | ||
20 | var value = iterator.next(); | ||
21 | accumulator = add(accumulator, value); | ||
22 | } | ||
23 | return accumulator; | ||
24 | } | ||
25 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/Term.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/Term.java deleted file mode 100644 index e6818b88..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/Term.java +++ /dev/null | |||
@@ -1,26 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.term; | ||
7 | |||
8 | import tools.refinery.store.query.literal.AssignLiteral; | ||
9 | import tools.refinery.store.query.literal.Literal; | ||
10 | import tools.refinery.store.query.substitution.Substitution; | ||
11 | import tools.refinery.store.query.valuation.Valuation; | ||
12 | |||
13 | public non-sealed interface Term<T> extends AnyTerm, AssignedValue<T> { | ||
14 | @Override | ||
15 | Class<T> getType(); | ||
16 | |||
17 | T evaluate(Valuation valuation); | ||
18 | |||
19 | @Override | ||
20 | Term<T> substitute(Substitution substitution); | ||
21 | |||
22 | @Override | ||
23 | default Literal toLiteral(DataVariable<T> targetVariable) { | ||
24 | return new AssignLiteral<>(targetVariable, this); | ||
25 | } | ||
26 | } | ||
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 deleted file mode 100644 index a464ece5..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/UnaryTerm.java +++ /dev/null | |||
@@ -1,74 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.term; | ||
7 | |||
8 | import tools.refinery.store.query.InvalidQueryException; | ||
9 | import tools.refinery.store.query.equality.LiteralEqualityHelper; | ||
10 | import tools.refinery.store.query.equality.LiteralHashCodeHelper; | ||
11 | import tools.refinery.store.query.substitution.Substitution; | ||
12 | import tools.refinery.store.query.valuation.Valuation; | ||
13 | |||
14 | import java.util.Objects; | ||
15 | import java.util.Set; | ||
16 | |||
17 | // {@link Object#equals(Object)} is implemented by {@link AbstractTerm}. | ||
18 | @SuppressWarnings("squid:S2160") | ||
19 | public abstract class UnaryTerm<R, T> extends AbstractTerm<R> { | ||
20 | private final Class<T> bodyType; | ||
21 | private final Term<T> body; | ||
22 | |||
23 | protected UnaryTerm(Class<R> type, Class<T> bodyType, Term<T> body) { | ||
24 | super(type); | ||
25 | if (!body.getType().equals(bodyType)) { | ||
26 | throw new InvalidQueryException("Expected body %s to be of type %s, got %s instead".formatted(body, | ||
27 | bodyType.getName(), body.getType().getName())); | ||
28 | } | ||
29 | this.bodyType = bodyType; | ||
30 | this.body = body; | ||
31 | } | ||
32 | |||
33 | public Class<T> getBodyType() { | ||
34 | return bodyType; | ||
35 | } | ||
36 | |||
37 | public Term<T> getBody() { | ||
38 | return body; | ||
39 | } | ||
40 | |||
41 | @Override | ||
42 | public R evaluate(Valuation valuation) { | ||
43 | var bodyValue = body.evaluate(valuation); | ||
44 | return bodyValue == null ? null : doEvaluate(bodyValue); | ||
45 | } | ||
46 | |||
47 | protected abstract R doEvaluate(T bodyValue); | ||
48 | |||
49 | @Override | ||
50 | public boolean equalsWithSubstitution(LiteralEqualityHelper helper, AnyTerm other) { | ||
51 | if (!super.equalsWithSubstitution(helper, other)) { | ||
52 | return false; | ||
53 | } | ||
54 | var otherUnaryTerm = (UnaryTerm<?, ?>) other; | ||
55 | return bodyType.equals(otherUnaryTerm.bodyType) && body.equalsWithSubstitution(helper, otherUnaryTerm.body); | ||
56 | } | ||
57 | |||
58 | @Override | ||
59 | public int hashCodeWithSubstitution(LiteralHashCodeHelper helper) { | ||
60 | return Objects.hash(super.hashCodeWithSubstitution(helper), bodyType, body.hashCodeWithSubstitution(helper)); | ||
61 | } | ||
62 | |||
63 | @Override | ||
64 | public Term<R> substitute(Substitution substitution) { | ||
65 | return doSubstitute(substitution, body.substitute(substitution)); | ||
66 | } | ||
67 | |||
68 | protected abstract Term<R> doSubstitute(Substitution substitution, Term<T> substitutedBody); | ||
69 | |||
70 | @Override | ||
71 | public Set<AnyDataVariable> getInputVariables() { | ||
72 | return body.getInputVariables(); | ||
73 | } | ||
74 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/Variable.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/Variable.java deleted file mode 100644 index 1b553704..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/Variable.java +++ /dev/null | |||
@@ -1,88 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.term; | ||
7 | |||
8 | import org.jetbrains.annotations.Nullable; | ||
9 | import tools.refinery.store.query.dnf.DnfUtils; | ||
10 | |||
11 | import java.util.Objects; | ||
12 | import java.util.Optional; | ||
13 | |||
14 | public abstract sealed class Variable permits AnyDataVariable, NodeVariable { | ||
15 | private final String explicitName; | ||
16 | private final String uniqueName; | ||
17 | |||
18 | protected Variable(String name) { | ||
19 | this.explicitName = name; | ||
20 | uniqueName = DnfUtils.generateUniqueName(name); | ||
21 | } | ||
22 | |||
23 | public abstract Optional<Class<?>> tryGetType(); | ||
24 | |||
25 | public String getName() { | ||
26 | return explicitName == null ? uniqueName : explicitName; | ||
27 | } | ||
28 | |||
29 | protected String getExplicitName() { | ||
30 | return explicitName; | ||
31 | } | ||
32 | |||
33 | public boolean isExplicitlyNamed() { | ||
34 | return explicitName != null; | ||
35 | } | ||
36 | |||
37 | public String getUniqueName() { | ||
38 | return uniqueName; | ||
39 | } | ||
40 | |||
41 | public abstract Variable renew(@Nullable String name); | ||
42 | |||
43 | public abstract Variable renew(); | ||
44 | |||
45 | public abstract boolean isNodeVariable(); | ||
46 | |||
47 | public abstract boolean isDataVariable(); | ||
48 | |||
49 | public abstract NodeVariable asNodeVariable(); | ||
50 | |||
51 | public abstract <T> DataVariable<T> asDataVariable(Class<T> type); | ||
52 | |||
53 | public abstract int hashCodeWithSubstitution(int sequenceNumber); | ||
54 | |||
55 | @Override | ||
56 | public String toString() { | ||
57 | return getName(); | ||
58 | } | ||
59 | |||
60 | @Override | ||
61 | public boolean equals(Object o) { | ||
62 | if (this == o) return true; | ||
63 | if (o == null || getClass() != o.getClass()) return false; | ||
64 | Variable variable = (Variable) o; | ||
65 | return Objects.equals(uniqueName, variable.uniqueName); | ||
66 | } | ||
67 | |||
68 | @Override | ||
69 | public int hashCode() { | ||
70 | return Objects.hash(uniqueName); | ||
71 | } | ||
72 | |||
73 | public static NodeVariable of(@Nullable String name) { | ||
74 | return new NodeVariable(name); | ||
75 | } | ||
76 | |||
77 | public static NodeVariable of() { | ||
78 | return of((String) null); | ||
79 | } | ||
80 | |||
81 | public static <T> DataVariable<T> of(@Nullable String name, Class<T> type) { | ||
82 | return new DataVariable<>(name, type); | ||
83 | } | ||
84 | |||
85 | public static <T> DataVariable<T> of(Class<T> type) { | ||
86 | return of(null, type); | ||
87 | } | ||
88 | } | ||
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 deleted file mode 100644 index f9e1c06f..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/bool/BoolAndTerm.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 | */ | ||
6 | package tools.refinery.store.query.term.bool; | ||
7 | |||
8 | import tools.refinery.store.query.substitution.Substitution; | ||
9 | import tools.refinery.store.query.term.Term; | ||
10 | |||
11 | public 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 deleted file mode 100644 index a85aa63a..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/bool/BoolBinaryTerm.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 | */ | ||
6 | package tools.refinery.store.query.term.bool; | ||
7 | |||
8 | import tools.refinery.store.query.term.BinaryTerm; | ||
9 | import tools.refinery.store.query.term.Term; | ||
10 | |||
11 | public 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/BoolNotTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/bool/BoolNotTerm.java deleted file mode 100644 index 8d3382b3..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/bool/BoolNotTerm.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 | */ | ||
6 | package tools.refinery.store.query.term.bool; | ||
7 | |||
8 | import tools.refinery.store.query.substitution.Substitution; | ||
9 | import tools.refinery.store.query.term.Term; | ||
10 | import tools.refinery.store.query.term.UnaryTerm; | ||
11 | |||
12 | public class BoolNotTerm extends UnaryTerm<Boolean, Boolean> { | ||
13 | protected BoolNotTerm(Term<Boolean> body) { | ||
14 | super(Boolean.class, Boolean.class, body); | ||
15 | } | ||
16 | |||
17 | @Override | ||
18 | protected Term<Boolean> doSubstitute(Substitution substitution, Term<Boolean> substitutedBody) { | ||
19 | return new BoolNotTerm(substitutedBody); | ||
20 | } | ||
21 | |||
22 | @Override | ||
23 | protected Boolean doEvaluate(Boolean bodyValue) { | ||
24 | return !bodyValue; | ||
25 | } | ||
26 | |||
27 | @Override | ||
28 | public String toString() { | ||
29 | return "(!%s)".formatted(getBody()); | ||
30 | } | ||
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 deleted file mode 100644 index b5195d52..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/bool/BoolOrTerm.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 | */ | ||
6 | package tools.refinery.store.query.term.bool; | ||
7 | |||
8 | import tools.refinery.store.query.substitution.Substitution; | ||
9 | import tools.refinery.store.query.term.Term; | ||
10 | |||
11 | public 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 deleted file mode 100644 index fa54f686..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/bool/BoolTerms.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 | */ | ||
6 | package tools.refinery.store.query.term.bool; | ||
7 | |||
8 | import tools.refinery.store.query.term.ConstantTerm; | ||
9 | import tools.refinery.store.query.term.Term; | ||
10 | |||
11 | public final class BoolTerms { | ||
12 | private BoolTerms() { | ||
13 | throw new IllegalArgumentException("This is a static utility class and should not be instantiated directly"); | ||
14 | } | ||
15 | |||
16 | public static Term<Boolean> constant(Boolean value) { | ||
17 | return new ConstantTerm<>(Boolean.class, value); | ||
18 | } | ||
19 | |||
20 | public static Term<Boolean> not(Term<Boolean> body) { | ||
21 | return new BoolNotTerm(body); | ||
22 | } | ||
23 | |||
24 | public static Term<Boolean> and(Term<Boolean> left, Term<Boolean> right) { | ||
25 | return new BoolAndTerm(left, right); | ||
26 | } | ||
27 | |||
28 | public static Term<Boolean> or(Term<Boolean> left, Term<Boolean> right) { | ||
29 | return new BoolOrTerm(left, right); | ||
30 | } | ||
31 | |||
32 | public static Term<Boolean> xor(Term<Boolean> left, Term<Boolean> right) { | ||
33 | return new BoolXorTerm(left, right); | ||
34 | } | ||
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 deleted file mode 100644 index 7478b8a5..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/bool/BoolXorTerm.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 | */ | ||
6 | package tools.refinery.store.query.term.bool; | ||
7 | |||
8 | import tools.refinery.store.query.substitution.Substitution; | ||
9 | import tools.refinery.store.query.term.Term; | ||
10 | |||
11 | public 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/comparable/ComparisonTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/comparable/ComparisonTerm.java deleted file mode 100644 index 5ca5a0a1..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/comparable/ComparisonTerm.java +++ /dev/null | |||
@@ -1,19 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.term.comparable; | ||
7 | |||
8 | import tools.refinery.store.query.term.BinaryTerm; | ||
9 | import tools.refinery.store.query.term.Term; | ||
10 | |||
11 | public 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 deleted file mode 100644 index b8cf36f8..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/comparable/EqTerm.java +++ /dev/null | |||
@@ -1,30 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.term.comparable; | ||
7 | |||
8 | import tools.refinery.store.query.substitution.Substitution; | ||
9 | import tools.refinery.store.query.term.Term; | ||
10 | |||
11 | public 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 deleted file mode 100644 index b109eb1a..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/comparable/GreaterEqTerm.java +++ /dev/null | |||
@@ -1,30 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.term.comparable; | ||
7 | |||
8 | import tools.refinery.store.query.substitution.Substitution; | ||
9 | import tools.refinery.store.query.term.Term; | ||
10 | |||
11 | public 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 deleted file mode 100644 index 1b67f8b5..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/comparable/GreaterTerm.java +++ /dev/null | |||
@@ -1,30 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.term.comparable; | ||
7 | |||
8 | import tools.refinery.store.query.substitution.Substitution; | ||
9 | import tools.refinery.store.query.term.Term; | ||
10 | |||
11 | public 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 deleted file mode 100644 index 1b34535f..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/comparable/LessEqTerm.java +++ /dev/null | |||
@@ -1,30 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.term.comparable; | ||
7 | |||
8 | import tools.refinery.store.query.substitution.Substitution; | ||
9 | import tools.refinery.store.query.term.Term; | ||
10 | |||
11 | public 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 deleted file mode 100644 index 44e70902..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/comparable/LessTerm.java +++ /dev/null | |||
@@ -1,30 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.term.comparable; | ||
7 | |||
8 | import tools.refinery.store.query.substitution.Substitution; | ||
9 | import tools.refinery.store.query.term.Term; | ||
10 | |||
11 | public 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 deleted file mode 100644 index 1f9734c4..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/comparable/NotEqTerm.java +++ /dev/null | |||
@@ -1,30 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.term.comparable; | ||
7 | |||
8 | import tools.refinery.store.query.substitution.Substitution; | ||
9 | import tools.refinery.store.query.term.Term; | ||
10 | |||
11 | public 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 deleted file mode 100644 index dbea3efc..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntAddTerm.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 | */ | ||
6 | package tools.refinery.store.query.term.int_; | ||
7 | |||
8 | import tools.refinery.store.query.substitution.Substitution; | ||
9 | import tools.refinery.store.query.term.Term; | ||
10 | |||
11 | public 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_/IntBinaryTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntBinaryTerm.java deleted file mode 100644 index 27ced4e4..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntBinaryTerm.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 | */ | ||
6 | package tools.refinery.store.query.term.int_; | ||
7 | |||
8 | import tools.refinery.store.query.term.BinaryTerm; | ||
9 | import tools.refinery.store.query.term.Term; | ||
10 | |||
11 | public 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_/IntDivTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntDivTerm.java deleted file mode 100644 index 2a35058c..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntDivTerm.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 | */ | ||
6 | package tools.refinery.store.query.term.int_; | ||
7 | |||
8 | import tools.refinery.store.query.substitution.Substitution; | ||
9 | import tools.refinery.store.query.term.Term; | ||
10 | |||
11 | public 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_/IntMaxTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntMaxTerm.java deleted file mode 100644 index f81fc509..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntMaxTerm.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 | */ | ||
6 | package tools.refinery.store.query.term.int_; | ||
7 | |||
8 | import tools.refinery.store.query.substitution.Substitution; | ||
9 | import tools.refinery.store.query.term.Term; | ||
10 | |||
11 | public 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 deleted file mode 100644 index 89182e26..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntMinTerm.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 | */ | ||
6 | package tools.refinery.store.query.term.int_; | ||
7 | |||
8 | import tools.refinery.store.query.substitution.Substitution; | ||
9 | import tools.refinery.store.query.term.Term; | ||
10 | |||
11 | public 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 deleted file mode 100644 index 709aa5ba..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntMinusTerm.java +++ /dev/null | |||
@@ -1,30 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.term.int_; | ||
7 | |||
8 | import tools.refinery.store.query.substitution.Substitution; | ||
9 | import tools.refinery.store.query.term.Term; | ||
10 | |||
11 | public 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 deleted file mode 100644 index 89d4c5f4..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntMulTerm.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 | */ | ||
6 | package tools.refinery.store.query.term.int_; | ||
7 | |||
8 | import tools.refinery.store.query.substitution.Substitution; | ||
9 | import tools.refinery.store.query.term.Term; | ||
10 | |||
11 | public 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 deleted file mode 100644 index aef83bb4..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntPlusTerm.java +++ /dev/null | |||
@@ -1,30 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.term.int_; | ||
7 | |||
8 | import tools.refinery.store.query.substitution.Substitution; | ||
9 | import tools.refinery.store.query.term.Term; | ||
10 | |||
11 | public 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 deleted file mode 100644 index d5af97a1..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntPowTerm.java +++ /dev/null | |||
@@ -1,43 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.term.int_; | ||
7 | |||
8 | import tools.refinery.store.query.substitution.Substitution; | ||
9 | import tools.refinery.store.query.term.Term; | ||
10 | |||
11 | public 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 deleted file mode 100644 index 2c27afb1..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntSubTerm.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 | */ | ||
6 | package tools.refinery.store.query.term.int_; | ||
7 | |||
8 | import tools.refinery.store.query.substitution.Substitution; | ||
9 | import tools.refinery.store.query.term.Term; | ||
10 | |||
11 | public 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_/IntSumAggregator.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntSumAggregator.java deleted file mode 100644 index cd718c53..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntSumAggregator.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 | */ | ||
6 | package tools.refinery.store.query.term.int_; | ||
7 | |||
8 | import tools.refinery.store.query.term.StatelessAggregator; | ||
9 | |||
10 | public final class IntSumAggregator implements StatelessAggregator<Integer, Integer> { | ||
11 | public static final IntSumAggregator INSTANCE = new IntSumAggregator(); | ||
12 | |||
13 | private IntSumAggregator() { | ||
14 | } | ||
15 | |||
16 | @Override | ||
17 | public Class<Integer> getResultType() { | ||
18 | return Integer.class; | ||
19 | } | ||
20 | |||
21 | @Override | ||
22 | public Class<Integer> getInputType() { | ||
23 | return Integer.class; | ||
24 | } | ||
25 | |||
26 | @Override | ||
27 | public Integer getEmptyResult() { | ||
28 | return 0; | ||
29 | } | ||
30 | |||
31 | @Override | ||
32 | public Integer add(Integer current, Integer value) { | ||
33 | return current + value; | ||
34 | } | ||
35 | |||
36 | @Override | ||
37 | public Integer remove(Integer current, Integer value) { | ||
38 | return current - value; | ||
39 | } | ||
40 | } | ||
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 deleted file mode 100644 index acb98b94..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntTerms.java +++ /dev/null | |||
@@ -1,94 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.term.int_; | ||
7 | |||
8 | import tools.refinery.store.query.term.Aggregator; | ||
9 | import tools.refinery.store.query.term.ConstantTerm; | ||
10 | import tools.refinery.store.query.term.ExtremeValueAggregator; | ||
11 | import tools.refinery.store.query.term.Term; | ||
12 | import tools.refinery.store.query.term.comparable.*; | ||
13 | |||
14 | import java.util.Comparator; | ||
15 | |||
16 | public final class IntTerms { | ||
17 | public static final Aggregator<Integer, Integer> INT_SUM = IntSumAggregator.INSTANCE; | ||
18 | public static final Aggregator<Integer, Integer> INT_MIN = new ExtremeValueAggregator<>(Integer.class, | ||
19 | Integer.MAX_VALUE); | ||
20 | public static final Aggregator<Integer, Integer> INT_MAX = new ExtremeValueAggregator<>(Integer.class, | ||
21 | Integer.MIN_VALUE, Comparator.reverseOrder()); | ||
22 | |||
23 | private IntTerms() { | ||
24 | throw new IllegalArgumentException("This is a static utility class and should not be instantiated directly"); | ||
25 | } | ||
26 | |||
27 | public static Term<Integer> constant(Integer value) { | ||
28 | return new ConstantTerm<>(Integer.class, value); | ||
29 | } | ||
30 | |||
31 | public static Term<Integer> plus(Term<Integer> body) { | ||
32 | return new IntPlusTerm(body); | ||
33 | } | ||
34 | |||
35 | public static Term<Integer> minus(Term<Integer> body) { | ||
36 | return new IntMinusTerm(body); | ||
37 | } | ||
38 | |||
39 | public static Term<Integer> add(Term<Integer> left, Term<Integer> right) { | ||
40 | return new IntAddTerm(left, right); | ||
41 | } | ||
42 | |||
43 | public static Term<Integer> sub(Term<Integer> left, Term<Integer> right) { | ||
44 | return new IntSubTerm(left, right); | ||
45 | } | ||
46 | |||
47 | public static Term<Integer> mul(Term<Integer> left, Term<Integer> right) { | ||
48 | return new IntMulTerm(left, right); | ||
49 | } | ||
50 | |||
51 | public static Term<Integer> div(Term<Integer> left, Term<Integer> right) { | ||
52 | return new IntDivTerm(left, right); | ||
53 | } | ||
54 | |||
55 | public static Term<Integer> pow(Term<Integer> left, Term<Integer> right) { | ||
56 | return new IntPowTerm(left, right); | ||
57 | } | ||
58 | |||
59 | public static Term<Integer> min(Term<Integer> left, Term<Integer> right) { | ||
60 | return new IntMinTerm(left, right); | ||
61 | } | ||
62 | |||
63 | public static Term<Integer> max(Term<Integer> left, Term<Integer> right) { | ||
64 | return new IntMaxTerm(left, right); | ||
65 | } | ||
66 | |||
67 | public static Term<Boolean> eq(Term<Integer> left, Term<Integer> right) { | ||
68 | return new EqTerm<>(Integer.class, left, right); | ||
69 | } | ||
70 | |||
71 | public static Term<Boolean> notEq(Term<Integer> left, Term<Integer> right) { | ||
72 | return new NotEqTerm<>(Integer.class, left, right); | ||
73 | } | ||
74 | |||
75 | public static Term<Boolean> less(Term<Integer> left, Term<Integer> right) { | ||
76 | return new LessTerm<>(Integer.class, left, right); | ||
77 | } | ||
78 | |||
79 | public static Term<Boolean> lessEq(Term<Integer> left, Term<Integer> right) { | ||
80 | return new LessEqTerm<>(Integer.class, left, right); | ||
81 | } | ||
82 | |||
83 | public static Term<Boolean> greater(Term<Integer> left, Term<Integer> right) { | ||
84 | return new GreaterTerm<>(Integer.class, left, right); | ||
85 | } | ||
86 | |||
87 | public static Term<Boolean> greaterEq(Term<Integer> left, Term<Integer> right) { | ||
88 | return new GreaterEqTerm<>(Integer.class, left, right); | ||
89 | } | ||
90 | |||
91 | public static Term<Integer> asInt(Term<Double> body) { | ||
92 | return new RealToIntTerm(body); | ||
93 | } | ||
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 deleted file mode 100644 index 49b4c647..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntUnaryTerm.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 | */ | ||
6 | package tools.refinery.store.query.term.int_; | ||
7 | |||
8 | import tools.refinery.store.query.term.Term; | ||
9 | import tools.refinery.store.query.term.UnaryTerm; | ||
10 | |||
11 | public 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 deleted file mode 100644 index 7d383562..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/RealToIntTerm.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 | */ | ||
6 | package tools.refinery.store.query.term.int_; | ||
7 | |||
8 | import tools.refinery.store.query.substitution.Substitution; | ||
9 | import tools.refinery.store.query.term.Term; | ||
10 | import tools.refinery.store.query.term.UnaryTerm; | ||
11 | |||
12 | public class RealToIntTerm extends UnaryTerm<Integer, Double> { | ||
13 | protected RealToIntTerm(Term<Double> body) { | ||
14 | super(Integer.class, Double.class, body); | ||
15 | } | ||
16 | |||
17 | @Override | ||
18 | protected Integer doEvaluate(Double bodyValue) { | ||
19 | return bodyValue.isNaN() ? null : bodyValue.intValue(); | ||
20 | } | ||
21 | |||
22 | @Override | ||
23 | protected Term<Integer> doSubstitute(Substitution substitution, Term<Double> substitutedBody) { | ||
24 | return new RealToIntTerm(substitutedBody); | ||
25 | } | ||
26 | |||
27 | @Override | ||
28 | public String toString() { | ||
29 | return "(%s as int)".formatted(getBody()); | ||
30 | } | ||
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 deleted file mode 100644 index 2f53117a..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/IntToRealTerm.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 | */ | ||
6 | package tools.refinery.store.query.term.real; | ||
7 | |||
8 | import tools.refinery.store.query.substitution.Substitution; | ||
9 | import tools.refinery.store.query.term.Term; | ||
10 | import tools.refinery.store.query.term.UnaryTerm; | ||
11 | |||
12 | public class IntToRealTerm extends UnaryTerm<Double, Integer> { | ||
13 | protected IntToRealTerm(Term<Integer> body) { | ||
14 | super(Double.class, Integer.class, body); | ||
15 | } | ||
16 | |||
17 | @Override | ||
18 | protected Term<Double> doSubstitute(Substitution substitution, Term<Integer> substitutedBody) { | ||
19 | return new IntToRealTerm(substitutedBody); | ||
20 | } | ||
21 | |||
22 | @Override | ||
23 | protected Double doEvaluate(Integer bodyValue) { | ||
24 | return bodyValue.doubleValue(); | ||
25 | } | ||
26 | |||
27 | @Override | ||
28 | public String toString() { | ||
29 | return "(%s as real)".formatted(getBody()); | ||
30 | } | ||
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 deleted file mode 100644 index 33fc9e41..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealAddTerm.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 | */ | ||
6 | package tools.refinery.store.query.term.real; | ||
7 | |||
8 | import tools.refinery.store.query.substitution.Substitution; | ||
9 | import tools.refinery.store.query.term.Term; | ||
10 | |||
11 | public 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/RealBinaryTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealBinaryTerm.java deleted file mode 100644 index 000f3623..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealBinaryTerm.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 | */ | ||
6 | package tools.refinery.store.query.term.real; | ||
7 | |||
8 | import tools.refinery.store.query.term.BinaryTerm; | ||
9 | import tools.refinery.store.query.term.Term; | ||
10 | |||
11 | public 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/RealDivTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealDivTerm.java deleted file mode 100644 index 1e55bf42..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealDivTerm.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 | */ | ||
6 | package tools.refinery.store.query.term.real; | ||
7 | |||
8 | import tools.refinery.store.query.substitution.Substitution; | ||
9 | import tools.refinery.store.query.term.Term; | ||
10 | |||
11 | public 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/RealMaxTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealMaxTerm.java deleted file mode 100644 index 2a249496..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealMaxTerm.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 | */ | ||
6 | package tools.refinery.store.query.term.real; | ||
7 | |||
8 | import tools.refinery.store.query.substitution.Substitution; | ||
9 | import tools.refinery.store.query.term.Term; | ||
10 | |||
11 | public 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 deleted file mode 100644 index 2eb4cc1e..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealMinTerm.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 | */ | ||
6 | package tools.refinery.store.query.term.real; | ||
7 | |||
8 | import tools.refinery.store.query.substitution.Substitution; | ||
9 | import tools.refinery.store.query.term.Term; | ||
10 | |||
11 | public 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 deleted file mode 100644 index 4afec7a1..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealMinusTerm.java +++ /dev/null | |||
@@ -1,30 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.term.real; | ||
7 | |||
8 | import tools.refinery.store.query.substitution.Substitution; | ||
9 | import tools.refinery.store.query.term.Term; | ||
10 | |||
11 | public 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 deleted file mode 100644 index ec95ac6f..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealMulTerm.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 | */ | ||
6 | package tools.refinery.store.query.term.real; | ||
7 | |||
8 | import tools.refinery.store.query.substitution.Substitution; | ||
9 | import tools.refinery.store.query.term.Term; | ||
10 | |||
11 | public 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 deleted file mode 100644 index 64dd2e70..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealPlusTerm.java +++ /dev/null | |||
@@ -1,30 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.term.real; | ||
7 | |||
8 | import tools.refinery.store.query.substitution.Substitution; | ||
9 | import tools.refinery.store.query.term.Term; | ||
10 | |||
11 | public 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 deleted file mode 100644 index 11c952ea..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealPowTerm.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 | */ | ||
6 | package tools.refinery.store.query.term.real; | ||
7 | |||
8 | import tools.refinery.store.query.substitution.Substitution; | ||
9 | import tools.refinery.store.query.term.Term; | ||
10 | |||
11 | public 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 deleted file mode 100644 index 8cc701ed..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealSubTerm.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 | */ | ||
6 | package tools.refinery.store.query.term.real; | ||
7 | |||
8 | import tools.refinery.store.query.substitution.Substitution; | ||
9 | import tools.refinery.store.query.term.Term; | ||
10 | |||
11 | public 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/RealSumAggregator.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealSumAggregator.java deleted file mode 100644 index d21048e9..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealSumAggregator.java +++ /dev/null | |||
@@ -1,90 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.term.real; | ||
7 | |||
8 | import tools.refinery.store.query.term.StatefulAggregate; | ||
9 | import tools.refinery.store.query.term.StatefulAggregator; | ||
10 | |||
11 | import java.util.Map; | ||
12 | import java.util.TreeMap; | ||
13 | |||
14 | public final class RealSumAggregator implements StatefulAggregator<Double, Double> { | ||
15 | public static final RealSumAggregator INSTANCE = new RealSumAggregator(); | ||
16 | |||
17 | private RealSumAggregator() { | ||
18 | } | ||
19 | |||
20 | @Override | ||
21 | public Class<Double> getResultType() { | ||
22 | return Double.class; | ||
23 | } | ||
24 | |||
25 | @Override | ||
26 | public Class<Double> getInputType() { | ||
27 | return Double.class; | ||
28 | } | ||
29 | |||
30 | @Override | ||
31 | public StatefulAggregate<Double, Double> createEmptyAggregate() { | ||
32 | return new Aggregate(); | ||
33 | } | ||
34 | |||
35 | @Override | ||
36 | public Double getEmptyResult() { | ||
37 | return 0d; | ||
38 | } | ||
39 | |||
40 | private static class Aggregate implements StatefulAggregate<Double, Double> { | ||
41 | private final Map<Double, Integer> values; | ||
42 | |||
43 | public Aggregate() { | ||
44 | values = new TreeMap<>(); | ||
45 | } | ||
46 | |||
47 | private Aggregate(Aggregate other) { | ||
48 | values = new TreeMap<>(other.values); | ||
49 | } | ||
50 | |||
51 | @Override | ||
52 | public void add(Double value) { | ||
53 | values.compute(value, (ignoredValue, currentCount) -> currentCount == null ? 1 : currentCount + 1); | ||
54 | } | ||
55 | |||
56 | @Override | ||
57 | public void remove(Double value) { | ||
58 | values.compute(value, (theValue, currentCount) -> { | ||
59 | if (currentCount == null || currentCount <= 0) { | ||
60 | throw new IllegalStateException("Invalid count %d for value %f".formatted(currentCount, theValue)); | ||
61 | } | ||
62 | return currentCount.equals(1) ? null : currentCount - 1; | ||
63 | }); | ||
64 | } | ||
65 | |||
66 | @Override | ||
67 | public Double getResult() { | ||
68 | return values.entrySet() | ||
69 | .stream() | ||
70 | .mapToDouble(entry -> entry.getKey() * entry.getValue()) | ||
71 | .reduce(Double::sum) | ||
72 | .orElse(0d); | ||
73 | } | ||
74 | |||
75 | @Override | ||
76 | public boolean isEmpty() { | ||
77 | return values.isEmpty(); | ||
78 | } | ||
79 | |||
80 | @Override | ||
81 | public StatefulAggregate<Double, Double> deepCopy() { | ||
82 | return new Aggregate(this); | ||
83 | } | ||
84 | |||
85 | @Override | ||
86 | public boolean contains(Double value) { | ||
87 | return values.containsKey(value); | ||
88 | } | ||
89 | } | ||
90 | } | ||
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 deleted file mode 100644 index 79220358..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealTerms.java +++ /dev/null | |||
@@ -1,94 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.term.real; | ||
7 | |||
8 | import tools.refinery.store.query.term.Aggregator; | ||
9 | import tools.refinery.store.query.term.ConstantTerm; | ||
10 | import tools.refinery.store.query.term.ExtremeValueAggregator; | ||
11 | import tools.refinery.store.query.term.Term; | ||
12 | import tools.refinery.store.query.term.comparable.*; | ||
13 | |||
14 | import java.util.Comparator; | ||
15 | |||
16 | public final class RealTerms { | ||
17 | public static final Aggregator<Double, Double> REAL_SUM = RealSumAggregator.INSTANCE; | ||
18 | public static final Aggregator<Double, Double> REAL_MIN = new ExtremeValueAggregator<>(Double.class, | ||
19 | Double.POSITIVE_INFINITY); | ||
20 | public static final Aggregator<Double, Double> REAL_MAX = new ExtremeValueAggregator<>(Double.class, | ||
21 | Double.NEGATIVE_INFINITY, Comparator.reverseOrder()); | ||
22 | |||
23 | private RealTerms() { | ||
24 | throw new IllegalArgumentException("This is a static utility class and should not be instantiated directly"); | ||
25 | } | ||
26 | |||
27 | public static Term<Double> constant(Double value) { | ||
28 | return new ConstantTerm<>(Double.class, value); | ||
29 | } | ||
30 | |||
31 | public static Term<Double> plus(Term<Double> body) { | ||
32 | return new RealPlusTerm(body); | ||
33 | } | ||
34 | |||
35 | public static Term<Double> minus(Term<Double> body) { | ||
36 | return new RealMinusTerm(body); | ||
37 | } | ||
38 | |||
39 | public static Term<Double> add(Term<Double> left, Term<Double> right) { | ||
40 | return new RealAddTerm(left, right); | ||
41 | } | ||
42 | |||
43 | public static Term<Double> sub(Term<Double> left, Term<Double> right) { | ||
44 | return new RealSubTerm(left, right); | ||
45 | } | ||
46 | |||
47 | public static Term<Double> mul(Term<Double> left, Term<Double> right) { | ||
48 | return new RealMulTerm(left, right); | ||
49 | } | ||
50 | |||
51 | public static Term<Double> div(Term<Double> left, Term<Double> right) { | ||
52 | return new RealDivTerm(left, right); | ||
53 | } | ||
54 | |||
55 | public static Term<Double> pow(Term<Double> left, Term<Double> right) { | ||
56 | return new RealPowTerm(left, right); | ||
57 | } | ||
58 | |||
59 | public static Term<Double> min(Term<Double> left, Term<Double> right) { | ||
60 | return new RealMinTerm(left, right); | ||
61 | } | ||
62 | |||
63 | public static Term<Double> max(Term<Double> left, Term<Double> right) { | ||
64 | return new RealMaxTerm(left, right); | ||
65 | } | ||
66 | |||
67 | public static Term<Boolean> eq(Term<Double> left, Term<Double> right) { | ||
68 | return new EqTerm<>(Double.class, left, right); | ||
69 | } | ||
70 | |||
71 | public static Term<Boolean> notEq(Term<Double> left, Term<Double> right) { | ||
72 | return new NotEqTerm<>(Double.class, left, right); | ||
73 | } | ||
74 | |||
75 | public static Term<Boolean> less(Term<Double> left, Term<Double> right) { | ||
76 | return new LessTerm<>(Double.class, left, right); | ||
77 | } | ||
78 | |||
79 | public static Term<Boolean> lessEq(Term<Double> left, Term<Double> right) { | ||
80 | return new LessEqTerm<>(Double.class, left, right); | ||
81 | } | ||
82 | |||
83 | public static Term<Boolean> greater(Term<Double> left, Term<Double> right) { | ||
84 | return new GreaterTerm<>(Double.class, left, right); | ||
85 | } | ||
86 | |||
87 | public static Term<Boolean> greaterEq(Term<Double> left, Term<Double> right) { | ||
88 | return new GreaterEqTerm<>(Double.class, left, right); | ||
89 | } | ||
90 | |||
91 | public static Term<Double> asReal(Term<Integer> body) { | ||
92 | return new IntToRealTerm(body); | ||
93 | } | ||
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 deleted file mode 100644 index d41c4ed9..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealUnaryTerm.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 | */ | ||
6 | package tools.refinery.store.query.term.real; | ||
7 | |||
8 | import tools.refinery.store.query.term.Term; | ||
9 | import tools.refinery.store.query.term.UnaryTerm; | ||
10 | |||
11 | public 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 deleted file mode 100644 index 68905f51..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/uppercardinality/UpperCardinalityAddTerm.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 | */ | ||
6 | package tools.refinery.store.query.term.uppercardinality; | ||
7 | |||
8 | import tools.refinery.store.query.substitution.Substitution; | ||
9 | import tools.refinery.store.query.term.Term; | ||
10 | import tools.refinery.store.representation.cardinality.UpperCardinality; | ||
11 | |||
12 | public 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 deleted file mode 100644 index 0cf8fe44..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/uppercardinality/UpperCardinalityBinaryTerm.java +++ /dev/null | |||
@@ -1,17 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.term.uppercardinality; | ||
7 | |||
8 | import tools.refinery.store.query.term.BinaryTerm; | ||
9 | import tools.refinery.store.query.term.Term; | ||
10 | import tools.refinery.store.representation.cardinality.UpperCardinality; | ||
11 | |||
12 | public 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 deleted file mode 100644 index ff75f64e..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/uppercardinality/UpperCardinalityMaxTerm.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 | */ | ||
6 | package tools.refinery.store.query.term.uppercardinality; | ||
7 | |||
8 | import tools.refinery.store.query.substitution.Substitution; | ||
9 | import tools.refinery.store.query.term.Term; | ||
10 | import tools.refinery.store.representation.cardinality.UpperCardinality; | ||
11 | |||
12 | public 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 deleted file mode 100644 index 1e89e9f4..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/uppercardinality/UpperCardinalityMinTerm.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 | */ | ||
6 | package tools.refinery.store.query.term.uppercardinality; | ||
7 | |||
8 | import tools.refinery.store.query.substitution.Substitution; | ||
9 | import tools.refinery.store.query.term.Term; | ||
10 | import tools.refinery.store.representation.cardinality.UpperCardinality; | ||
11 | |||
12 | public 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 deleted file mode 100644 index 3b4970f4..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/uppercardinality/UpperCardinalityMulTerm.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 | */ | ||
6 | package tools.refinery.store.query.term.uppercardinality; | ||
7 | |||
8 | import tools.refinery.store.query.substitution.Substitution; | ||
9 | import tools.refinery.store.query.term.Term; | ||
10 | import tools.refinery.store.representation.cardinality.UpperCardinality; | ||
11 | |||
12 | public 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 deleted file mode 100644 index d31f00a2..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/uppercardinality/UpperCardinalitySumAggregator.java +++ /dev/null | |||
@@ -1,86 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.term.uppercardinality; | ||
7 | |||
8 | import tools.refinery.store.query.term.StatefulAggregate; | ||
9 | import tools.refinery.store.query.term.StatefulAggregator; | ||
10 | import tools.refinery.store.representation.cardinality.FiniteUpperCardinality; | ||
11 | import tools.refinery.store.representation.cardinality.UnboundedUpperCardinality; | ||
12 | import tools.refinery.store.representation.cardinality.UpperCardinalities; | ||
13 | import tools.refinery.store.representation.cardinality.UpperCardinality; | ||
14 | |||
15 | public 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.atMost(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 deleted file mode 100644 index 13914f2d..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/uppercardinality/UpperCardinalityTerms.java +++ /dev/null | |||
@@ -1,73 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.term.uppercardinality; | ||
7 | |||
8 | import tools.refinery.store.query.term.Aggregator; | ||
9 | import tools.refinery.store.query.term.ConstantTerm; | ||
10 | import tools.refinery.store.query.term.ExtremeValueAggregator; | ||
11 | import tools.refinery.store.query.term.Term; | ||
12 | import tools.refinery.store.query.term.comparable.*; | ||
13 | import tools.refinery.store.representation.cardinality.UpperCardinalities; | ||
14 | import tools.refinery.store.representation.cardinality.UpperCardinality; | ||
15 | |||
16 | import java.util.Comparator; | ||
17 | |||
18 | public 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 deleted file mode 100644 index 261ceaa5..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/valuation/MapBasedValuation.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 | */ | ||
6 | package tools.refinery.store.query.valuation; | ||
7 | |||
8 | import tools.refinery.store.query.term.AnyDataVariable; | ||
9 | import tools.refinery.store.query.term.DataVariable; | ||
10 | |||
11 | import java.util.Map; | ||
12 | |||
13 | record 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/RestrictedValuation.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/valuation/RestrictedValuation.java deleted file mode 100644 index fc8406aa..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/valuation/RestrictedValuation.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 | */ | ||
6 | package tools.refinery.store.query.valuation; | ||
7 | |||
8 | import tools.refinery.store.query.term.AnyDataVariable; | ||
9 | import tools.refinery.store.query.term.DataVariable; | ||
10 | |||
11 | import java.util.Set; | ||
12 | |||
13 | public record RestrictedValuation(Valuation valuation, Set<AnyDataVariable> allowedVariables) implements Valuation { | ||
14 | @Override | ||
15 | public <T> T getValue(DataVariable<T> variable) { | ||
16 | if (!allowedVariables.contains(variable)) { | ||
17 | throw new IllegalArgumentException("Variable %s is not in scope".formatted(variable)); | ||
18 | } | ||
19 | return valuation.getValue(variable); | ||
20 | } | ||
21 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/valuation/SubstitutedValuation.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/valuation/SubstitutedValuation.java deleted file mode 100644 index 1c14112c..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/valuation/SubstitutedValuation.java +++ /dev/null | |||
@@ -1,16 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.valuation; | ||
7 | |||
8 | import tools.refinery.store.query.substitution.Substitution; | ||
9 | import tools.refinery.store.query.term.DataVariable; | ||
10 | |||
11 | public record SubstitutedValuation(Valuation originalValuation, Substitution substitution) implements Valuation { | ||
12 | @Override | ||
13 | public <T> T getValue(DataVariable<T> variable) { | ||
14 | return originalValuation.getValue(substitution.getTypeSafeSubstitute(variable)); | ||
15 | } | ||
16 | } | ||
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 deleted file mode 100644 index 1588e957..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/valuation/Valuation.java +++ /dev/null | |||
@@ -1,37 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.valuation; | ||
7 | |||
8 | import org.jetbrains.annotations.Nullable; | ||
9 | import tools.refinery.store.query.substitution.Substitution; | ||
10 | import tools.refinery.store.query.term.AnyDataVariable; | ||
11 | import tools.refinery.store.query.term.DataVariable; | ||
12 | |||
13 | import java.util.Map; | ||
14 | import java.util.Set; | ||
15 | |||
16 | public interface Valuation { | ||
17 | <T> T getValue(DataVariable<T> variable); | ||
18 | |||
19 | default Valuation substitute(@Nullable Substitution substitution) { | ||
20 | if (substitution == null) { | ||
21 | return this; | ||
22 | } | ||
23 | return new SubstitutedValuation(this, substitution); | ||
24 | } | ||
25 | |||
26 | default Valuation restrict(Set<? extends AnyDataVariable> allowedVariables) { | ||
27 | return new RestrictedValuation(this, Set.copyOf(allowedVariables)); | ||
28 | } | ||
29 | |||
30 | static ValuationBuilder builder() { | ||
31 | return new ValuationBuilder(); | ||
32 | } | ||
33 | |||
34 | static Valuation empty() { | ||
35 | return new MapBasedValuation(Map.of()); | ||
36 | } | ||
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 deleted file mode 100644 index 7337dbc3..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/valuation/ValuationBuilder.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 | */ | ||
6 | package tools.refinery.store.query.valuation; | ||
7 | |||
8 | import tools.refinery.store.query.term.AnyDataVariable; | ||
9 | import tools.refinery.store.query.term.DataVariable; | ||
10 | |||
11 | import java.util.Collections; | ||
12 | import java.util.HashMap; | ||
13 | import java.util.Map; | ||
14 | |||
15 | public 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 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/view/AbstractFunctionView.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/view/AbstractFunctionView.java index f130fa59..d9809991 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/view/AbstractFunctionView.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/view/AbstractFunctionView.java | |||
@@ -7,8 +7,8 @@ package tools.refinery.store.query.view; | |||
7 | 7 | ||
8 | import tools.refinery.store.map.CursorAsIterator; | 8 | import tools.refinery.store.map.CursorAsIterator; |
9 | import tools.refinery.store.model.Model; | 9 | import tools.refinery.store.model.Model; |
10 | import tools.refinery.store.query.dnf.FunctionalDependency; | 10 | import tools.refinery.logic.dnf.FunctionalDependency; |
11 | import tools.refinery.store.query.term.Parameter; | 11 | import tools.refinery.logic.term.Parameter; |
12 | import tools.refinery.store.representation.Symbol; | 12 | import tools.refinery.store.representation.Symbol; |
13 | import tools.refinery.store.tuple.Tuple; | 13 | import tools.refinery.store.tuple.Tuple; |
14 | import tools.refinery.store.tuple.Tuple1; | 14 | import tools.refinery.store.tuple.Tuple1; |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/view/AnySymbolView.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/view/AnySymbolView.java index 7e9bf6df..b01c3988 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/view/AnySymbolView.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/view/AnySymbolView.java | |||
@@ -5,10 +5,10 @@ | |||
5 | */ | 5 | */ |
6 | package tools.refinery.store.query.view; | 6 | package tools.refinery.store.query.view; |
7 | 7 | ||
8 | import tools.refinery.logic.dnf.FunctionalDependency; | ||
8 | import tools.refinery.store.model.Model; | 9 | import tools.refinery.store.model.Model; |
9 | import tools.refinery.store.query.dnf.FunctionalDependency; | 10 | import tools.refinery.logic.Constraint; |
10 | import tools.refinery.store.representation.AnySymbol; | 11 | import tools.refinery.store.representation.AnySymbol; |
11 | import tools.refinery.store.query.Constraint; | ||
12 | 12 | ||
13 | import java.util.Set; | 13 | import java.util.Set; |
14 | 14 | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/view/FilteredView.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/view/FilteredView.java index 924277ed..7ce07442 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/view/FilteredView.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/view/FilteredView.java | |||
@@ -5,7 +5,7 @@ | |||
5 | */ | 5 | */ |
6 | package tools.refinery.store.query.view; | 6 | package tools.refinery.store.query.view; |
7 | 7 | ||
8 | import tools.refinery.store.query.InvalidQueryException; | 8 | import tools.refinery.logic.InvalidQueryException; |
9 | import tools.refinery.store.tuple.Tuple; | 9 | import tools.refinery.store.tuple.Tuple; |
10 | import tools.refinery.store.representation.Symbol; | 10 | import tools.refinery.store.representation.Symbol; |
11 | 11 | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/view/ForbiddenView.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/view/ForbiddenView.java index c312330e..8323ace7 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/view/ForbiddenView.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/view/ForbiddenView.java | |||
@@ -6,7 +6,7 @@ | |||
6 | package tools.refinery.store.query.view; | 6 | package tools.refinery.store.query.view; |
7 | 7 | ||
8 | import tools.refinery.store.representation.Symbol; | 8 | import tools.refinery.store.representation.Symbol; |
9 | import tools.refinery.store.representation.TruthValue; | 9 | import tools.refinery.logic.term.truthvalue.TruthValue; |
10 | import tools.refinery.store.tuple.Tuple; | 10 | import tools.refinery.store.tuple.Tuple; |
11 | 11 | ||
12 | public class ForbiddenView extends TuplePreservingView<TruthValue> { | 12 | public class ForbiddenView extends TuplePreservingView<TruthValue> { |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/view/FunctionView.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/view/FunctionView.java index 74a5be07..5585f5f2 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/view/FunctionView.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/view/FunctionView.java | |||
@@ -1,11 +1,11 @@ | |||
1 | /* | 1 | /* |
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | 2 | * SPDX-FileCopyrightText: 2021-2024 The Refinery Authors <https://refinery.tools/> |
3 | * | 3 | * |
4 | * SPDX-License-Identifier: EPL-2.0 | 4 | * SPDX-License-Identifier: EPL-2.0 |
5 | */ | 5 | */ |
6 | package tools.refinery.store.query.view; | 6 | package tools.refinery.store.query.view; |
7 | 7 | ||
8 | import tools.refinery.store.query.term.*; | 8 | import tools.refinery.logic.term.*; |
9 | import tools.refinery.store.representation.Symbol; | 9 | import tools.refinery.store.representation.Symbol; |
10 | 10 | ||
11 | import java.util.ArrayList; | 11 | import java.util.ArrayList; |
@@ -33,4 +33,18 @@ public final class FunctionView<T> extends AbstractFunctionView<T> { | |||
33 | public <R> AssignedValue<R> aggregate(Aggregator<R, T> aggregator, NodeVariable... arguments) { | 33 | public <R> AssignedValue<R> aggregate(Aggregator<R, T> aggregator, NodeVariable... arguments) { |
34 | return aggregate(aggregator, List.of(arguments)); | 34 | return aggregate(aggregator, List.of(arguments)); |
35 | } | 35 | } |
36 | |||
37 | public AssignedValue<T> leftJoin(T defaultValue, List<NodeVariable> arguments) { | ||
38 | return targetVariable -> { | ||
39 | var placeholderVariable = Variable.of(getSymbol().valueType()); | ||
40 | var argumentsWithPlaceholder = new ArrayList<Variable>(arguments.size() + 1); | ||
41 | argumentsWithPlaceholder.addAll(arguments); | ||
42 | argumentsWithPlaceholder.add(placeholderVariable); | ||
43 | return leftJoinBy(placeholderVariable, defaultValue, argumentsWithPlaceholder).toLiteral(targetVariable); | ||
44 | }; | ||
45 | } | ||
46 | |||
47 | public AssignedValue<T> leftJoin(T defaultValue, NodeVariable... arguments) { | ||
48 | return leftJoin(defaultValue, List.of(arguments)); | ||
49 | } | ||
36 | } | 50 | } |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/view/MayView.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/view/MayView.java index c322e220..3a6cc93b 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/view/MayView.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/view/MayView.java | |||
@@ -6,7 +6,7 @@ | |||
6 | package tools.refinery.store.query.view; | 6 | package tools.refinery.store.query.view; |
7 | 7 | ||
8 | import tools.refinery.store.representation.Symbol; | 8 | import tools.refinery.store.representation.Symbol; |
9 | import tools.refinery.store.representation.TruthValue; | 9 | import tools.refinery.logic.term.truthvalue.TruthValue; |
10 | import tools.refinery.store.tuple.Tuple; | 10 | import tools.refinery.store.tuple.Tuple; |
11 | 11 | ||
12 | public class MayView extends TuplePreservingView<TruthValue> { | 12 | public class MayView extends TuplePreservingView<TruthValue> { |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/view/MustView.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/view/MustView.java index 65bb4e4c..af984327 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/view/MustView.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/view/MustView.java | |||
@@ -6,7 +6,7 @@ | |||
6 | package tools.refinery.store.query.view; | 6 | package tools.refinery.store.query.view; |
7 | 7 | ||
8 | import tools.refinery.store.representation.Symbol; | 8 | import tools.refinery.store.representation.Symbol; |
9 | import tools.refinery.store.representation.TruthValue; | 9 | import tools.refinery.logic.term.truthvalue.TruthValue; |
10 | import tools.refinery.store.tuple.Tuple; | 10 | import tools.refinery.store.tuple.Tuple; |
11 | 11 | ||
12 | public class MustView extends TuplePreservingView<TruthValue> { | 12 | public class MustView extends TuplePreservingView<TruthValue> { |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/view/NodeFunctionView.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/view/NodeFunctionView.java index fcf11506..01865cbe 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/view/NodeFunctionView.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/view/NodeFunctionView.java | |||
@@ -5,7 +5,7 @@ | |||
5 | */ | 5 | */ |
6 | package tools.refinery.store.query.view; | 6 | package tools.refinery.store.query.view; |
7 | 7 | ||
8 | import tools.refinery.store.query.term.Parameter; | 8 | import tools.refinery.logic.term.Parameter; |
9 | import tools.refinery.store.representation.Symbol; | 9 | import tools.refinery.store.representation.Symbol; |
10 | import tools.refinery.store.tuple.Tuple1; | 10 | import tools.refinery.store.tuple.Tuple1; |
11 | 11 | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/view/TuplePreservingView.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/view/TuplePreservingView.java index ed12cd9d..6841488d 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/view/TuplePreservingView.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/view/TuplePreservingView.java | |||
@@ -7,7 +7,7 @@ package tools.refinery.store.query.view; | |||
7 | 7 | ||
8 | import tools.refinery.store.map.CursorAsIterator; | 8 | import tools.refinery.store.map.CursorAsIterator; |
9 | import tools.refinery.store.model.Model; | 9 | import tools.refinery.store.model.Model; |
10 | import tools.refinery.store.query.term.Parameter; | 10 | import tools.refinery.logic.term.Parameter; |
11 | import tools.refinery.store.representation.Symbol; | 11 | import tools.refinery.store.representation.Symbol; |
12 | import tools.refinery.store.tuple.Tuple; | 12 | import tools.refinery.store.tuple.Tuple; |
13 | import tools.refinery.store.tuple.Tuple1; | 13 | import tools.refinery.store.tuple.Tuple1; |