aboutsummaryrefslogtreecommitdiffstats
path: root/subprojects/logic/src/main/java/tools/refinery/logic/substitution/SubstitutionBuilder.java
diff options
context:
space:
mode:
Diffstat (limited to 'subprojects/logic/src/main/java/tools/refinery/logic/substitution/SubstitutionBuilder.java')
-rw-r--r--subprojects/logic/src/main/java/tools/refinery/logic/substitution/SubstitutionBuilder.java79
1 files changed, 79 insertions, 0 deletions
diff --git a/subprojects/logic/src/main/java/tools/refinery/logic/substitution/SubstitutionBuilder.java b/subprojects/logic/src/main/java/tools/refinery/logic/substitution/SubstitutionBuilder.java
new file mode 100644
index 00000000..f30b1a5d
--- /dev/null
+++ b/subprojects/logic/src/main/java/tools/refinery/logic/substitution/SubstitutionBuilder.java
@@ -0,0 +1,79 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.logic.substitution;
7
8import tools.refinery.logic.term.DataVariable;
9import tools.refinery.logic.term.NodeVariable;
10import tools.refinery.logic.term.Variable;
11
12import java.util.Collections;
13import java.util.HashMap;
14import java.util.List;
15import java.util.Map;
16
17@SuppressWarnings("UnusedReturnValue")
18public class SubstitutionBuilder {
19 private final Map<Variable, Variable> map = new HashMap<>();
20 private Substitution fallback;
21
22 SubstitutionBuilder() {
23 total();
24 }
25
26 public SubstitutionBuilder put(NodeVariable original, NodeVariable substitute) {
27 return putChecked(original, substitute);
28 }
29
30 public <T> SubstitutionBuilder put(DataVariable<T> original, DataVariable<T> substitute) {
31 return putChecked(original, substitute);
32 }
33
34 public SubstitutionBuilder putChecked(Variable original, Variable substitute) {
35 if (!original.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}