diff options
author | 2023-03-31 17:31:46 +0200 | |
---|---|---|
committer | 2023-03-31 17:31:46 +0200 | |
commit | 93f1d439f33a5139039fe93280bbfcae61a904ab (patch) | |
tree | e98eae681a866d2d0cd728885ed6c8f8fa65e9a2 /subprojects/store | |
parent | refactor: PartialInterpretation adapter naming (diff) | |
parent | build: try to fix secret detection in workflow (diff) | |
download | refinery-93f1d439f33a5139039fe93280bbfcae61a904ab.tar.gz refinery-93f1d439f33a5139039fe93280bbfcae61a904ab.tar.zst refinery-93f1d439f33a5139039fe93280bbfcae61a904ab.zip |
Merge pull request #24 from kris7t/partial-interpretation
Changes for supporting partial interpretation
Diffstat (limited to 'subprojects/store')
42 files changed, 196 insertions, 1011 deletions
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/Cursors.java b/subprojects/store/src/main/java/tools/refinery/store/map/Cursors.java new file mode 100644 index 00000000..fc8e628b --- /dev/null +++ b/subprojects/store/src/main/java/tools/refinery/store/map/Cursors.java | |||
@@ -0,0 +1,36 @@ | |||
1 | package tools.refinery.store.map; | ||
2 | |||
3 | public final class Cursors { | ||
4 | private Cursors() { | ||
5 | throw new IllegalStateException("This is a static utility class and should not be instantiated directly"); | ||
6 | } | ||
7 | |||
8 | public static <K, V> Cursor<K, V> empty() { | ||
9 | return new Empty<>(); | ||
10 | } | ||
11 | |||
12 | private static class Empty<K, V> implements Cursor<K, V> { | ||
13 | private boolean terminated = false; | ||
14 | |||
15 | @Override | ||
16 | public K getKey() { | ||
17 | return null; | ||
18 | } | ||
19 | |||
20 | @Override | ||
21 | public V getValue() { | ||
22 | return null; | ||
23 | } | ||
24 | |||
25 | @Override | ||
26 | public boolean isTerminated() { | ||
27 | return terminated; | ||
28 | } | ||
29 | |||
30 | @Override | ||
31 | public boolean move() { | ||
32 | terminated = true; | ||
33 | return false; | ||
34 | } | ||
35 | } | ||
36 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/partial/PartialInterpretation.java b/subprojects/store/src/main/java/tools/refinery/store/partial/PartialInterpretation.java deleted file mode 100644 index 331fa294..00000000 --- a/subprojects/store/src/main/java/tools/refinery/store/partial/PartialInterpretation.java +++ /dev/null | |||
@@ -1,19 +0,0 @@ | |||
1 | package tools.refinery.store.partial; | ||
2 | |||
3 | import tools.refinery.store.adapter.ModelAdapterBuilderFactory; | ||
4 | import tools.refinery.store.model.ModelStoreBuilder; | ||
5 | import tools.refinery.store.partial.internal.PartialInterpretationBuilderImpl; | ||
6 | |||
7 | public final class PartialInterpretation extends ModelAdapterBuilderFactory<PartialInterpretationAdapter, | ||
8 | PartialInterpretationStoreAdapter, PartialInterpretationBuilder> { | ||
9 | public static final PartialInterpretation ADAPTER = new PartialInterpretation(); | ||
10 | |||
11 | private PartialInterpretation() { | ||
12 | super(PartialInterpretationAdapter.class, PartialInterpretationStoreAdapter.class, PartialInterpretationBuilder.class); | ||
13 | } | ||
14 | |||
15 | @Override | ||
16 | public PartialInterpretationBuilder createBuilder(ModelStoreBuilder storeBuilder) { | ||
17 | return new PartialInterpretationBuilderImpl(storeBuilder); | ||
18 | } | ||
19 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/partial/PartialInterpretationAdapter.java b/subprojects/store/src/main/java/tools/refinery/store/partial/PartialInterpretationAdapter.java deleted file mode 100644 index 2c83a200..00000000 --- a/subprojects/store/src/main/java/tools/refinery/store/partial/PartialInterpretationAdapter.java +++ /dev/null | |||
@@ -1,9 +0,0 @@ | |||
1 | package tools.refinery.store.partial; | ||
2 | |||
3 | import tools.refinery.store.adapter.ModelAdapter; | ||
4 | |||
5 | public interface PartialInterpretationAdapter extends ModelAdapter { | ||
6 | @Override | ||
7 | PartialInterpretationStoreAdapter getStoreAdapter(); | ||
8 | } | ||
9 | |||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/partial/PartialInterpretationBuilder.java b/subprojects/store/src/main/java/tools/refinery/store/partial/PartialInterpretationBuilder.java deleted file mode 100644 index 0ec13836..00000000 --- a/subprojects/store/src/main/java/tools/refinery/store/partial/PartialInterpretationBuilder.java +++ /dev/null | |||
@@ -1,9 +0,0 @@ | |||
1 | package tools.refinery.store.partial; | ||
2 | |||
3 | import tools.refinery.store.adapter.ModelAdapterBuilder; | ||
4 | import tools.refinery.store.model.ModelStore; | ||
5 | |||
6 | public interface PartialInterpretationBuilder extends ModelAdapterBuilder { | ||
7 | @Override | ||
8 | PartialInterpretationStoreAdapter createStoreAdapter(ModelStore store); | ||
9 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/partial/PartialInterpretationStoreAdapter.java b/subprojects/store/src/main/java/tools/refinery/store/partial/PartialInterpretationStoreAdapter.java deleted file mode 100644 index d4eb770d..00000000 --- a/subprojects/store/src/main/java/tools/refinery/store/partial/PartialInterpretationStoreAdapter.java +++ /dev/null | |||
@@ -1,9 +0,0 @@ | |||
1 | package tools.refinery.store.partial; | ||
2 | |||
3 | import tools.refinery.store.adapter.ModelStoreAdapter; | ||
4 | import tools.refinery.store.model.Model; | ||
5 | |||
6 | public interface PartialInterpretationStoreAdapter extends ModelStoreAdapter { | ||
7 | @Override | ||
8 | PartialInterpretationAdapter createModelAdapter(Model model); | ||
9 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/partial/internal/PartialInterpretationAdapterImpl.java b/subprojects/store/src/main/java/tools/refinery/store/partial/internal/PartialInterpretationAdapterImpl.java deleted file mode 100644 index 4b3977c0..00000000 --- a/subprojects/store/src/main/java/tools/refinery/store/partial/internal/PartialInterpretationAdapterImpl.java +++ /dev/null | |||
@@ -1,24 +0,0 @@ | |||
1 | package tools.refinery.store.partial.internal; | ||
2 | |||
3 | import tools.refinery.store.model.Model; | ||
4 | import tools.refinery.store.partial.PartialInterpretationAdapter; | ||
5 | |||
6 | public class PartialInterpretationAdapterImpl implements PartialInterpretationAdapter { | ||
7 | private final Model model; | ||
8 | private final PartialInterpretationStoreAdapterImpl storeAdapter; | ||
9 | |||
10 | PartialInterpretationAdapterImpl(Model model, PartialInterpretationStoreAdapterImpl storeAdapter) { | ||
11 | this.model = model; | ||
12 | this.storeAdapter = storeAdapter; | ||
13 | } | ||
14 | |||
15 | @Override | ||
16 | public Model getModel() { | ||
17 | return model; | ||
18 | } | ||
19 | |||
20 | @Override | ||
21 | public PartialInterpretationStoreAdapterImpl getStoreAdapter() { | ||
22 | return storeAdapter; | ||
23 | } | ||
24 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/partial/internal/PartialInterpretationBuilderImpl.java b/subprojects/store/src/main/java/tools/refinery/store/partial/internal/PartialInterpretationBuilderImpl.java deleted file mode 100644 index 4609dc32..00000000 --- a/subprojects/store/src/main/java/tools/refinery/store/partial/internal/PartialInterpretationBuilderImpl.java +++ /dev/null | |||
@@ -1,17 +0,0 @@ | |||
1 | package tools.refinery.store.partial.internal; | ||
2 | |||
3 | import tools.refinery.store.adapter.AbstractModelAdapterBuilder; | ||
4 | import tools.refinery.store.model.ModelStore; | ||
5 | import tools.refinery.store.model.ModelStoreBuilder; | ||
6 | import tools.refinery.store.partial.PartialInterpretationBuilder; | ||
7 | |||
8 | public class PartialInterpretationBuilderImpl extends AbstractModelAdapterBuilder implements PartialInterpretationBuilder { | ||
9 | public PartialInterpretationBuilderImpl(ModelStoreBuilder storeBuilder) { | ||
10 | super(storeBuilder); | ||
11 | } | ||
12 | |||
13 | @Override | ||
14 | public PartialInterpretationStoreAdapterImpl createStoreAdapter(ModelStore store) { | ||
15 | return null; | ||
16 | } | ||
17 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/partial/internal/PartialInterpretationStoreAdapterImpl.java b/subprojects/store/src/main/java/tools/refinery/store/partial/internal/PartialInterpretationStoreAdapterImpl.java deleted file mode 100644 index 970b802b..00000000 --- a/subprojects/store/src/main/java/tools/refinery/store/partial/internal/PartialInterpretationStoreAdapterImpl.java +++ /dev/null | |||
@@ -1,23 +0,0 @@ | |||
1 | package tools.refinery.store.partial.internal; | ||
2 | |||
3 | import tools.refinery.store.model.Model; | ||
4 | import tools.refinery.store.model.ModelStore; | ||
5 | import tools.refinery.store.partial.PartialInterpretationStoreAdapter; | ||
6 | |||
7 | public class PartialInterpretationStoreAdapterImpl implements PartialInterpretationStoreAdapter { | ||
8 | private final ModelStore store; | ||
9 | |||
10 | PartialInterpretationStoreAdapterImpl(ModelStore store) { | ||
11 | this.store = store; | ||
12 | } | ||
13 | |||
14 | @Override | ||
15 | public ModelStore getStore() { | ||
16 | return store; | ||
17 | } | ||
18 | |||
19 | @Override | ||
20 | public PartialInterpretationAdapterImpl createModelAdapter(Model model) { | ||
21 | return new PartialInterpretationAdapterImpl(model, this); | ||
22 | } | ||
23 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/DNF.java b/subprojects/store/src/main/java/tools/refinery/store/query/DNF.java deleted file mode 100644 index 95c5d787..00000000 --- a/subprojects/store/src/main/java/tools/refinery/store/query/DNF.java +++ /dev/null | |||
@@ -1,169 +0,0 @@ | |||
1 | package tools.refinery.store.query; | ||
2 | |||
3 | import tools.refinery.store.query.atom.DNFAtom; | ||
4 | |||
5 | import java.util.*; | ||
6 | |||
7 | public final class DNF implements RelationLike { | ||
8 | private final String name; | ||
9 | |||
10 | private final String uniqueName; | ||
11 | |||
12 | private final List<Variable> parameters; | ||
13 | |||
14 | private final List<FunctionalDependency<Variable>> functionalDependencies; | ||
15 | |||
16 | private final List<DNFAnd> clauses; | ||
17 | |||
18 | private DNF(String name, List<Variable> parameters, List<FunctionalDependency<Variable>> functionalDependencies, | ||
19 | List<DNFAnd> clauses) { | ||
20 | validateFunctionalDependencies(parameters, functionalDependencies); | ||
21 | this.name = name; | ||
22 | this.uniqueName = DNFUtils.generateUniqueName(name); | ||
23 | this.parameters = parameters; | ||
24 | this.functionalDependencies = functionalDependencies; | ||
25 | this.clauses = clauses; | ||
26 | } | ||
27 | |||
28 | private static void validateFunctionalDependencies( | ||
29 | Collection<Variable> parameters, Collection<FunctionalDependency<Variable>> functionalDependencies) { | ||
30 | var parameterSet = new HashSet<>(parameters); | ||
31 | for (var functionalDependency : functionalDependencies) { | ||
32 | validateParameters(parameters, parameterSet, functionalDependency.forEach(), functionalDependency); | ||
33 | validateParameters(parameters, parameterSet, functionalDependency.unique(), functionalDependency); | ||
34 | } | ||
35 | } | ||
36 | |||
37 | private static void validateParameters(Collection<Variable> parameters, Set<Variable> parameterSet, | ||
38 | Collection<Variable> toValidate, | ||
39 | FunctionalDependency<Variable> functionalDependency) { | ||
40 | for (var variable : toValidate) { | ||
41 | if (!parameterSet.contains(variable)) { | ||
42 | throw new IllegalArgumentException( | ||
43 | "Variable %s of functional dependency %s does not appear in the parameter list %s" | ||
44 | .formatted(variable, functionalDependency, parameters)); | ||
45 | } | ||
46 | } | ||
47 | } | ||
48 | |||
49 | @Override | ||
50 | public String name() { | ||
51 | return name; | ||
52 | } | ||
53 | |||
54 | public String getUniqueName() { | ||
55 | return uniqueName; | ||
56 | } | ||
57 | |||
58 | public List<Variable> getParameters() { | ||
59 | return parameters; | ||
60 | } | ||
61 | |||
62 | public List<FunctionalDependency<Variable>> getFunctionalDependencies() { | ||
63 | return functionalDependencies; | ||
64 | } | ||
65 | |||
66 | @Override | ||
67 | public int arity() { | ||
68 | return parameters.size(); | ||
69 | } | ||
70 | |||
71 | public List<DNFAnd> getClauses() { | ||
72 | return clauses; | ||
73 | } | ||
74 | |||
75 | public static Builder builder() { | ||
76 | return builder(null); | ||
77 | } | ||
78 | |||
79 | public static Builder builder(String name) { | ||
80 | return new Builder(name); | ||
81 | } | ||
82 | |||
83 | @SuppressWarnings("UnusedReturnValue") | ||
84 | public static class Builder { | ||
85 | private final String name; | ||
86 | |||
87 | private final List<Variable> parameters = new ArrayList<>(); | ||
88 | |||
89 | private final List<FunctionalDependency<Variable>> functionalDependencies = new ArrayList<>(); | ||
90 | |||
91 | private final List<List<DNFAtom>> clauses = new ArrayList<>(); | ||
92 | |||
93 | private Builder(String name) { | ||
94 | this.name = name; | ||
95 | } | ||
96 | |||
97 | public Builder parameter(Variable variable) { | ||
98 | parameters.add(variable); | ||
99 | return this; | ||
100 | } | ||
101 | |||
102 | public Builder parameters(Variable... variables) { | ||
103 | return parameters(List.of(variables)); | ||
104 | } | ||
105 | |||
106 | public Builder parameters(Collection<Variable> variables) { | ||
107 | parameters.addAll(variables); | ||
108 | return this; | ||
109 | } | ||
110 | |||
111 | public Builder functionalDependencies(Collection<FunctionalDependency<Variable>> functionalDependencies) { | ||
112 | this.functionalDependencies.addAll(functionalDependencies); | ||
113 | return this; | ||
114 | } | ||
115 | |||
116 | public Builder functionalDependency(FunctionalDependency<Variable> functionalDependency) { | ||
117 | functionalDependencies.add(functionalDependency); | ||
118 | return this; | ||
119 | } | ||
120 | |||
121 | public Builder functionalDependency(Set<Variable> forEach, Set<Variable> unique) { | ||
122 | return functionalDependency(new FunctionalDependency<>(forEach, unique)); | ||
123 | } | ||
124 | |||
125 | public Builder clause(DNFAtom... atoms) { | ||
126 | clauses.add(List.of(atoms)); | ||
127 | return this; | ||
128 | } | ||
129 | |||
130 | public Builder clause(Collection<DNFAtom> atoms) { | ||
131 | clauses.add(List.copyOf(atoms)); | ||
132 | return this; | ||
133 | } | ||
134 | |||
135 | public Builder clause(DNFAnd clause) { | ||
136 | return clause(clause.constraints()); | ||
137 | } | ||
138 | |||
139 | public Builder clauses(DNFAnd... clauses) { | ||
140 | for (var clause : clauses) { | ||
141 | this.clause(clause); | ||
142 | } | ||
143 | return this; | ||
144 | } | ||
145 | |||
146 | public Builder clauses(Collection<DNFAnd> clauses) { | ||
147 | for (var clause : clauses) { | ||
148 | this.clause(clause); | ||
149 | } | ||
150 | return this; | ||
151 | } | ||
152 | |||
153 | public DNF build() { | ||
154 | var postProcessedClauses = new ArrayList<DNFAnd>(); | ||
155 | for (var constraints : clauses) { | ||
156 | var variables = new HashSet<Variable>(); | ||
157 | for (var constraint : constraints) { | ||
158 | constraint.collectAllVariables(variables); | ||
159 | } | ||
160 | parameters.forEach(variables::remove); | ||
161 | postProcessedClauses.add(new DNFAnd(Collections.unmodifiableSet(variables), | ||
162 | Collections.unmodifiableList(constraints))); | ||
163 | } | ||
164 | return new DNF(name, Collections.unmodifiableList(parameters), | ||
165 | Collections.unmodifiableList(functionalDependencies), | ||
166 | Collections.unmodifiableList(postProcessedClauses)); | ||
167 | } | ||
168 | } | ||
169 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/DNFAnd.java b/subprojects/store/src/main/java/tools/refinery/store/query/DNFAnd.java deleted file mode 100644 index 8c3bf05d..00000000 --- a/subprojects/store/src/main/java/tools/refinery/store/query/DNFAnd.java +++ /dev/null | |||
@@ -1,9 +0,0 @@ | |||
1 | package tools.refinery.store.query; | ||
2 | |||
3 | import tools.refinery.store.query.atom.DNFAtom; | ||
4 | |||
5 | import java.util.List; | ||
6 | import java.util.Set; | ||
7 | |||
8 | public record DNFAnd(Set<Variable> quantifiedVariables, List<DNFAtom> constraints) { | ||
9 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/DNFUtils.java b/subprojects/store/src/main/java/tools/refinery/store/query/DNFUtils.java deleted file mode 100644 index 0ef77d49..00000000 --- a/subprojects/store/src/main/java/tools/refinery/store/query/DNFUtils.java +++ /dev/null | |||
@@ -1,19 +0,0 @@ | |||
1 | package tools.refinery.store.query; | ||
2 | |||
3 | import java.util.UUID; | ||
4 | |||
5 | public final class DNFUtils { | ||
6 | private DNFUtils() { | ||
7 | throw new IllegalStateException("This is a static utility class and should not be instantiated directly"); | ||
8 | } | ||
9 | |||
10 | public static String generateUniqueName(String originalName) { | ||
11 | UUID uuid = UUID.randomUUID(); | ||
12 | String uniqueString = "_" + uuid.toString().replace('-', '_'); | ||
13 | if (originalName == null) { | ||
14 | return uniqueString; | ||
15 | } else { | ||
16 | return originalName + uniqueString; | ||
17 | } | ||
18 | } | ||
19 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/FunctionalDependency.java b/subprojects/store/src/main/java/tools/refinery/store/query/FunctionalDependency.java deleted file mode 100644 index 63a81713..00000000 --- a/subprojects/store/src/main/java/tools/refinery/store/query/FunctionalDependency.java +++ /dev/null | |||
@@ -1,15 +0,0 @@ | |||
1 | package tools.refinery.store.query; | ||
2 | |||
3 | import java.util.HashSet; | ||
4 | import java.util.Set; | ||
5 | |||
6 | public record FunctionalDependency<T>(Set<T> forEach, Set<T> unique) { | ||
7 | public FunctionalDependency { | ||
8 | var uniqueForEach = new HashSet<>(unique); | ||
9 | uniqueForEach.retainAll(forEach); | ||
10 | if (!uniqueForEach.isEmpty()) { | ||
11 | throw new IllegalArgumentException("Variables %s appear on both sides of the functional dependency" | ||
12 | .formatted(uniqueForEach)); | ||
13 | } | ||
14 | } | ||
15 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/ModelQuery.java b/subprojects/store/src/main/java/tools/refinery/store/query/ModelQuery.java deleted file mode 100644 index 6a1aeabb..00000000 --- a/subprojects/store/src/main/java/tools/refinery/store/query/ModelQuery.java +++ /dev/null | |||
@@ -1,11 +0,0 @@ | |||
1 | package tools.refinery.store.query; | ||
2 | |||
3 | import tools.refinery.store.adapter.ModelAdapterType; | ||
4 | |||
5 | public final class ModelQuery extends ModelAdapterType<ModelQueryAdapter, ModelQueryStoreAdapter, ModelQueryBuilder> { | ||
6 | public static final ModelQuery ADAPTER = new ModelQuery(); | ||
7 | |||
8 | private ModelQuery() { | ||
9 | super(ModelQueryAdapter.class, ModelQueryStoreAdapter.class, ModelQueryBuilder.class); | ||
10 | } | ||
11 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/ModelQueryAdapter.java b/subprojects/store/src/main/java/tools/refinery/store/query/ModelQueryAdapter.java deleted file mode 100644 index 7449e39b..00000000 --- a/subprojects/store/src/main/java/tools/refinery/store/query/ModelQueryAdapter.java +++ /dev/null | |||
@@ -1,13 +0,0 @@ | |||
1 | package tools.refinery.store.query; | ||
2 | |||
3 | import tools.refinery.store.adapter.ModelAdapter; | ||
4 | |||
5 | public interface ModelQueryAdapter extends ModelAdapter { | ||
6 | ModelQueryStoreAdapter getStoreAdapter(); | ||
7 | |||
8 | ResultSet getResultSet(DNF query); | ||
9 | |||
10 | boolean hasPendingChanges(); | ||
11 | |||
12 | void flushChanges(); | ||
13 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/ModelQueryBuilder.java b/subprojects/store/src/main/java/tools/refinery/store/query/ModelQueryBuilder.java deleted file mode 100644 index 4364d844..00000000 --- a/subprojects/store/src/main/java/tools/refinery/store/query/ModelQueryBuilder.java +++ /dev/null | |||
@@ -1,23 +0,0 @@ | |||
1 | package tools.refinery.store.query; | ||
2 | |||
3 | import tools.refinery.store.adapter.ModelAdapterBuilder; | ||
4 | import tools.refinery.store.model.ModelStore; | ||
5 | |||
6 | import java.util.Collection; | ||
7 | import java.util.List; | ||
8 | |||
9 | public interface ModelQueryBuilder extends ModelAdapterBuilder { | ||
10 | default ModelQueryBuilder queries(DNF... queries) { | ||
11 | return queries(List.of(queries)); | ||
12 | } | ||
13 | |||
14 | default ModelQueryBuilder queries(Collection<DNF> queries) { | ||
15 | queries.forEach(this::query); | ||
16 | return this; | ||
17 | } | ||
18 | |||
19 | ModelQueryBuilder query(DNF query); | ||
20 | |||
21 | @Override | ||
22 | ModelQueryStoreAdapter createStoreAdapter(ModelStore store); | ||
23 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/ModelQueryStoreAdapter.java b/subprojects/store/src/main/java/tools/refinery/store/query/ModelQueryStoreAdapter.java deleted file mode 100644 index ef5a4587..00000000 --- a/subprojects/store/src/main/java/tools/refinery/store/query/ModelQueryStoreAdapter.java +++ /dev/null | |||
@@ -1,16 +0,0 @@ | |||
1 | package tools.refinery.store.query; | ||
2 | |||
3 | import tools.refinery.store.adapter.ModelStoreAdapter; | ||
4 | import tools.refinery.store.model.Model; | ||
5 | import tools.refinery.store.query.view.AnyRelationView; | ||
6 | |||
7 | import java.util.Collection; | ||
8 | |||
9 | public interface ModelQueryStoreAdapter extends ModelStoreAdapter { | ||
10 | Collection<AnyRelationView> getRelationViews(); | ||
11 | |||
12 | Collection<DNF> getQueries(); | ||
13 | |||
14 | @Override | ||
15 | ModelQueryAdapter createModelAdapter(Model model); | ||
16 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/RelationLike.java b/subprojects/store/src/main/java/tools/refinery/store/query/RelationLike.java deleted file mode 100644 index 8c784d8b..00000000 --- a/subprojects/store/src/main/java/tools/refinery/store/query/RelationLike.java +++ /dev/null | |||
@@ -1,11 +0,0 @@ | |||
1 | package tools.refinery.store.query; | ||
2 | |||
3 | public interface RelationLike { | ||
4 | String name(); | ||
5 | |||
6 | int arity(); | ||
7 | |||
8 | default boolean invalidIndex(int i) { | ||
9 | return i < 0 || i >= arity(); | ||
10 | } | ||
11 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/ResultSet.java b/subprojects/store/src/main/java/tools/refinery/store/query/ResultSet.java deleted file mode 100644 index 3542e252..00000000 --- a/subprojects/store/src/main/java/tools/refinery/store/query/ResultSet.java +++ /dev/null | |||
@@ -1,25 +0,0 @@ | |||
1 | package tools.refinery.store.query; | ||
2 | |||
3 | import tools.refinery.store.tuple.Tuple; | ||
4 | import tools.refinery.store.tuple.TupleLike; | ||
5 | |||
6 | import java.util.Optional; | ||
7 | import java.util.stream.Stream; | ||
8 | |||
9 | public interface ResultSet { | ||
10 | boolean hasResult(); | ||
11 | |||
12 | boolean hasResult(Tuple parameters); | ||
13 | |||
14 | Optional<TupleLike> oneResult(); | ||
15 | |||
16 | Optional<TupleLike> oneResult(Tuple parameters); | ||
17 | |||
18 | Stream<TupleLike> allResults(); | ||
19 | |||
20 | Stream<TupleLike> allResults(Tuple parameters); | ||
21 | |||
22 | int countResults(); | ||
23 | |||
24 | int countResults(Tuple parameters); | ||
25 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/Variable.java b/subprojects/store/src/main/java/tools/refinery/store/query/Variable.java deleted file mode 100644 index 3632f3c5..00000000 --- a/subprojects/store/src/main/java/tools/refinery/store/query/Variable.java +++ /dev/null | |||
@@ -1,43 +0,0 @@ | |||
1 | package tools.refinery.store.query; | ||
2 | |||
3 | import java.util.Objects; | ||
4 | |||
5 | public class Variable { | ||
6 | private final String name; | ||
7 | private final String uniqueName; | ||
8 | |||
9 | public Variable() { | ||
10 | this(null); | ||
11 | } | ||
12 | |||
13 | public Variable(String name) { | ||
14 | super(); | ||
15 | this.name = name; | ||
16 | this.uniqueName = DNFUtils.generateUniqueName(name); | ||
17 | |||
18 | } | ||
19 | public String getName() { | ||
20 | return name; | ||
21 | } | ||
22 | |||
23 | public String getUniqueName() { | ||
24 | return uniqueName; | ||
25 | } | ||
26 | |||
27 | public boolean isNamed() { | ||
28 | return name != null; | ||
29 | } | ||
30 | |||
31 | @Override | ||
32 | public boolean equals(Object o) { | ||
33 | if (this == o) return true; | ||
34 | if (o == null || getClass() != o.getClass()) return false; | ||
35 | Variable variable = (Variable) o; | ||
36 | return Objects.equals(uniqueName, variable.uniqueName); | ||
37 | } | ||
38 | |||
39 | @Override | ||
40 | public int hashCode() { | ||
41 | return Objects.hash(uniqueName); | ||
42 | } | ||
43 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/atom/CallAtom.java b/subprojects/store/src/main/java/tools/refinery/store/query/atom/CallAtom.java deleted file mode 100644 index 47121870..00000000 --- a/subprojects/store/src/main/java/tools/refinery/store/query/atom/CallAtom.java +++ /dev/null | |||
@@ -1,80 +0,0 @@ | |||
1 | package tools.refinery.store.query.atom; | ||
2 | |||
3 | import tools.refinery.store.query.Variable; | ||
4 | import tools.refinery.store.query.RelationLike; | ||
5 | |||
6 | import java.util.List; | ||
7 | import java.util.Objects; | ||
8 | import java.util.Set; | ||
9 | |||
10 | public abstract class CallAtom<T extends RelationLike> implements DNFAtom { | ||
11 | private final CallPolarity polarity; | ||
12 | private final T target; | ||
13 | private final List<Variable> substitution; | ||
14 | |||
15 | protected CallAtom(CallPolarity polarity, T target, List<Variable> substitution) { | ||
16 | if (substitution.size() != target.arity()) { | ||
17 | throw new IllegalArgumentException("%s needs %d arguments, but got %s".formatted(target.name(), | ||
18 | target.arity(), substitution.size())); | ||
19 | } | ||
20 | if (polarity.isTransitive() && target.arity() != 2) { | ||
21 | throw new IllegalArgumentException("Transitive closures can only take binary relations"); | ||
22 | } | ||
23 | this.polarity = polarity; | ||
24 | this.target = target; | ||
25 | this.substitution = substitution; | ||
26 | } | ||
27 | |||
28 | protected CallAtom(CallPolarity polarity, T target, Variable... substitution) { | ||
29 | this(polarity, target, List.of(substitution)); | ||
30 | } | ||
31 | |||
32 | protected CallAtom(boolean positive, T target, List<Variable> substitution) { | ||
33 | this(CallPolarity.fromBoolean(positive), target, substitution); | ||
34 | } | ||
35 | |||
36 | protected CallAtom(boolean positive, T target, Variable... substitution) { | ||
37 | this(positive, target, List.of(substitution)); | ||
38 | } | ||
39 | |||
40 | protected CallAtom(T target, List<Variable> substitution) { | ||
41 | this(true, target, substitution); | ||
42 | } | ||
43 | |||
44 | protected CallAtom(T target, Variable... substitution) { | ||
45 | this(target, List.of(substitution)); | ||
46 | } | ||
47 | |||
48 | public CallPolarity getPolarity() { | ||
49 | return polarity; | ||
50 | } | ||
51 | |||
52 | public T getTarget() { | ||
53 | return target; | ||
54 | } | ||
55 | |||
56 | public List<Variable> getSubstitution() { | ||
57 | return substitution; | ||
58 | } | ||
59 | |||
60 | @Override | ||
61 | public void collectAllVariables(Set<Variable> variables) { | ||
62 | if (polarity.isPositive()) { | ||
63 | variables.addAll(substitution); | ||
64 | } | ||
65 | } | ||
66 | |||
67 | @Override | ||
68 | public boolean equals(Object o) { | ||
69 | if (this == o) return true; | ||
70 | if (o == null || getClass() != o.getClass()) return false; | ||
71 | CallAtom<?> callAtom = (CallAtom<?>) o; | ||
72 | return polarity == callAtom.polarity && Objects.equals(target, callAtom.target) && Objects.equals(substitution | ||
73 | , callAtom.substitution); | ||
74 | } | ||
75 | |||
76 | @Override | ||
77 | public int hashCode() { | ||
78 | return Objects.hash(polarity, target, substitution); | ||
79 | } | ||
80 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/atom/CallPolarity.java b/subprojects/store/src/main/java/tools/refinery/store/query/atom/CallPolarity.java deleted file mode 100644 index 957e9b7b..00000000 --- a/subprojects/store/src/main/java/tools/refinery/store/query/atom/CallPolarity.java +++ /dev/null | |||
@@ -1,28 +0,0 @@ | |||
1 | package tools.refinery.store.query.atom; | ||
2 | |||
3 | public enum CallPolarity { | ||
4 | POSITIVE(true, false), | ||
5 | NEGATIVE(false, false), | ||
6 | TRANSITIVE(true, true); | ||
7 | |||
8 | private final boolean positive; | ||
9 | |||
10 | private final boolean transitive; | ||
11 | |||
12 | CallPolarity(boolean positive, boolean transitive) { | ||
13 | this.positive = positive; | ||
14 | this.transitive = transitive; | ||
15 | } | ||
16 | |||
17 | public boolean isPositive() { | ||
18 | return positive; | ||
19 | } | ||
20 | |||
21 | public boolean isTransitive() { | ||
22 | return transitive; | ||
23 | } | ||
24 | |||
25 | public static CallPolarity fromBoolean(boolean positive) { | ||
26 | return positive ? POSITIVE : NEGATIVE; | ||
27 | } | ||
28 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/atom/ConstantAtom.java b/subprojects/store/src/main/java/tools/refinery/store/query/atom/ConstantAtom.java deleted file mode 100644 index 13dae7d0..00000000 --- a/subprojects/store/src/main/java/tools/refinery/store/query/atom/ConstantAtom.java +++ /dev/null | |||
@@ -1,12 +0,0 @@ | |||
1 | package tools.refinery.store.query.atom; | ||
2 | |||
3 | import tools.refinery.store.query.Variable; | ||
4 | |||
5 | import java.util.Set; | ||
6 | |||
7 | public record ConstantAtom(Variable variable, int nodeId) implements DNFAtom { | ||
8 | @Override | ||
9 | public void collectAllVariables(Set<Variable> variables) { | ||
10 | variables.add(variable); | ||
11 | } | ||
12 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/atom/DNFAtom.java b/subprojects/store/src/main/java/tools/refinery/store/query/atom/DNFAtom.java deleted file mode 100644 index ebf71236..00000000 --- a/subprojects/store/src/main/java/tools/refinery/store/query/atom/DNFAtom.java +++ /dev/null | |||
@@ -1,9 +0,0 @@ | |||
1 | package tools.refinery.store.query.atom; | ||
2 | |||
3 | import tools.refinery.store.query.Variable; | ||
4 | |||
5 | import java.util.Set; | ||
6 | |||
7 | public interface DNFAtom { | ||
8 | void collectAllVariables(Set<Variable> variables); | ||
9 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/atom/DNFCallAtom.java b/subprojects/store/src/main/java/tools/refinery/store/query/atom/DNFCallAtom.java deleted file mode 100644 index 3b4f5cd1..00000000 --- a/subprojects/store/src/main/java/tools/refinery/store/query/atom/DNFCallAtom.java +++ /dev/null | |||
@@ -1,32 +0,0 @@ | |||
1 | package tools.refinery.store.query.atom; | ||
2 | |||
3 | import tools.refinery.store.query.DNF; | ||
4 | import tools.refinery.store.query.Variable; | ||
5 | |||
6 | import java.util.List; | ||
7 | |||
8 | public class DNFCallAtom extends CallAtom<DNF> { | ||
9 | public DNFCallAtom(CallPolarity polarity, DNF target, List<Variable> substitution) { | ||
10 | super(polarity, target, substitution); | ||
11 | } | ||
12 | |||
13 | public DNFCallAtom(CallPolarity polarity, DNF target, Variable... substitution) { | ||
14 | super(polarity, target, substitution); | ||
15 | } | ||
16 | |||
17 | public DNFCallAtom(boolean positive, DNF target, List<Variable> substitution) { | ||
18 | super(positive, target, substitution); | ||
19 | } | ||
20 | |||
21 | public DNFCallAtom(boolean positive, DNF target, Variable... substitution) { | ||
22 | super(positive, target, substitution); | ||
23 | } | ||
24 | |||
25 | public DNFCallAtom(DNF target, List<Variable> substitution) { | ||
26 | super(target, substitution); | ||
27 | } | ||
28 | |||
29 | public DNFCallAtom(DNF target, Variable... substitution) { | ||
30 | super(target, substitution); | ||
31 | } | ||
32 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/atom/EquivalenceAtom.java b/subprojects/store/src/main/java/tools/refinery/store/query/atom/EquivalenceAtom.java deleted file mode 100644 index b1b3a6f7..00000000 --- a/subprojects/store/src/main/java/tools/refinery/store/query/atom/EquivalenceAtom.java +++ /dev/null | |||
@@ -1,17 +0,0 @@ | |||
1 | package tools.refinery.store.query.atom; | ||
2 | |||
3 | import tools.refinery.store.query.Variable; | ||
4 | |||
5 | import java.util.Set; | ||
6 | |||
7 | public record EquivalenceAtom(boolean positive, Variable left, Variable right) implements DNFAtom { | ||
8 | public EquivalenceAtom(Variable left, Variable right) { | ||
9 | this(true, left, right); | ||
10 | } | ||
11 | |||
12 | @Override | ||
13 | public void collectAllVariables(Set<Variable> variables) { | ||
14 | variables.add(left); | ||
15 | variables.add(right); | ||
16 | } | ||
17 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/atom/Modality.java b/subprojects/store/src/main/java/tools/refinery/store/query/atom/Modality.java deleted file mode 100644 index e389f563..00000000 --- a/subprojects/store/src/main/java/tools/refinery/store/query/atom/Modality.java +++ /dev/null | |||
@@ -1,22 +0,0 @@ | |||
1 | package tools.refinery.store.query.atom; | ||
2 | |||
3 | import java.util.Locale; | ||
4 | |||
5 | public enum Modality { | ||
6 | MUST, | ||
7 | MAY, | ||
8 | CURRENT; | ||
9 | |||
10 | public Modality negate() { | ||
11 | return switch(this) { | ||
12 | case MUST -> MAY; | ||
13 | case MAY -> MUST; | ||
14 | case CURRENT -> CURRENT; | ||
15 | }; | ||
16 | } | ||
17 | |||
18 | @Override | ||
19 | public String toString() { | ||
20 | return name().toLowerCase(Locale.ROOT); | ||
21 | } | ||
22 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/atom/RelationViewAtom.java b/subprojects/store/src/main/java/tools/refinery/store/query/atom/RelationViewAtom.java deleted file mode 100644 index a2b176c4..00000000 --- a/subprojects/store/src/main/java/tools/refinery/store/query/atom/RelationViewAtom.java +++ /dev/null | |||
@@ -1,32 +0,0 @@ | |||
1 | package tools.refinery.store.query.atom; | ||
2 | |||
3 | import tools.refinery.store.query.Variable; | ||
4 | import tools.refinery.store.query.view.AnyRelationView; | ||
5 | |||
6 | import java.util.List; | ||
7 | |||
8 | public final class RelationViewAtom extends CallAtom<AnyRelationView> { | ||
9 | public RelationViewAtom(CallPolarity polarity, AnyRelationView target, List<Variable> substitution) { | ||
10 | super(polarity, target, substitution); | ||
11 | } | ||
12 | |||
13 | public RelationViewAtom(CallPolarity polarity, AnyRelationView target, Variable... substitution) { | ||
14 | super(polarity, target, substitution); | ||
15 | } | ||
16 | |||
17 | public RelationViewAtom(boolean positive, AnyRelationView target, List<Variable> substitution) { | ||
18 | super(positive, target, substitution); | ||
19 | } | ||
20 | |||
21 | public RelationViewAtom(boolean positive, AnyRelationView target, Variable... substitution) { | ||
22 | super(positive, target, substitution); | ||
23 | } | ||
24 | |||
25 | public RelationViewAtom(AnyRelationView target, List<Variable> substitution) { | ||
26 | super(target, substitution); | ||
27 | } | ||
28 | |||
29 | public RelationViewAtom(AnyRelationView target, Variable... substitution) { | ||
30 | super(target, substitution); | ||
31 | } | ||
32 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/view/AnyRelationView.java b/subprojects/store/src/main/java/tools/refinery/store/query/view/AnyRelationView.java deleted file mode 100644 index 328cde3a..00000000 --- a/subprojects/store/src/main/java/tools/refinery/store/query/view/AnyRelationView.java +++ /dev/null | |||
@@ -1,24 +0,0 @@ | |||
1 | package tools.refinery.store.query.view; | ||
2 | |||
3 | import tools.refinery.store.model.Model; | ||
4 | import tools.refinery.store.query.FunctionalDependency; | ||
5 | import tools.refinery.store.representation.AnySymbol; | ||
6 | import tools.refinery.store.query.RelationLike; | ||
7 | |||
8 | import java.util.Set; | ||
9 | |||
10 | public sealed interface AnyRelationView extends RelationLike permits RelationView { | ||
11 | AnySymbol getSymbol(); | ||
12 | |||
13 | default Set<FunctionalDependency<Integer>> getFunctionalDependencies() { | ||
14 | return Set.of(); | ||
15 | } | ||
16 | |||
17 | default Set<RelationViewImplication> getImpliedRelationViews() { | ||
18 | return Set.of(); | ||
19 | } | ||
20 | |||
21 | boolean get(Model model, Object[] tuple); | ||
22 | |||
23 | Iterable<Object[]> getAll(Model model); | ||
24 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/view/FilteredRelationView.java b/subprojects/store/src/main/java/tools/refinery/store/query/view/FilteredRelationView.java deleted file mode 100644 index 64c601bb..00000000 --- a/subprojects/store/src/main/java/tools/refinery/store/query/view/FilteredRelationView.java +++ /dev/null | |||
@@ -1,49 +0,0 @@ | |||
1 | package tools.refinery.store.query.view; | ||
2 | |||
3 | import tools.refinery.store.tuple.Tuple; | ||
4 | import tools.refinery.store.representation.Symbol; | ||
5 | |||
6 | import java.util.Objects; | ||
7 | import java.util.function.BiPredicate; | ||
8 | import java.util.function.Predicate; | ||
9 | |||
10 | public class FilteredRelationView<T> extends TuplePreservingRelationView<T> { | ||
11 | private final BiPredicate<Tuple, T> predicate; | ||
12 | |||
13 | public FilteredRelationView(Symbol<T> symbol, String name, BiPredicate<Tuple, T> predicate) { | ||
14 | super(symbol, name); | ||
15 | this.predicate = predicate; | ||
16 | } | ||
17 | |||
18 | public FilteredRelationView(Symbol<T> symbol, BiPredicate<Tuple, T> predicate) { | ||
19 | super(symbol); | ||
20 | this.predicate = predicate; | ||
21 | } | ||
22 | |||
23 | public FilteredRelationView(Symbol<T> symbol, String name, Predicate<T> predicate) { | ||
24 | this(symbol, name, (k, v) -> predicate.test(v)); | ||
25 | } | ||
26 | |||
27 | public FilteredRelationView(Symbol<T> symbol, Predicate<T> predicate) { | ||
28 | this(symbol, (k, v) -> predicate.test(v)); | ||
29 | } | ||
30 | |||
31 | @Override | ||
32 | public boolean filter(Tuple key, T value) { | ||
33 | return this.predicate.test(key, value); | ||
34 | } | ||
35 | |||
36 | @Override | ||
37 | public boolean equals(Object o) { | ||
38 | if (this == o) return true; | ||
39 | if (o == null || getClass() != o.getClass()) return false; | ||
40 | if (!super.equals(o)) return false; | ||
41 | FilteredRelationView<?> that = (FilteredRelationView<?>) o; | ||
42 | return Objects.equals(predicate, that.predicate); | ||
43 | } | ||
44 | |||
45 | @Override | ||
46 | public int hashCode() { | ||
47 | return Objects.hash(super.hashCode(), predicate); | ||
48 | } | ||
49 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/view/FunctionalRelationView.java b/subprojects/store/src/main/java/tools/refinery/store/query/view/FunctionalRelationView.java deleted file mode 100644 index 3d278a8b..00000000 --- a/subprojects/store/src/main/java/tools/refinery/store/query/view/FunctionalRelationView.java +++ /dev/null | |||
@@ -1,71 +0,0 @@ | |||
1 | package tools.refinery.store.query.view; | ||
2 | |||
3 | import tools.refinery.store.model.Model; | ||
4 | import tools.refinery.store.query.FunctionalDependency; | ||
5 | import tools.refinery.store.representation.Symbol; | ||
6 | import tools.refinery.store.tuple.Tuple; | ||
7 | import tools.refinery.store.tuple.Tuple1; | ||
8 | |||
9 | import java.util.Set; | ||
10 | import java.util.stream.Collectors; | ||
11 | import java.util.stream.IntStream; | ||
12 | |||
13 | public final class FunctionalRelationView<T> extends RelationView<T> { | ||
14 | public FunctionalRelationView(Symbol<T> symbol, String name) { | ||
15 | super(symbol, name); | ||
16 | } | ||
17 | |||
18 | public FunctionalRelationView(Symbol<T> symbol) { | ||
19 | super(symbol); | ||
20 | } | ||
21 | |||
22 | @Override | ||
23 | public Set<FunctionalDependency<Integer>> getFunctionalDependencies() { | ||
24 | var arity = getSymbol().arity(); | ||
25 | var forEach = IntStream.range(0, arity).boxed().collect(Collectors.toUnmodifiableSet()); | ||
26 | var unique = Set.of(arity); | ||
27 | return Set.of(new FunctionalDependency<>(forEach, unique)); | ||
28 | } | ||
29 | |||
30 | @Override | ||
31 | public Set<RelationViewImplication> getImpliedRelationViews() { | ||
32 | var symbol = getSymbol(); | ||
33 | var impliedIndices = IntStream.range(0, symbol.arity()).boxed().toList(); | ||
34 | var keyOnlyRelationView = new KeyOnlyRelationView<>(symbol); | ||
35 | return Set.of(new RelationViewImplication(this, keyOnlyRelationView, impliedIndices)); | ||
36 | } | ||
37 | |||
38 | @Override | ||
39 | public boolean filter(Tuple key, T value) { | ||
40 | return true; | ||
41 | } | ||
42 | |||
43 | @Override | ||
44 | public Object[] forwardMap(Tuple key, T value) { | ||
45 | int size = key.getSize(); | ||
46 | Object[] result = new Object[size + 1]; | ||
47 | for (int i = 0; i < size; i++) { | ||
48 | result[i] = Tuple.of(key.get(i)); | ||
49 | } | ||
50 | result[key.getSize()] = value; | ||
51 | return result; | ||
52 | } | ||
53 | |||
54 | @Override | ||
55 | public boolean get(Model model, Object[] tuple) { | ||
56 | int[] content = new int[tuple.length - 1]; | ||
57 | for (int i = 0; i < tuple.length - 1; i++) { | ||
58 | content[i] = ((Tuple1) tuple[i]).value0(); | ||
59 | } | ||
60 | Tuple key = Tuple.of(content); | ||
61 | @SuppressWarnings("unchecked") | ||
62 | T valueInTuple = (T) tuple[tuple.length - 1]; | ||
63 | T valueInMap = model.getInterpretation(getSymbol()).get(key); | ||
64 | return valueInTuple.equals(valueInMap); | ||
65 | } | ||
66 | |||
67 | @Override | ||
68 | public int arity() { | ||
69 | return getSymbol().arity() + 1; | ||
70 | } | ||
71 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/view/KeyOnlyRelationView.java b/subprojects/store/src/main/java/tools/refinery/store/query/view/KeyOnlyRelationView.java deleted file mode 100644 index e1b2e45b..00000000 --- a/subprojects/store/src/main/java/tools/refinery/store/query/view/KeyOnlyRelationView.java +++ /dev/null | |||
@@ -1,36 +0,0 @@ | |||
1 | package tools.refinery.store.query.view; | ||
2 | |||
3 | import tools.refinery.store.representation.Symbol; | ||
4 | import tools.refinery.store.tuple.Tuple; | ||
5 | |||
6 | import java.util.Objects; | ||
7 | |||
8 | public final class KeyOnlyRelationView<T> extends TuplePreservingRelationView<T> { | ||
9 | public static final String VIEW_NAME = "key"; | ||
10 | |||
11 | private final T defaultValue; | ||
12 | |||
13 | public KeyOnlyRelationView(Symbol<T> symbol) { | ||
14 | super(symbol, VIEW_NAME); | ||
15 | defaultValue = symbol.defaultValue(); | ||
16 | } | ||
17 | |||
18 | @Override | ||
19 | public boolean filter(Tuple key, T value) { | ||
20 | return !Objects.equals(value, defaultValue); | ||
21 | } | ||
22 | |||
23 | @Override | ||
24 | public boolean equals(Object o) { | ||
25 | if (this == o) return true; | ||
26 | if (o == null || getClass() != o.getClass()) return false; | ||
27 | if (!super.equals(o)) return false; | ||
28 | KeyOnlyRelationView<?> that = (KeyOnlyRelationView<?>) o; | ||
29 | return Objects.equals(defaultValue, that.defaultValue); | ||
30 | } | ||
31 | |||
32 | @Override | ||
33 | public int hashCode() { | ||
34 | return Objects.hash(super.hashCode(), defaultValue); | ||
35 | } | ||
36 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/view/RelationView.java b/subprojects/store/src/main/java/tools/refinery/store/query/view/RelationView.java deleted file mode 100644 index bbec1e73..00000000 --- a/subprojects/store/src/main/java/tools/refinery/store/query/view/RelationView.java +++ /dev/null | |||
@@ -1,62 +0,0 @@ | |||
1 | package tools.refinery.store.query.view; | ||
2 | |||
3 | import tools.refinery.store.map.CursorAsIterator; | ||
4 | import tools.refinery.store.model.Model; | ||
5 | import tools.refinery.store.representation.Symbol; | ||
6 | import tools.refinery.store.tuple.Tuple; | ||
7 | |||
8 | import java.util.Objects; | ||
9 | import java.util.UUID; | ||
10 | |||
11 | /** | ||
12 | * Represents a view of a {@link Symbol} that can be queried. | ||
13 | * | ||
14 | * @param <T> | ||
15 | * @author Oszkar Semerath | ||
16 | */ | ||
17 | public abstract non-sealed class RelationView<T> implements AnyRelationView { | ||
18 | private final Symbol<T> symbol; | ||
19 | |||
20 | private final String name; | ||
21 | |||
22 | protected RelationView(Symbol<T> symbol, String name) { | ||
23 | this.symbol = symbol; | ||
24 | this.name = name; | ||
25 | } | ||
26 | |||
27 | protected RelationView(Symbol<T> representation) { | ||
28 | this(representation, UUID.randomUUID().toString()); | ||
29 | } | ||
30 | |||
31 | @Override | ||
32 | public Symbol<T> getSymbol() { | ||
33 | return symbol; | ||
34 | } | ||
35 | |||
36 | @Override | ||
37 | public String name() { | ||
38 | return symbol.name() + "#" + name; | ||
39 | } | ||
40 | |||
41 | public abstract boolean filter(Tuple key, T value); | ||
42 | |||
43 | public abstract Object[] forwardMap(Tuple key, T value); | ||
44 | |||
45 | @Override | ||
46 | public Iterable<Object[]> getAll(Model model) { | ||
47 | return (() -> new CursorAsIterator<>(model.getInterpretation(symbol).getAll(), this::forwardMap, this::filter)); | ||
48 | } | ||
49 | |||
50 | @Override | ||
51 | public boolean equals(Object o) { | ||
52 | if (this == o) return true; | ||
53 | if (o == null || getClass() != o.getClass()) return false; | ||
54 | RelationView<?> that = (RelationView<?>) o; | ||
55 | return Objects.equals(symbol, that.symbol) && Objects.equals(name, that.name); | ||
56 | } | ||
57 | |||
58 | @Override | ||
59 | public int hashCode() { | ||
60 | return Objects.hash(symbol, name); | ||
61 | } | ||
62 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/view/RelationViewImplication.java b/subprojects/store/src/main/java/tools/refinery/store/query/view/RelationViewImplication.java deleted file mode 100644 index 2ba1fcc4..00000000 --- a/subprojects/store/src/main/java/tools/refinery/store/query/view/RelationViewImplication.java +++ /dev/null | |||
@@ -1,19 +0,0 @@ | |||
1 | package tools.refinery.store.query.view; | ||
2 | |||
3 | import java.util.List; | ||
4 | |||
5 | public record RelationViewImplication(AnyRelationView implyingRelationView, AnyRelationView impliedRelationView, | ||
6 | List<Integer> impliedIndices) { | ||
7 | public RelationViewImplication { | ||
8 | if (impliedIndices.size() != impliedRelationView.arity()) { | ||
9 | throw new IllegalArgumentException("Expected %d implied indices for %s, but %d are provided" | ||
10 | .formatted(impliedRelationView.arity(), impliedRelationView, impliedIndices.size())); | ||
11 | } | ||
12 | for (var index : impliedIndices) { | ||
13 | if (impliedRelationView.invalidIndex(index)) { | ||
14 | throw new IllegalArgumentException("%d is not a valid index for %s".formatted(index, | ||
15 | implyingRelationView)); | ||
16 | } | ||
17 | } | ||
18 | } | ||
19 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/view/TuplePreservingRelationView.java b/subprojects/store/src/main/java/tools/refinery/store/query/view/TuplePreservingRelationView.java deleted file mode 100644 index 8cc4986e..00000000 --- a/subprojects/store/src/main/java/tools/refinery/store/query/view/TuplePreservingRelationView.java +++ /dev/null | |||
@@ -1,44 +0,0 @@ | |||
1 | package tools.refinery.store.query.view; | ||
2 | |||
3 | import tools.refinery.store.model.Model; | ||
4 | import tools.refinery.store.tuple.Tuple; | ||
5 | import tools.refinery.store.tuple.Tuple1; | ||
6 | import tools.refinery.store.representation.Symbol; | ||
7 | |||
8 | public abstract class TuplePreservingRelationView<T> extends RelationView<T> { | ||
9 | protected TuplePreservingRelationView(Symbol<T> symbol, String name) { | ||
10 | super(symbol, name); | ||
11 | } | ||
12 | |||
13 | protected TuplePreservingRelationView(Symbol<T> symbol) { | ||
14 | super(symbol); | ||
15 | } | ||
16 | |||
17 | public Object[] forwardMap(Tuple key) { | ||
18 | Object[] result = new Object[key.getSize()]; | ||
19 | for (int i = 0; i < key.getSize(); i++) { | ||
20 | result[i] = Tuple.of(key.get(i)); | ||
21 | } | ||
22 | return result; | ||
23 | } | ||
24 | |||
25 | @Override | ||
26 | public Object[] forwardMap(Tuple key, T value) { | ||
27 | return forwardMap(key); | ||
28 | } | ||
29 | |||
30 | @Override | ||
31 | public boolean get(Model model, Object[] tuple) { | ||
32 | int[] content = new int[tuple.length]; | ||
33 | for (int i = 0; i < tuple.length; i++) { | ||
34 | content[i] = ((Tuple1) tuple[i]).value0(); | ||
35 | } | ||
36 | Tuple key = Tuple.of(content); | ||
37 | T value = model.getInterpretation(getSymbol()).get(key); | ||
38 | return filter(key, value); | ||
39 | } | ||
40 | |||
41 | public int arity() { | ||
42 | return this.getSymbol().arity(); | ||
43 | } | ||
44 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/representation/AbstractDomain.java b/subprojects/store/src/main/java/tools/refinery/store/representation/AbstractDomain.java new file mode 100644 index 00000000..18903ead --- /dev/null +++ b/subprojects/store/src/main/java/tools/refinery/store/representation/AbstractDomain.java | |||
@@ -0,0 +1,29 @@ | |||
1 | package tools.refinery.store.representation; | ||
2 | |||
3 | import java.util.Optional; | ||
4 | |||
5 | public non-sealed interface AbstractDomain<A, C> extends AnyAbstractDomain { | ||
6 | @Override | ||
7 | Class<A> abstractType(); | ||
8 | |||
9 | @Override | ||
10 | Class<C> concreteType(); | ||
11 | |||
12 | A toAbstract(C concreteValue); | ||
13 | |||
14 | Optional<C> toConcrete(A abstractValue); | ||
15 | |||
16 | default boolean isConcrete(A abstractValue) { | ||
17 | return toConcrete(abstractValue).isPresent(); | ||
18 | } | ||
19 | |||
20 | boolean isRefinement(A originalValue, A refinedValue); | ||
21 | |||
22 | A commonRefinement(A leftValue, A rightValue); | ||
23 | |||
24 | A commonAncestor(A leftValue, A rightValue); | ||
25 | |||
26 | A unknown(); | ||
27 | |||
28 | boolean isError(A abstractValue); | ||
29 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/representation/AnyAbstractDomain.java b/subprojects/store/src/main/java/tools/refinery/store/representation/AnyAbstractDomain.java new file mode 100644 index 00000000..4c428a1e --- /dev/null +++ b/subprojects/store/src/main/java/tools/refinery/store/representation/AnyAbstractDomain.java | |||
@@ -0,0 +1,7 @@ | |||
1 | package tools.refinery.store.representation; | ||
2 | |||
3 | public sealed interface AnyAbstractDomain permits AbstractDomain { | ||
4 | Class<?> abstractType(); | ||
5 | |||
6 | Class<?> concreteType(); | ||
7 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/representation/Symbol.java b/subprojects/store/src/main/java/tools/refinery/store/representation/Symbol.java index 85ea15f4..30b1c03f 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/representation/Symbol.java +++ b/subprojects/store/src/main/java/tools/refinery/store/representation/Symbol.java | |||
@@ -1,12 +1,6 @@ | |||
1 | package tools.refinery.store.representation; | 1 | package tools.refinery.store.representation; |
2 | 2 | ||
3 | import java.util.Objects; | ||
4 | |||
5 | public record Symbol<T>(String name, int arity, Class<T> valueType, T defaultValue) implements AnySymbol { | 3 | public record Symbol<T>(String name, int arity, Class<T> valueType, T defaultValue) implements AnySymbol { |
6 | public boolean isDefaultValue(T value) { | ||
7 | return Objects.equals(defaultValue, value); | ||
8 | } | ||
9 | |||
10 | @Override | 4 | @Override |
11 | public boolean equals(Object o) { | 5 | public boolean equals(Object o) { |
12 | return this == o; | 6 | return this == o; |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/representation/TruthValueDomain.java b/subprojects/store/src/main/java/tools/refinery/store/representation/TruthValueDomain.java new file mode 100644 index 00000000..29858bce --- /dev/null +++ b/subprojects/store/src/main/java/tools/refinery/store/representation/TruthValueDomain.java | |||
@@ -0,0 +1,60 @@ | |||
1 | package tools.refinery.store.representation; | ||
2 | |||
3 | import java.util.Optional; | ||
4 | |||
5 | public final class TruthValueDomain implements AbstractDomain<TruthValue, Boolean> { | ||
6 | public static final TruthValueDomain INSTANCE = new TruthValueDomain(); | ||
7 | |||
8 | private TruthValueDomain() { | ||
9 | } | ||
10 | |||
11 | @Override | ||
12 | public Class<TruthValue> abstractType() { | ||
13 | return null; | ||
14 | } | ||
15 | |||
16 | @Override | ||
17 | public Class<Boolean> concreteType() { | ||
18 | return null; | ||
19 | } | ||
20 | |||
21 | @Override | ||
22 | public TruthValue toAbstract(Boolean concreteValue) { | ||
23 | return null; | ||
24 | } | ||
25 | |||
26 | @Override | ||
27 | public Optional<Boolean> toConcrete(TruthValue abstractValue) { | ||
28 | return Optional.empty(); | ||
29 | } | ||
30 | |||
31 | @Override | ||
32 | public boolean isConcrete(TruthValue abstractValue) { | ||
33 | return AbstractDomain.super.isConcrete(abstractValue); | ||
34 | } | ||
35 | |||
36 | @Override | ||
37 | public boolean isRefinement(TruthValue originalValue, TruthValue refinedValue) { | ||
38 | return false; | ||
39 | } | ||
40 | |||
41 | @Override | ||
42 | public TruthValue commonRefinement(TruthValue leftValue, TruthValue rightValue) { | ||
43 | return null; | ||
44 | } | ||
45 | |||
46 | @Override | ||
47 | public TruthValue commonAncestor(TruthValue leftValue, TruthValue rightValue) { | ||
48 | return null; | ||
49 | } | ||
50 | |||
51 | @Override | ||
52 | public TruthValue unknown() { | ||
53 | return null; | ||
54 | } | ||
55 | |||
56 | @Override | ||
57 | public boolean isError(TruthValue abstractValue) { | ||
58 | return false; | ||
59 | } | ||
60 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/tuple/TupleLike.java b/subprojects/store/src/main/java/tools/refinery/store/tuple/TupleLike.java index 470ca298..953ea9f8 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/tuple/TupleLike.java +++ b/subprojects/store/src/main/java/tools/refinery/store/tuple/TupleLike.java | |||
@@ -1,5 +1,8 @@ | |||
1 | package tools.refinery.store.tuple; | 1 | package tools.refinery.store.tuple; |
2 | 2 | ||
3 | import java.util.stream.Collectors; | ||
4 | import java.util.stream.IntStream; | ||
5 | |||
3 | public interface TupleLike { | 6 | public interface TupleLike { |
4 | int getSize(); | 7 | int getSize(); |
5 | 8 | ||
@@ -22,4 +25,11 @@ public interface TupleLike { | |||
22 | default -> Tuple.of(toArray()); | 25 | default -> Tuple.of(toArray()); |
23 | }; | 26 | }; |
24 | } | 27 | } |
28 | |||
29 | static String toString(TupleLike tuple) { | ||
30 | var valuesString = IntStream.range(0, tuple.getSize()) | ||
31 | .mapToObj(i -> Integer.toString(tuple.get(i))) | ||
32 | .collect(Collectors.joining(", ")); | ||
33 | return "[" + valuesString + "]"; | ||
34 | } | ||
25 | } | 35 | } |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/tuple/TupleN.java b/subprojects/store/src/main/java/tools/refinery/store/tuple/TupleN.java index 15fd063b..c3aed847 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/tuple/TupleN.java +++ b/subprojects/store/src/main/java/tools/refinery/store/tuple/TupleN.java | |||
@@ -1,7 +1,6 @@ | |||
1 | package tools.refinery.store.tuple; | 1 | package tools.refinery.store.tuple; |
2 | 2 | ||
3 | import java.util.Arrays; | 3 | import java.util.Arrays; |
4 | import java.util.stream.Collectors; | ||
5 | 4 | ||
6 | public record TupleN(int[] values) implements Tuple { | 5 | public record TupleN(int[] values) implements Tuple { |
7 | static final int CUSTOM_TUPLE_SIZE = 2; | 6 | static final int CUSTOM_TUPLE_SIZE = 2; |
@@ -29,8 +28,7 @@ public record TupleN(int[] values) implements Tuple { | |||
29 | 28 | ||
30 | @Override | 29 | @Override |
31 | public String toString() { | 30 | public String toString() { |
32 | var valuesString = Arrays.stream(values).mapToObj(Integer::toString).collect(Collectors.joining(", ")); | 31 | return TupleLike.toString(this); |
33 | return "[" + valuesString + "]"; | ||
34 | } | 32 | } |
35 | 33 | ||
36 | @Override | 34 | @Override |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/util/CycleDetectingMapper.java b/subprojects/store/src/main/java/tools/refinery/store/util/CycleDetectingMapper.java new file mode 100644 index 00000000..8a151d01 --- /dev/null +++ b/subprojects/store/src/main/java/tools/refinery/store/util/CycleDetectingMapper.java | |||
@@ -0,0 +1,52 @@ | |||
1 | package tools.refinery.store.util; | ||
2 | |||
3 | import java.util.*; | ||
4 | import java.util.function.Function; | ||
5 | import java.util.stream.Collectors; | ||
6 | |||
7 | public class CycleDetectingMapper<T, R> { | ||
8 | private static final String SEPARATOR = " -> "; | ||
9 | |||
10 | private final Function<T, String> getName; | ||
11 | |||
12 | private final Function<T, R> doMap; | ||
13 | |||
14 | private final Set<T> inProgress = new LinkedHashSet<>(); | ||
15 | |||
16 | private final Map<T, R> results = new HashMap<>(); | ||
17 | |||
18 | public CycleDetectingMapper(Function<T, String> getName, Function<T, R> doMap) { | ||
19 | this.getName = getName; | ||
20 | this.doMap = doMap; | ||
21 | } | ||
22 | |||
23 | public R map(T input) { | ||
24 | if (inProgress.contains(input)) { | ||
25 | var path = inProgress.stream().map(getName).collect(Collectors.joining(SEPARATOR)); | ||
26 | throw new IllegalArgumentException("Circular reference %s%s%s detected".formatted(path, SEPARATOR, | ||
27 | getName.apply(input))); | ||
28 | } | ||
29 | // We can't use computeIfAbsent here, because translating referenced queries calls this method in a reentrant | ||
30 | // way, which would cause a ConcurrentModificationException with computeIfAbsent. | ||
31 | @SuppressWarnings("squid:S3824") | ||
32 | var result = results.get(input); | ||
33 | if (result == null) { | ||
34 | inProgress.add(input); | ||
35 | try { | ||
36 | result = doMap.apply(input); | ||
37 | results.put(input, result); | ||
38 | } finally { | ||
39 | inProgress.remove(input); | ||
40 | } | ||
41 | } | ||
42 | return result; | ||
43 | } | ||
44 | |||
45 | public List<T> getInProgress() { | ||
46 | return List.copyOf(inProgress); | ||
47 | } | ||
48 | |||
49 | public R getAlreadyMapped(T input) { | ||
50 | return results.get(input); | ||
51 | } | ||
52 | } | ||
diff --git a/subprojects/store/src/test/java/tools/refinery/store/model/tests/ModelTest.java b/subprojects/store/src/test/java/tools/refinery/store/model/tests/ModelTest.java index 371b5e47..9536a444 100644 --- a/subprojects/store/src/test/java/tools/refinery/store/model/tests/ModelTest.java +++ b/subprojects/store/src/test/java/tools/refinery/store/model/tests/ModelTest.java | |||
@@ -49,7 +49,7 @@ class ModelTest { | |||
49 | 49 | ||
50 | assertEquals(3, ageInterpretation.get(Tuple.of(0))); | 50 | assertEquals(3, ageInterpretation.get(Tuple.of(0))); |
51 | assertEquals(1, ageInterpretation.get(Tuple.of(1))); | 51 | assertEquals(1, ageInterpretation.get(Tuple.of(1))); |
52 | assertNull(ageInterpretation.get( Tuple.of(2))); | 52 | assertNull(ageInterpretation.get(Tuple.of(2))); |
53 | 53 | ||
54 | assertTrue(friendInterpretation.get(Tuple.of(0, 1))); | 54 | assertTrue(friendInterpretation.get(Tuple.of(0, 1))); |
55 | assertFalse(friendInterpretation.get(Tuple.of(0, 5))); | 55 | assertFalse(friendInterpretation.get(Tuple.of(0, 5))); |