aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--subprojects/language/src/main/java/tools/refinery/language/utils/ContainmentRole.java17
-rw-r--r--subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/ViatraQueryableModelStore.java58
-rw-r--r--subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/ViatraQueryableModel.java38
-rw-r--r--subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/DNF2PQuery.java126
-rw-r--r--subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/tests/QueryTest.java229
-rw-r--r--subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/tests/QueryTransactionTest.java20
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/model/ModelStoreImpl.java19
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/model/RelationLike.java7
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/model/representation/AuxilaryData.java22
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/model/representation/AuxiliaryData.java22
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/model/representation/DataRepresentation.java22
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/model/representation/Relation.java23
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/query/DNF.java121
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/query/DNFAnd.java9
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/query/DNFUtils.java19
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/query/QueryableModel.java19
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/query/QueryableModelStore.java3
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/query/Variable.java43
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/query/atom/AbstractCallAtom.java30
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/query/atom/AbstractSubstitutionAtom.java35
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/query/atom/CallKind.java24
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/query/atom/DNFAtom.java9
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/query/atom/DNFCallAtom.java40
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/query/atom/EquivalenceAtom.java17
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/query/atom/ModalRelationAtom.java38
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/query/atom/Modality.java7
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/query/atom/RelationAtom.java32
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/query/atom/RelationViewAtom.java31
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/query/building/DNFAnd.java37
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/query/building/DNFAtom.java33
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/query/building/DNFPredicate.java72
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/query/building/EquivalenceAtom.java44
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/query/building/PredicateAtom.java66
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/query/building/RelationAtom.java31
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/query/building/Variable.java22
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/query/view/RelationView.java6
36 files changed, 777 insertions, 614 deletions
diff --git a/subprojects/language/src/main/java/tools/refinery/language/utils/ContainmentRole.java b/subprojects/language/src/main/java/tools/refinery/language/utils/ContainmentRole.java
new file mode 100644
index 00000000..708e10a9
--- /dev/null
+++ b/subprojects/language/src/main/java/tools/refinery/language/utils/ContainmentRole.java
@@ -0,0 +1,17 @@
1package tools.refinery.language.utils;
2
3import tools.refinery.language.model.problem.PredicateKind;
4
5public enum ContainmentRole {
6 NONE,
7 CONTAINED,
8 CONTAINMENT;
9
10 public static ContainmentRole fromPredicateKind(PredicateKind predicateKind) {
11 return switch (predicateKind) {
12 case CONTAINED -> CONTAINED;
13 case CONTAINMENT -> CONTAINMENT;
14 default -> NONE;
15 };
16 }
17}
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/ViatraQueryableModelStore.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/ViatraQueryableModelStore.java
index a63abc3a..702eb659 100644
--- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/ViatraQueryableModelStore.java
+++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/ViatraQueryableModelStore.java
@@ -5,9 +5,11 @@ import tools.refinery.store.model.ModelDiffCursor;
5import tools.refinery.store.model.ModelStore; 5import tools.refinery.store.model.ModelStore;
6import tools.refinery.store.model.ModelStoreImpl; 6import tools.refinery.store.model.ModelStoreImpl;
7import tools.refinery.store.model.representation.DataRepresentation; 7import tools.refinery.store.model.representation.DataRepresentation;
8import tools.refinery.store.query.QueryableModel; 8import tools.refinery.store.query.*;
9import tools.refinery.store.query.QueryableModelStore; 9import tools.refinery.store.query.atom.DNFAtom;
10import tools.refinery.store.query.building.*; 10import tools.refinery.store.query.atom.DNFCallAtom;
11import tools.refinery.store.query.atom.EquivalenceAtom;
12import tools.refinery.store.query.atom.RelationViewAtom;
11import tools.refinery.store.query.viatra.internal.RawPatternMatcher; 13import tools.refinery.store.query.viatra.internal.RawPatternMatcher;
12import tools.refinery.store.query.viatra.internal.ViatraQueryableModel; 14import tools.refinery.store.query.viatra.internal.ViatraQueryableModel;
13import tools.refinery.store.query.viatra.internal.pquery.DNF2PQuery; 15import tools.refinery.store.query.viatra.internal.pquery.DNF2PQuery;
@@ -23,10 +25,10 @@ public class ViatraQueryableModelStore implements QueryableModelStore {
23 25
24 protected final Set<RelationView<?>> relationViews; 26 protected final Set<RelationView<?>> relationViews;
25 27
26 protected final Map<DNFPredicate, GenericQuerySpecification<RawPatternMatcher>> predicates; 28 protected final Map<DNF, GenericQuerySpecification<RawPatternMatcher>> predicates;
27 29
28 public ViatraQueryableModelStore(ModelStore store, Set<RelationView<?>> relationViews, 30 public ViatraQueryableModelStore(ModelStore store, Set<RelationView<?>> relationViews,
29 Set<DNFPredicate> predicates) { 31 Set<DNF> predicates) {
30 this.store = store; 32 this.store = store;
31 validateViews(store.getDataRepresentations(), relationViews); 33 validateViews(store.getDataRepresentations(), relationViews);
32 this.relationViews = Collections.unmodifiableSet(relationViews); 34 this.relationViews = Collections.unmodifiableSet(relationViews);
@@ -35,7 +37,7 @@ public class ViatraQueryableModelStore implements QueryableModelStore {
35 } 37 }
36 38
37 public ViatraQueryableModelStore(Set<DataRepresentation<?, ?>> dataRepresentations, 39 public ViatraQueryableModelStore(Set<DataRepresentation<?, ?>> dataRepresentations,
38 Set<RelationView<?>> relationViews, Set<DNFPredicate> predicates) { 40 Set<RelationView<?>> relationViews, Set<DNF> predicates) {
39 this(new ModelStoreImpl(dataRepresentations), relationViews, predicates); 41 this(new ModelStoreImpl(dataRepresentations), relationViews, predicates);
40 } 42 }
41 43
@@ -49,44 +51,46 @@ public class ViatraQueryableModelStore implements QueryableModelStore {
49 } 51 }
50 } 52 }
51 53
52 private void validatePredicates(Set<RelationView<?>> relationViews, Set<DNFPredicate> predicates) { 54 private void validatePredicates(Set<RelationView<?>> relationViews, Set<DNF> predicates) {
53 for (DNFPredicate dnfPredicate : predicates) { 55 for (DNF dnfPredicate : predicates) {
54 for (DNFAnd clause : dnfPredicate.getClauses()) { 56 for (DNFAnd clause : dnfPredicate.getClauses()) {
55 for (DNFAtom atom : clause.getConstraints()) { 57 for (DNFAtom atom : clause.constraints()) {
56 if (atom instanceof RelationAtom relationAtom) { 58 if (atom instanceof RelationViewAtom relationViewAtom) {
57 validateRelationAtom(relationViews, dnfPredicate, relationAtom); 59 validateRelationAtom(relationViews, dnfPredicate, relationViewAtom);
58 } else if (atom instanceof PredicateAtom predicateAtom) { 60 } else if (atom instanceof DNFCallAtom queryCallAtom) {
59 validatePredicateAtom(predicates, dnfPredicate, predicateAtom); 61 validatePredicateAtom(predicates, dnfPredicate, queryCallAtom);
62 } else if (!(atom instanceof EquivalenceAtom)) {
63 throw new IllegalArgumentException("Unknown constraint: " + atom.toString());
60 } 64 }
61 } 65 }
62 } 66 }
63 } 67 }
64 } 68 }
65 69
66 private void validateRelationAtom(Set<RelationView<?>> relationViews, DNFPredicate dnfPredicate, 70 private void validateRelationAtom(Set<RelationView<?>> relationViews, DNF dnfPredicate,
67 RelationAtom relationAtom) { 71 RelationViewAtom relationViewAtom) {
68 if (!relationViews.contains(relationAtom.view())) { 72 if (!relationViews.contains(relationViewAtom.getTarget())) {
69 throw new IllegalArgumentException( 73 throw new IllegalArgumentException(
70 "%s %s contains reference to a view %s that is not in the model.".formatted( 74 "%s %s contains reference to a view %s that is not in the model.".formatted(
71 DNFPredicate.class.getSimpleName(), dnfPredicate.getUniqueName(), 75 DNF.class.getSimpleName(), dnfPredicate.getUniqueName(),
72 relationAtom.view().getName())); 76 relationViewAtom.getTarget().getName()));
73 } 77 }
74 } 78 }
75 79
76 private void validatePredicateAtom(Set<DNFPredicate> predicates, DNFPredicate dnfPredicate, 80 private void validatePredicateAtom(Set<DNF> predicates, DNF dnfPredicate,
77 PredicateAtom predicateAtom) { 81 DNFCallAtom queryCallAtom) {
78 if (!predicates.contains(predicateAtom.getReferred())) { 82 if (!predicates.contains(queryCallAtom.getTarget())) {
79 throw new IllegalArgumentException( 83 throw new IllegalArgumentException(
80 "%s %s contains reference to a predicate %s that is not in the model.".formatted( 84 "%s %s contains reference to a predicate %s that is not in the model.".formatted(
81 DNFPredicate.class.getSimpleName(), dnfPredicate.getUniqueName(), 85 DNF.class.getSimpleName(), dnfPredicate.getUniqueName(),
82 predicateAtom.getReferred().getName())); 86 queryCallAtom.getTarget().getName()));
83 } 87 }
84 } 88 }
85 89
86 private Map<DNFPredicate, GenericQuerySpecification<RawPatternMatcher>> initPredicates(Set<DNFPredicate> predicates) { 90 private Map<DNF, GenericQuerySpecification<RawPatternMatcher>> initPredicates(Set<DNF> predicates) {
87 Map<DNFPredicate, GenericQuerySpecification<RawPatternMatcher>> result = new HashMap<>(); 91 Map<DNF, GenericQuerySpecification<RawPatternMatcher>> result = new HashMap<>();
88 var dnf2PQuery = new DNF2PQuery(); 92 var dnf2PQuery = new DNF2PQuery();
89 for (DNFPredicate dnfPredicate : predicates) { 93 for (DNF dnfPredicate : predicates) {
90 GenericQuerySpecification<RawPatternMatcher> query = dnf2PQuery.translate(dnfPredicate).build(); 94 GenericQuerySpecification<RawPatternMatcher> query = dnf2PQuery.translate(dnfPredicate).build();
91 result.put(dnfPredicate, query); 95 result.put(dnfPredicate, query);
92 } 96 }
@@ -105,7 +109,7 @@ public class ViatraQueryableModelStore implements QueryableModelStore {
105 } 109 }
106 110
107 @Override 111 @Override
108 public Set<DNFPredicate> getPredicates() { 112 public Set<DNF> getPredicates() {
109 return predicates.keySet(); 113 return predicates.keySet();
110 } 114 }
111 115
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/ViatraQueryableModel.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/ViatraQueryableModel.java
index 1c15e8f9..cd9fb180 100644
--- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/ViatraQueryableModel.java
+++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/ViatraQueryableModel.java
@@ -12,7 +12,7 @@ import tools.refinery.store.model.representation.DataRepresentation;
12import tools.refinery.store.model.representation.Relation; 12import tools.refinery.store.model.representation.Relation;
13import tools.refinery.store.query.QueryableModel; 13import tools.refinery.store.query.QueryableModel;
14import tools.refinery.store.query.QueryableModelStore; 14import tools.refinery.store.query.QueryableModelStore;
15import tools.refinery.store.query.building.DNFPredicate; 15import tools.refinery.store.query.DNF;
16import tools.refinery.store.tuple.Tuple; 16import tools.refinery.store.tuple.Tuple;
17import tools.refinery.store.tuple.TupleLike; 17import tools.refinery.store.tuple.TupleLike;
18 18
@@ -27,16 +27,16 @@ public class ViatraQueryableModel implements QueryableModel {
27 27
28 protected final Model model; 28 protected final Model model;
29 29
30 protected final Map<DNFPredicate, GenericQuerySpecification<RawPatternMatcher>> predicates2PQuery; 30 protected final Map<DNF, GenericQuerySpecification<RawPatternMatcher>> predicates2PQuery;
31 31
32 protected RelationalScope scope; 32 protected RelationalScope scope;
33 33
34 protected AdvancedViatraQueryEngine engine; 34 protected AdvancedViatraQueryEngine engine;
35 35
36 protected Map<DNFPredicate, RawPatternMatcher> predicate2Matcher; 36 protected Map<DNF, RawPatternMatcher> predicate2Matcher;
37 37
38 public ViatraQueryableModel(QueryableModelStore store, Model model, 38 public ViatraQueryableModel(QueryableModelStore store, Model model,
39 Map<DNFPredicate, GenericQuerySpecification<RawPatternMatcher>> predicates2PQuery) { 39 Map<DNF, GenericQuerySpecification<RawPatternMatcher>> predicates2PQuery) {
40 this.store = store; 40 this.store = store;
41 this.model = model; 41 this.model = model;
42 this.predicates2PQuery = predicates2PQuery; 42 this.predicates2PQuery = predicates2PQuery;
@@ -49,15 +49,15 @@ public class ViatraQueryableModel implements QueryableModel {
49 this.predicate2Matcher = initMatchers(this.engine, this.predicates2PQuery); 49 this.predicate2Matcher = initMatchers(this.engine, this.predicates2PQuery);
50 } 50 }
51 51
52 private Map<DNFPredicate, RawPatternMatcher> initMatchers( 52 private Map<DNF, RawPatternMatcher> initMatchers(
53 AdvancedViatraQueryEngine engine, 53 AdvancedViatraQueryEngine engine,
54 Map<DNFPredicate, GenericQuerySpecification<RawPatternMatcher>> predicates2pQuery) { 54 Map<DNF, GenericQuerySpecification<RawPatternMatcher>> predicates2pQuery) {
55 // 1. prepare group 55 // 1. prepare group
56 IQueryGroup queryGroup = GenericQueryGroup.of(Set.copyOf(predicates2pQuery.values())); 56 IQueryGroup queryGroup = GenericQueryGroup.of(Set.copyOf(predicates2pQuery.values()));
57 engine.prepareGroup(queryGroup, null); 57 engine.prepareGroup(queryGroup, null);
58 58
59 // 2. then get all matchers 59 // 2. then get all matchers
60 Map<DNFPredicate, RawPatternMatcher> result = new HashMap<>(); 60 Map<DNF, RawPatternMatcher> result = new HashMap<>();
61 for (var entry : predicates2pQuery.entrySet()) { 61 for (var entry : predicates2pQuery.entrySet()) {
62 var matcher = engine.getMatcher(entry.getValue()); 62 var matcher = engine.getMatcher(entry.getValue());
63 result.put(entry.getKey(), matcher); 63 result.put(entry.getKey(), matcher);
@@ -71,7 +71,7 @@ public class ViatraQueryableModel implements QueryableModel {
71 } 71 }
72 72
73 @Override 73 @Override
74 public Set<DNFPredicate> getPredicates() { 74 public Set<DNF> getPredicates() {
75 return store.getPredicates(); 75 return store.getPredicates();
76 } 76 }
77 77
@@ -117,7 +117,7 @@ public class ViatraQueryableModel implements QueryableModel {
117 return model.getSize(representation); 117 return model.getSize(representation);
118 } 118 }
119 119
120 protected RawPatternMatcher getMatcher(DNFPredicate predicate) { 120 protected RawPatternMatcher getMatcher(DNF predicate) {
121 var result = this.predicate2Matcher.get(predicate); 121 var result = this.predicate2Matcher.get(predicate);
122 if (result == null) { 122 if (result == null) {
123 throw new IllegalArgumentException("Model does not contain predicate %s".formatted(predicate.getName())); 123 throw new IllegalArgumentException("Model does not contain predicate %s".formatted(predicate.getName()));
@@ -125,8 +125,8 @@ public class ViatraQueryableModel implements QueryableModel {
125 return result; 125 return result;
126 } 126 }
127 127
128 protected void validateParameters(DNFPredicate predicate, Tuple parameters) { 128 protected void validateParameters(DNF predicate, Tuple parameters) {
129 int predicateArity = predicate.getVariables().size(); 129 int predicateArity = predicate.getParameters().size();
130 int parameterArity = parameters.getSize(); 130 int parameterArity = parameters.getSize();
131 if (parameterArity != predicateArity) { 131 if (parameterArity != predicateArity) {
132 throw new IllegalArgumentException( 132 throw new IllegalArgumentException(
@@ -136,45 +136,45 @@ public class ViatraQueryableModel implements QueryableModel {
136 } 136 }
137 137
138 @Override 138 @Override
139 public boolean hasResult(DNFPredicate predicate) { 139 public boolean hasResult(DNF predicate) {
140 return getMatcher(predicate).hasResult(); 140 return getMatcher(predicate).hasResult();
141 } 141 }
142 142
143 @Override 143 @Override
144 public boolean hasResult(DNFPredicate predicate, Tuple parameters) { 144 public boolean hasResult(DNF predicate, Tuple parameters) {
145 validateParameters(predicate, parameters); 145 validateParameters(predicate, parameters);
146 return getMatcher(predicate).hasResult(parameters); 146 return getMatcher(predicate).hasResult(parameters);
147 } 147 }
148 148
149 @Override 149 @Override
150 public Optional<TupleLike> oneResult(DNFPredicate predicate) { 150 public Optional<TupleLike> oneResult(DNF predicate) {
151 return getMatcher(predicate).oneResult(); 151 return getMatcher(predicate).oneResult();
152 } 152 }
153 153
154 @Override 154 @Override
155 public Optional<TupleLike> oneResult(DNFPredicate predicate, Tuple parameters) { 155 public Optional<TupleLike> oneResult(DNF predicate, Tuple parameters) {
156 validateParameters(predicate, parameters); 156 validateParameters(predicate, parameters);
157 return getMatcher(predicate).oneResult(parameters); 157 return getMatcher(predicate).oneResult(parameters);
158 } 158 }
159 159
160 @Override 160 @Override
161 public Stream<TupleLike> allResults(DNFPredicate predicate) { 161 public Stream<TupleLike> allResults(DNF predicate) {
162 return getMatcher(predicate).allResults(); 162 return getMatcher(predicate).allResults();
163 } 163 }
164 164
165 @Override 165 @Override
166 public Stream<TupleLike> allResults(DNFPredicate predicate, Tuple parameters) { 166 public Stream<TupleLike> allResults(DNF predicate, Tuple parameters) {
167 validateParameters(predicate, parameters); 167 validateParameters(predicate, parameters);
168 return getMatcher(predicate).allResults(parameters); 168 return getMatcher(predicate).allResults(parameters);
169 } 169 }
170 170
171 @Override 171 @Override
172 public int countResults(DNFPredicate predicate) { 172 public int countResults(DNF predicate) {
173 return getMatcher(predicate).countResults(); 173 return getMatcher(predicate).countResults();
174 } 174 }
175 175
176 @Override 176 @Override
177 public int countResults(DNFPredicate predicate, Tuple parameters) { 177 public int countResults(DNF predicate, Tuple parameters) {
178 validateParameters(predicate, parameters); 178 validateParameters(predicate, parameters);
179 return getMatcher(predicate).countResults(parameters); 179 return getMatcher(predicate).countResults(parameters);
180 180
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/DNF2PQuery.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/DNF2PQuery.java
index b6468e76..e3c586a0 100644
--- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/DNF2PQuery.java
+++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/DNF2PQuery.java
@@ -11,130 +11,124 @@ import org.eclipse.viatra.query.runtime.matchers.psystem.basicenumerables.Positi
11import org.eclipse.viatra.query.runtime.matchers.psystem.basicenumerables.TypeConstraint; 11import org.eclipse.viatra.query.runtime.matchers.psystem.basicenumerables.TypeConstraint;
12import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PParameter; 12import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PParameter;
13import org.eclipse.viatra.query.runtime.matchers.tuple.Tuples; 13import org.eclipse.viatra.query.runtime.matchers.tuple.Tuples;
14import tools.refinery.store.query.building.*; 14import tools.refinery.store.query.*;
15import tools.refinery.store.query.atom.DNFAtom;
16import tools.refinery.store.query.atom.EquivalenceAtom;
17import tools.refinery.store.query.atom.DNFCallAtom;
18import tools.refinery.store.query.atom.RelationViewAtom;
15import tools.refinery.store.query.view.RelationView; 19import tools.refinery.store.query.view.RelationView;
16 20
17import java.util.*; 21import java.util.*;
18import java.util.stream.Collectors; 22import java.util.stream.Collectors;
19 23
20public class DNF2PQuery { 24public class DNF2PQuery {
21 private final Set<DNFPredicate> translating = new LinkedHashSet<>(); 25 private final Set<DNF> translating = new LinkedHashSet<>();
22 26
23 private final Map<DNFPredicate, SimplePQuery> dnf2PQueryMap = new HashMap<>(); 27 private final Map<DNF, SimplePQuery> dnf2PQueryMap = new HashMap<>();
24 28
25 private final Map<RelationView<?>, RelationViewWrapper> view2WrapperMap = new HashMap<>(); 29 private final Map<RelationView<?>, RelationViewWrapper> view2WrapperMap = new HashMap<>();
26 30
27 public SimplePQuery translate(DNFPredicate predicate) { 31 public SimplePQuery translate(DNF dnfQuery) {
28 if (translating.contains(predicate)) { 32 if (translating.contains(dnfQuery)) {
29 var path = translating.stream().map(DNFPredicate::getName).collect(Collectors.joining(" -> ")); 33 var path = translating.stream().map(DNF::getName).collect(Collectors.joining(" -> "));
30 throw new IllegalStateException("Circular reference %s -> %s detected".formatted(path, 34 throw new IllegalStateException("Circular reference %s -> %s detected".formatted(path,
31 predicate.getName())); 35 dnfQuery.getName()));
32 } 36 }
33 // We can't use computeIfAbsent here, because translating referenced queries calls this method in a reentrant 37 // We can't use computeIfAbsent here, because translating referenced queries calls this method in a reentrant
34 // way, which would cause a ConcurrentModificationException with computeIfAbsent. 38 // way, which would cause a ConcurrentModificationException with computeIfAbsent.
35 var pQuery = dnf2PQueryMap.get(predicate); 39 var pQuery = dnf2PQueryMap.get(dnfQuery);
36 if (pQuery == null) { 40 if (pQuery == null) {
37 translating.add(predicate); 41 translating.add(dnfQuery);
38 try { 42 try {
39 pQuery = doTranslate(predicate); 43 pQuery = doTranslate(dnfQuery);
40 dnf2PQueryMap.put(predicate, pQuery); 44 dnf2PQueryMap.put(dnfQuery, pQuery);
41 } finally { 45 } finally {
42 translating.remove(predicate); 46 translating.remove(dnfQuery);
43 } 47 }
44 } 48 }
45 return pQuery; 49 return pQuery;
46 } 50 }
47 51
48 private SimplePQuery doTranslate(DNFPredicate predicate) { 52 private SimplePQuery doTranslate(DNF dnfQuery) {
49 var query = new SimplePQuery(predicate.getName()); 53 var pQuery = new SimplePQuery(dnfQuery.getUniqueName());
50 54
51 Map<Variable, PParameter> parameters = new HashMap<>(); 55 Map<Variable, PParameter> parameters = new HashMap<>();
52 for (Variable variable : predicate.getVariables()) { 56 for (Variable variable : dnfQuery.getParameters()) {
53 parameters.put(variable, new PParameter(variable.getName())); 57 parameters.put(variable, new PParameter(variable.getUniqueName()));
54 } 58 }
55 59
56 List<PParameter> parameterList = new ArrayList<>(); 60 List<PParameter> parameterList = new ArrayList<>();
57 for (var param : predicate.getVariables()) { 61 for (var param : dnfQuery.getParameters()) {
58 parameterList.add(parameters.get(param)); 62 parameterList.add(parameters.get(param));
59 } 63 }
60 query.setParameters(parameterList); 64 pQuery.setParameters(parameterList);
61 65
62 for (DNFAnd clause : predicate.getClauses()) { 66 for (DNFAnd clause : dnfQuery.getClauses()) {
63 PBody body = new PBody(query); 67 PBody body = new PBody(pQuery);
64 List<ExportedParameter> symbolicParameters = new ArrayList<>(); 68 List<ExportedParameter> symbolicParameters = new ArrayList<>();
65 for (var param : predicate.getVariables()) { 69 for (var param : dnfQuery.getParameters()) {
66 PVariable pVar = body.getOrCreateVariableByName(param.getName()); 70 PVariable pVar = body.getOrCreateVariableByName(param.getUniqueName());
67 symbolicParameters.add(new ExportedParameter(body, pVar, parameters.get(param))); 71 symbolicParameters.add(new ExportedParameter(body, pVar, parameters.get(param)));
68 } 72 }
69 body.setSymbolicParameters(symbolicParameters); 73 body.setSymbolicParameters(symbolicParameters);
70 query.addBody(body); 74 pQuery.addBody(body);
71 for (DNFAtom constraint : clause.getConstraints()) { 75 for (DNFAtom constraint : clause.constraints()) {
72 translateDNFAtom(constraint, body); 76 translateDNFAtom(constraint, body);
73 } 77 }
74 } 78 }
75 79
76 return query; 80 return pQuery;
77 } 81 }
78 82
79 private void translateDNFAtom(DNFAtom constraint, PBody body) { 83 private void translateDNFAtom(DNFAtom constraint, PBody body) {
80 if (constraint instanceof EquivalenceAtom equivalence) { 84 if (constraint instanceof EquivalenceAtom equivalenceAtom) {
81 translateEquivalenceAtom(equivalence, body); 85 translateEquivalenceAtom(equivalenceAtom, body);
82 } 86 } else if (constraint instanceof RelationViewAtom relationViewAtom) {
83 if (constraint instanceof RelationAtom relation) { 87 translateRelationViewAtom(relationViewAtom, body);
84 translateRelationAtom(relation, body); 88 } else if (constraint instanceof DNFCallAtom dnfCallAtom) {
85 } 89 translateDNFCallAtom(dnfCallAtom, body);
86 if (constraint instanceof PredicateAtom predicate) { 90 } else {
87 translatePredicateAtom(predicate, body); 91 throw new IllegalArgumentException("Unknown constraint: " + constraint.toString());
88 } 92 }
89 } 93 }
90 94
91 private void translateEquivalenceAtom(EquivalenceAtom equivalence, PBody body) { 95 private void translateEquivalenceAtom(EquivalenceAtom equivalence, PBody body) {
92 PVariable varSource = body.getOrCreateVariableByName(equivalence.getLeft().getName()); 96 PVariable varSource = body.getOrCreateVariableByName(equivalence.left().getUniqueName());
93 PVariable varTarget = body.getOrCreateVariableByName(equivalence.getRight().getName()); 97 PVariable varTarget = body.getOrCreateVariableByName(equivalence.right().getUniqueName());
94 if (equivalence.isPositive()) 98 if (equivalence.positive()) {
95 new Equality(body, varSource, varTarget); 99 new Equality(body, varSource, varTarget);
96 else 100 } else {
97 new Inequality(body, varSource, varTarget); 101 new Inequality(body, varSource, varTarget);
102 }
98 } 103 }
99 104
100 private void translateRelationAtom(RelationAtom relation, PBody body) { 105 private void translateRelationViewAtom(RelationViewAtom relationViewAtom, PBody body) {
101 if (relation.substitution().size() != relation.view().getArity()) { 106 int arity = relationViewAtom.getSubstitution().size();
102 throw new IllegalArgumentException("Arity (%d) does not match parameter numbers (%d)".formatted( 107 Object[] variables = new Object[arity];
103 relation.view().getArity(), relation.substitution().size())); 108 for (int i = 0; i < arity; i++) {
104 } 109 var variable = relationViewAtom.getSubstitution().get(i);
105 Object[] variables = new Object[relation.substitution().size()]; 110 variables[i] = body.getOrCreateVariableByName(variable.getUniqueName());
106 for (int i = 0; i < relation.substitution().size(); i++) {
107 variables[i] = body.getOrCreateVariableByName(relation.substitution().get(i).getName());
108 } 111 }
109 new TypeConstraint(body, Tuples.flatTupleOf(variables), wrapView(relation.view())); 112 new TypeConstraint(body, Tuples.flatTupleOf(variables), wrapView(relationViewAtom.getTarget()));
110 } 113 }
111 114
112 private RelationViewWrapper wrapView(RelationView<?> relationView) { 115 private RelationViewWrapper wrapView(RelationView<?> relationView) {
113 return view2WrapperMap.computeIfAbsent(relationView, RelationViewWrapper::new); 116 return view2WrapperMap.computeIfAbsent(relationView, RelationViewWrapper::new);
114 } 117 }
115 118
116 private void translatePredicateAtom(PredicateAtom predicate, PBody body) { 119 private void translateDNFCallAtom(DNFCallAtom queryCallAtom, PBody body) {
117 Object[] variables = new Object[predicate.getSubstitution().size()]; 120 int arity = queryCallAtom.getSubstitution().size();
118 for (int i = 0; i < predicate.getSubstitution().size(); i++) { 121 Object[] variables = new Object[arity];
119 variables[i] = body.getOrCreateVariableByName(predicate.getSubstitution().get(i).getName()); 122 for (int i = 0; i < arity; i++) {
123 var variable = queryCallAtom.getSubstitution().get(i);
124 variables[i] = body.getOrCreateVariableByName(variable.getUniqueName());
120 } 125 }
121 var variablesTuple = Tuples.flatTupleOf(variables); 126 var variablesTuple = Tuples.flatTupleOf(variables);
122 var translatedReferred = translate(predicate.getReferred()); 127 var translatedReferred = translate(queryCallAtom.getTarget());
123 if (predicate.isPositive()) { 128 switch (queryCallAtom.getKind()) {
124 if (predicate.isTransitive()) { 129 case POSITIVE -> new PositivePatternCall(body, variablesTuple, translatedReferred);
125 if (predicate.getSubstitution().size() != 2) { 130 case TRANSITIVE -> new BinaryTransitiveClosure(body, variablesTuple, translatedReferred);
126 throw new IllegalArgumentException("Transitive Predicate Atoms must be binary."); 131 case NEGATIVE -> new NegativePatternCall(body, variablesTuple, translatedReferred);
127 }
128 new BinaryTransitiveClosure(body, variablesTuple, translatedReferred);
129 } else {
130 new PositivePatternCall(body, variablesTuple, translatedReferred);
131 }
132 } else {
133 if (predicate.isTransitive()) {
134 throw new IllegalArgumentException("Transitive Predicate Atoms cannot be negative.");
135 } else {
136 new NegativePatternCall(body, variablesTuple, translatedReferred);
137 }
138 } 132 }
139 } 133 }
140} 134}
diff --git a/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/tests/QueryTest.java b/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/tests/QueryTest.java
index d6213b02..8984cb2c 100644
--- a/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/tests/QueryTest.java
+++ b/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/tests/QueryTest.java
@@ -3,9 +3,11 @@ package tools.refinery.store.query.viatra.tests;
3import org.junit.jupiter.api.Test; 3import org.junit.jupiter.api.Test;
4import tools.refinery.store.model.representation.Relation; 4import tools.refinery.store.model.representation.Relation;
5import tools.refinery.store.model.representation.TruthValue; 5import tools.refinery.store.model.representation.TruthValue;
6import tools.refinery.store.query.QueryableModel; 6import tools.refinery.store.query.*;
7import tools.refinery.store.query.QueryableModelStore; 7import tools.refinery.store.query.atom.CallKind;
8import tools.refinery.store.query.building.*; 8import tools.refinery.store.query.atom.EquivalenceAtom;
9import tools.refinery.store.query.atom.DNFCallAtom;
10import tools.refinery.store.query.atom.RelationViewAtom;
9import tools.refinery.store.query.viatra.ViatraQueryableModelStore; 11import tools.refinery.store.query.viatra.ViatraQueryableModelStore;
10import tools.refinery.store.query.view.FilteredRelationView; 12import tools.refinery.store.query.view.FilteredRelationView;
11import tools.refinery.store.query.view.KeyOnlyRelationView; 13import tools.refinery.store.query.view.KeyOnlyRelationView;
@@ -25,10 +27,11 @@ class QueryTest {
25 Relation<Boolean> asset = new Relation<>("Asset", 1, false); 27 Relation<Boolean> asset = new Relation<>("Asset", 1, false);
26 RelationView<Boolean> personView = new KeyOnlyRelationView(person); 28 RelationView<Boolean> personView = new KeyOnlyRelationView(person);
27 29
28 List<Variable> parameters = List.of(new Variable("p1")); 30 var p1 = new Variable("p1");
29 RelationAtom personRelationAtom = new RelationAtom(personView, parameters); 31 DNF predicate = DNF.builder("TypeConstraint")
30 DNFAnd clause = new DNFAnd(Collections.emptySet(), List.of(personRelationAtom)); 32 .parameters(p1)
31 DNFPredicate predicate = new DNFPredicate("TypeConstraint", parameters, List.of(clause)); 33 .clause(new RelationViewAtom(personView, p1))
34 .build();
32 35
33 QueryableModelStore store = new ViatraQueryableModelStore(Set.of(person, asset), Set.of(personView), 36 QueryableModelStore store = new ViatraQueryableModelStore(Set.of(person, asset), Set.of(personView),
34 Set.of(predicate)); 37 Set.of(predicate));
@@ -54,14 +57,14 @@ class QueryTest {
54 57
55 Variable p1 = new Variable("p1"); 58 Variable p1 = new Variable("p1");
56 Variable p2 = new Variable("p2"); 59 Variable p2 = new Variable("p2");
57 List<Variable> parameters = Arrays.asList(p1, p2); 60 DNF predicate = DNF.builder("RelationConstraint")
58 61 .parameters(p1, p2)
59 RelationAtom personRelationAtom1 = new RelationAtom(personView, List.of(p1)); 62 .clause(
60 RelationAtom personRelationAtom2 = new RelationAtom(personView, List.of(p2)); 63 new RelationViewAtom(personView, p1),
61 RelationAtom friendRelationAtom = new RelationAtom(friendMustView, Arrays.asList(p1, p2)); 64 new RelationViewAtom(personView, p1),
62 DNFAnd clause = new DNFAnd(Collections.emptySet(), 65 new RelationViewAtom(friendMustView, p1, p2)
63 Arrays.asList(personRelationAtom1, personRelationAtom2, friendRelationAtom)); 66 )
64 DNFPredicate predicate = new DNFPredicate("RelationConstraint", parameters, List.of(clause)); 67 .build();
65 68
66 QueryableModelStore store = new ViatraQueryableModelStore(Set.of(person, friend), 69 QueryableModelStore store = new ViatraQueryableModelStore(Set.of(person, friend),
67 Set.of(personView, friendMustView), Set.of(predicate)); 70 Set.of(personView, friendMustView), Set.of(predicate));
@@ -93,15 +96,15 @@ class QueryTest {
93 96
94 Variable p1 = new Variable("p1"); 97 Variable p1 = new Variable("p1");
95 Variable p2 = new Variable("p2"); 98 Variable p2 = new Variable("p2");
96 List<Variable> parameters = Arrays.asList(p1, p2); 99 DNF predicate = DNF.builder("RelationConstraint")
97 100 .parameters(p1, p2)
98 RelationAtom personRelationAtom1 = new RelationAtom(personView, List.of(p1)); 101 .clause(
99 RelationAtom personRelationAtom2 = new RelationAtom(personView, List.of(p2)); 102 new RelationViewAtom(personView, p1),
100 RelationAtom friendRelationAtom1 = new RelationAtom(friendMustView, Arrays.asList(p1, p2)); 103 new RelationViewAtom(personView, p2),
101 RelationAtom friendRelationAtom2 = new RelationAtom(friendMustView, Arrays.asList(p2, p1)); 104 new RelationViewAtom(friendMustView, p1, p2),
102 DNFAnd clause = new DNFAnd(Collections.emptySet(), 105 new RelationViewAtom(friendMustView, p2, p1)
103 Arrays.asList(personRelationAtom1, personRelationAtom2, friendRelationAtom1, friendRelationAtom2)); 106 )
104 DNFPredicate predicate = new DNFPredicate("RelationConstraint", parameters, List.of(clause)); 107 .build();
105 108
106 QueryableModelStore store = new ViatraQueryableModelStore(Set.of(person, friend), 109 QueryableModelStore store = new ViatraQueryableModelStore(Set.of(person, friend),
107 Set.of(personView, friendMustView), Set.of(predicate)); 110 Set.of(personView, friendMustView), Set.of(predicate));
@@ -141,14 +144,14 @@ class QueryTest {
141 144
142 Variable p1 = new Variable("p1"); 145 Variable p1 = new Variable("p1");
143 Variable p2 = new Variable("p2"); 146 Variable p2 = new Variable("p2");
144 List<Variable> parameters = List.of(p1); 147 DNF predicate = DNF.builder("RelationConstraint")
145 148 .parameters(p1)
146 RelationAtom personRelationAtom1 = new RelationAtom(personView, List.of(p1)); 149 .clause(
147 RelationAtom personRelationAtom2 = new RelationAtom(personView, List.of(p2)); 150 new RelationViewAtom(personView, p1),
148 RelationAtom friendRelationAtom = new RelationAtom(friendMustView, Arrays.asList(p1, p2)); 151 new RelationViewAtom(personView, p2),
149 DNFAnd clause = new DNFAnd(Set.of(p2), 152 new RelationViewAtom(friendMustView, p1, p2)
150 Arrays.asList(personRelationAtom1, personRelationAtom2, friendRelationAtom)); 153 )
151 DNFPredicate predicate = new DNFPredicate("RelationConstraint", parameters, List.of(clause)); 154 .build();
152 155
153 QueryableModelStore store = new ViatraQueryableModelStore(Set.of(person, friend), 156 QueryableModelStore store = new ViatraQueryableModelStore(Set.of(person, friend),
154 Set.of(personView, friendMustView), Set.of(predicate)); 157 Set.of(personView, friendMustView), Set.of(predicate));
@@ -182,24 +185,19 @@ class QueryTest {
182 185
183 Variable p1 = new Variable("p1"); 186 Variable p1 = new Variable("p1");
184 Variable p2 = new Variable("p2"); 187 Variable p2 = new Variable("p2");
185 List<Variable> parameters = Arrays.asList(p1, p2); 188 DNF predicate = DNF.builder("Or")
186 189 .parameters(p1, p2)
187 // Person-Person friendship 190 .clause(
188 RelationAtom personRelationAtom1 = new RelationAtom(personView, List.of(p1)); 191 new RelationViewAtom(personView, p1),
189 RelationAtom personRelationAtom2 = new RelationAtom(personView, List.of(p2)); 192 new RelationViewAtom(personView, p2),
190 RelationAtom friendRelationAtom1 = new RelationAtom(friendMustView, Arrays.asList(p1, p2)); 193 new RelationViewAtom(friendMustView, p1, p2)
191 DNFAnd clause1 = new DNFAnd(Collections.emptySet(), 194 )
192 Arrays.asList(personRelationAtom1, personRelationAtom2, friendRelationAtom1)); 195 .clause(
193 196 new RelationViewAtom(animalView, p1),
194 // Animal-Animal friendship 197 new RelationViewAtom(animalView, p2),
195 RelationAtom animalRelationAtom1 = new RelationAtom(animalView, List.of(p1)); 198 new RelationViewAtom(friendMustView, p1, p2)
196 RelationAtom animalRelationAtom2 = new RelationAtom(animalView, List.of(p2)); 199 )
197 RelationAtom friendRelationAtom2 = new RelationAtom(friendMustView, Arrays.asList(p1, p2)); 200 .build();
198 DNFAnd clause2 = new DNFAnd(Collections.emptySet(),
199 Arrays.asList(animalRelationAtom1, animalRelationAtom2, friendRelationAtom2));
200
201 // No friendship between species
202 DNFPredicate predicate = new DNFPredicate("Or", parameters, Arrays.asList(clause1, clause2));
203 201
204 QueryableModelStore store = new ViatraQueryableModelStore(Set.of(person, animal, friend), 202 QueryableModelStore store = new ViatraQueryableModelStore(Set.of(person, animal, friend),
205 Set.of(personView, animalView, friendMustView), Set.of(predicate)); 203 Set.of(personView, animalView, friendMustView), Set.of(predicate));
@@ -226,14 +224,14 @@ class QueryTest {
226 224
227 Variable p1 = new Variable("p1"); 225 Variable p1 = new Variable("p1");
228 Variable p2 = new Variable("p2"); 226 Variable p2 = new Variable("p2");
229 List<Variable> parameters = Arrays.asList(p1, p2); 227 DNF predicate = DNF.builder("Equality")
230 228 .parameters(p1, p2)
231 RelationAtom personRelationAtom1 = new RelationAtom(personView, List.of(p1)); 229 .clause(
232 RelationAtom personRelationAtom2 = new RelationAtom(personView, List.of(p2)); 230 new RelationViewAtom(personView, p1),
233 EquivalenceAtom equivalenceAtom = new EquivalenceAtom(true, p1, p2); 231 new RelationViewAtom(personView, p2),
234 DNFAnd clause = new DNFAnd(Collections.emptySet(), 232 new EquivalenceAtom(p1, p2)
235 Arrays.asList(personRelationAtom1, personRelationAtom2, equivalenceAtom)); 233 )
236 DNFPredicate predicate = new DNFPredicate("Equality", parameters, List.of(clause)); 234 .build();
237 235
238 QueryableModelStore store = new ViatraQueryableModelStore(Set.of(person), Set.of(personView), Set.of(predicate)); 236 QueryableModelStore store = new ViatraQueryableModelStore(Set.of(person), Set.of(personView), Set.of(predicate));
239 QueryableModel model = store.createModel(); 237 QueryableModel model = store.createModel();
@@ -258,16 +256,16 @@ class QueryTest {
258 Variable p1 = new Variable("p1"); 256 Variable p1 = new Variable("p1");
259 Variable p2 = new Variable("p2"); 257 Variable p2 = new Variable("p2");
260 Variable p3 = new Variable("p3"); 258 Variable p3 = new Variable("p3");
261 List<Variable> parameters = Arrays.asList(p1, p2, p3); 259 DNF predicate = DNF.builder("Inequality")
262 260 .parameters(p1, p2, p3)
263 RelationAtom personRelationAtom1 = new RelationAtom(personView, List.of(p1)); 261 .clause(
264 RelationAtom personRelationAtom2 = new RelationAtom(personView, List.of(p2)); 262 new RelationViewAtom(personView, p1),
265 RelationAtom friendRelationAtom1 = new RelationAtom(friendMustView, Arrays.asList(p1, p3)); 263 new RelationViewAtom(personView, p2),
266 RelationAtom friendRelationAtom2 = new RelationAtom(friendMustView, Arrays.asList(p2, p3)); 264 new RelationViewAtom(friendMustView, p1, p3),
267 EquivalenceAtom inequivalenceAtom = new EquivalenceAtom(false, p1, p2); 265 new RelationViewAtom(friendMustView, p2, p3),
268 DNFAnd clause = new DNFAnd(Collections.emptySet(), Arrays.asList(personRelationAtom1, personRelationAtom2, 266 new EquivalenceAtom(false, p1, p2)
269 friendRelationAtom1, friendRelationAtom2, inequivalenceAtom)); 267 )
270 DNFPredicate predicate = new DNFPredicate("Inequality", parameters, List.of(clause)); 268 .build();
271 269
272 QueryableModelStore store = new ViatraQueryableModelStore(Set.of(person, friend), 270 QueryableModelStore store = new ViatraQueryableModelStore(Set.of(person, friend),
273 Set.of(personView, friendMustView), Set.of(predicate)); 271 Set.of(personView, friendMustView), Set.of(predicate));
@@ -294,24 +292,25 @@ class QueryTest {
294 292
295 Variable p1 = new Variable("p1"); 293 Variable p1 = new Variable("p1");
296 Variable p2 = new Variable("p2"); 294 Variable p2 = new Variable("p2");
297 List<Variable> parameters = Arrays.asList(p1, p2); 295 DNF friendPredicate = DNF.builder("RelationConstraint")
298 296 .parameters(p1, p2)
299 RelationAtom personRelationAtom1 = new RelationAtom(personView, List.of(p1)); 297 .clause(
300 RelationAtom personRelationAtom2 = new RelationAtom(personView, List.of(p2)); 298 new RelationViewAtom(personView, p1),
301 RelationAtom friendRelationAtom = new RelationAtom(friendMustView, Arrays.asList(p1, p2)); 299 new RelationViewAtom(personView, p2),
302 DNFAnd clause = new DNFAnd(Collections.emptySet(), 300 new RelationViewAtom(friendMustView, p1, p2)
303 Arrays.asList(personRelationAtom1, personRelationAtom2, friendRelationAtom)); 301 )
304 DNFPredicate friendPredicate = new DNFPredicate("RelationConstraint", parameters, List.of(clause)); 302 .build();
305 303
306 Variable p3 = new Variable("p3"); 304 Variable p3 = new Variable("p3");
307 Variable p4 = new Variable("p4"); 305 Variable p4 = new Variable("p4");
308 List<Variable> substitution = Arrays.asList(p3, p4); 306 DNF predicate = DNF.builder("PositivePatternCall")
309 RelationAtom personRelationAtom3 = new RelationAtom(personView, List.of(p3)); 307 .parameters(p3, p4)
310 RelationAtom personRelationAtom4 = new RelationAtom(personView, List.of(p4)); 308 .clause(
311 PredicateAtom friendPredicateAtom = new PredicateAtom(true, false, friendPredicate, substitution); 309 new RelationViewAtom(personView, p3),
312 DNFAnd patternCallClause = new DNFAnd(Collections.emptySet(), 310 new RelationViewAtom(personView, p4),
313 Arrays.asList(personRelationAtom3, personRelationAtom4, friendPredicateAtom)); 311 new DNFCallAtom(friendPredicate, p3, p4)
314 DNFPredicate predicate = new DNFPredicate("PatternCall", substitution, List.of(patternCallClause)); 312 )
313 .build();
315 314
316 QueryableModelStore store = new ViatraQueryableModelStore(Set.of(person, friend), 315 QueryableModelStore store = new ViatraQueryableModelStore(Set.of(person, friend),
317 Set.of(personView, friendMustView), Set.of(friendPredicate, predicate)); 316 Set.of(personView, friendMustView), Set.of(friendPredicate, predicate));
@@ -339,25 +338,25 @@ class QueryTest {
339 338
340 Variable p1 = new Variable("p1"); 339 Variable p1 = new Variable("p1");
341 Variable p2 = new Variable("p2"); 340 Variable p2 = new Variable("p2");
342 List<Variable> parameters = Arrays.asList(p1, p2); 341 DNF friendPredicate = DNF.builder("RelationConstraint")
343 342 .parameters(p1, p2)
344 RelationAtom personRelationAtom1 = new RelationAtom(personView, List.of(p1)); 343 .clause(
345 RelationAtom personRelationAtom2 = new RelationAtom(personView, List.of(p2)); 344 new RelationViewAtom(personView, p1),
346 RelationAtom friendRelationAtom = new RelationAtom(friendMustView, Arrays.asList(p1, p2)); 345 new RelationViewAtom(personView, p2),
347 DNFAnd clause = new DNFAnd(Collections.emptySet(), 346 new RelationViewAtom(friendMustView, p1, p2)
348 Arrays.asList(personRelationAtom1, personRelationAtom2, friendRelationAtom)); 347 )
349 DNFPredicate friendPredicate = new DNFPredicate("RelationConstraint", parameters, List.of(clause)); 348 .build();
350 349
351 Variable p3 = new Variable("p3"); 350 Variable p3 = new Variable("p3");
352 Variable p4 = new Variable("p4"); 351 Variable p4 = new Variable("p4");
353 List<Variable> substitution = Arrays.asList(p3, p4); 352 DNF predicate = DNF.builder("NegativePatternCall")
354 RelationAtom personRelationAtom3 = new RelationAtom(personView, List.of(p3)); 353 .parameters(p3, p4)
355 RelationAtom personRelationAtom4 = new RelationAtom(personView, List.of(p4)); 354 .clause(
356 PredicateAtom friendPredicateAtom = new PredicateAtom(false, false, friendPredicate, substitution); 355 new RelationViewAtom(personView, p3),
357 DNFAnd negativePatternCallClause = new DNFAnd(Collections.emptySet(), 356 new RelationViewAtom(personView, p4),
358 Arrays.asList(personRelationAtom3, personRelationAtom4, friendPredicateAtom)); 357 new DNFCallAtom(CallKind.NEGATIVE, friendPredicate, p3, p4)
359 DNFPredicate predicate = new DNFPredicate("NegativePatternCall", substitution, 358 )
360 List.of(negativePatternCallClause)); 359 .build();
361 360
362 QueryableModelStore store = new ViatraQueryableModelStore(Set.of(person, friend), 361 QueryableModelStore store = new ViatraQueryableModelStore(Set.of(person, friend),
363 Set.of(personView, friendMustView), Set.of(friendPredicate, predicate)); 362 Set.of(personView, friendMustView), Set.of(friendPredicate, predicate));
@@ -384,25 +383,25 @@ class QueryTest {
384 383
385 Variable p1 = new Variable("p1"); 384 Variable p1 = new Variable("p1");
386 Variable p2 = new Variable("p2"); 385 Variable p2 = new Variable("p2");
387 List<Variable> parameters = Arrays.asList(p1, p2); 386 DNF friendPredicate = DNF.builder("RelationConstraint")
388 387 .parameters(p1, p2)
389 RelationAtom personRelationAtom1 = new RelationAtom(personView, List.of(p1)); 388 .clause(
390 RelationAtom personRelationAtom2 = new RelationAtom(personView, List.of(p2)); 389 new RelationViewAtom(personView, p1),
391 RelationAtom friendRelationAtom = new RelationAtom(friendMustView, Arrays.asList(p1, p2)); 390 new RelationViewAtom(personView, p2),
392 DNFAnd clause = new DNFAnd(Collections.emptySet(), 391 new RelationViewAtom(friendMustView, p1, p2)
393 Arrays.asList(personRelationAtom1, personRelationAtom2, friendRelationAtom)); 392 )
394 DNFPredicate friendPredicate = new DNFPredicate("RelationConstraint", parameters, List.of(clause)); 393 .build();
395 394
396 Variable p3 = new Variable("p3"); 395 Variable p3 = new Variable("p3");
397 Variable p4 = new Variable("p4"); 396 Variable p4 = new Variable("p4");
398 List<Variable> substitution = Arrays.asList(p3, p4); 397 DNF predicate = DNF.builder("TransitivePatternCall")
399 RelationAtom personRelationAtom3 = new RelationAtom(personView, List.of(p3)); 398 .parameters(p3, p4)
400 RelationAtom personRelationAtom4 = new RelationAtom(personView, List.of(p4)); 399 .clause(
401 PredicateAtom friendPredicateAtom = new PredicateAtom(true, true, friendPredicate, substitution); 400 new RelationViewAtom(personView, p3),
402 DNFAnd patternCallClause = new DNFAnd(Collections.emptySet(), 401 new RelationViewAtom(personView, p4),
403 Arrays.asList(personRelationAtom3, personRelationAtom4, friendPredicateAtom)); 402 new DNFCallAtom(CallKind.TRANSITIVE, friendPredicate, p3, p4)
404 DNFPredicate predicate = new DNFPredicate("TransitivePatternCall", substitution, 403 )
405 List.of(patternCallClause)); 404 .build();
406 405
407 QueryableModelStore store = new ViatraQueryableModelStore(Set.of(person, friend), 406 QueryableModelStore store = new ViatraQueryableModelStore(Set.of(person, friend),
408 Set.of(personView, friendMustView), Set.of(friendPredicate, predicate)); 407 Set.of(personView, friendMustView), Set.of(friendPredicate, predicate));
diff --git a/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/tests/QueryTransactionTest.java b/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/tests/QueryTransactionTest.java
index f57bca2b..a555f024 100644
--- a/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/tests/QueryTransactionTest.java
+++ b/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/tests/QueryTransactionTest.java
@@ -1,20 +1,17 @@
1package tools.refinery.store.query.viatra.tests; 1package tools.refinery.store.query.viatra.tests;
2 2
3import org.junit.jupiter.api.Test; 3import org.junit.jupiter.api.Test;
4import tools.refinery.store.tuple.Tuple;
5import tools.refinery.store.model.representation.Relation; 4import tools.refinery.store.model.representation.Relation;
5import tools.refinery.store.query.DNF;
6import tools.refinery.store.query.QueryableModel; 6import tools.refinery.store.query.QueryableModel;
7import tools.refinery.store.query.QueryableModelStore; 7import tools.refinery.store.query.QueryableModelStore;
8import tools.refinery.store.query.building.DNFAnd; 8import tools.refinery.store.query.Variable;
9import tools.refinery.store.query.building.DNFPredicate; 9import tools.refinery.store.query.atom.RelationViewAtom;
10import tools.refinery.store.query.building.RelationAtom;
11import tools.refinery.store.query.building.Variable;
12import tools.refinery.store.query.viatra.ViatraQueryableModelStore; 10import tools.refinery.store.query.viatra.ViatraQueryableModelStore;
13import tools.refinery.store.query.view.KeyOnlyRelationView; 11import tools.refinery.store.query.view.KeyOnlyRelationView;
14import tools.refinery.store.query.view.RelationView; 12import tools.refinery.store.query.view.RelationView;
13import tools.refinery.store.tuple.Tuple;
15 14
16import java.util.Collections;
17import java.util.List;
18import java.util.Set; 15import java.util.Set;
19 16
20import static org.junit.jupiter.api.Assertions.assertEquals; 17import static org.junit.jupiter.api.Assertions.assertEquals;
@@ -26,10 +23,11 @@ class QueryTransactionTest {
26 Relation<Boolean> asset = new Relation<>("Asset", 1, false); 23 Relation<Boolean> asset = new Relation<>("Asset", 1, false);
27 RelationView<Boolean> personView = new KeyOnlyRelationView(person); 24 RelationView<Boolean> personView = new KeyOnlyRelationView(person);
28 25
29 List<Variable> parameters = List.of(new Variable("p1")); 26 var p1 = new Variable("p1");
30 RelationAtom personRelationAtom = new RelationAtom(personView, parameters); 27 DNF predicate = DNF.builder("TypeConstraint")
31 DNFAnd clause = new DNFAnd(Collections.emptySet(), List.of(personRelationAtom)); 28 .parameters(p1)
32 DNFPredicate predicate = new DNFPredicate("TypeConstraint", parameters, List.of(clause)); 29 .clause(new RelationViewAtom(personView, p1))
30 .build();
33 31
34 QueryableModelStore store = new ViatraQueryableModelStore(Set.of(person, asset), Set.of(personView), 32 QueryableModelStore store = new ViatraQueryableModelStore(Set.of(person, asset), Set.of(personView),
35 Set.of(predicate)); 33 Set.of(predicate));
diff --git a/subprojects/store/src/main/java/tools/refinery/store/model/ModelStoreImpl.java b/subprojects/store/src/main/java/tools/refinery/store/model/ModelStoreImpl.java
index b5e1c453..d08cf0f8 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/model/ModelStoreImpl.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/model/ModelStoreImpl.java
@@ -1,24 +1,15 @@
1package tools.refinery.store.model; 1package tools.refinery.store.model;
2 2
3import java.util.HashMap; 3import tools.refinery.store.map.*;
4import java.util.LinkedList;
5import java.util.List;
6import java.util.Map;
7import java.util.Map.Entry;
8
9import tools.refinery.store.map.ContinousHashProvider;
10import tools.refinery.store.map.DiffCursor;
11import tools.refinery.store.map.VersionedMap;
12import tools.refinery.store.map.VersionedMapStore;
13import tools.refinery.store.map.VersionedMapStoreImpl;
14import tools.refinery.store.model.internal.ModelImpl; 4import tools.refinery.store.model.internal.ModelImpl;
15import tools.refinery.store.model.internal.SimilarRelationEquivalenceClass; 5import tools.refinery.store.model.internal.SimilarRelationEquivalenceClass;
16import tools.refinery.store.model.representation.AuxilaryData; 6import tools.refinery.store.model.representation.AuxiliaryData;
17import tools.refinery.store.model.representation.DataRepresentation; 7import tools.refinery.store.model.representation.DataRepresentation;
18import tools.refinery.store.model.representation.Relation; 8import tools.refinery.store.model.representation.Relation;
19import tools.refinery.store.tuple.Tuple; 9import tools.refinery.store.tuple.Tuple;
20 10
21import java.util.Set; 11import java.util.*;
12import java.util.Map.Entry;
22 13
23public class ModelStoreImpl implements ModelStore { 14public class ModelStoreImpl implements ModelStore {
24 15
@@ -38,7 +29,7 @@ public class ModelStoreImpl implements ModelStore {
38 if (dataRepresentation instanceof Relation<?> symbolRepresentation) { 29 if (dataRepresentation instanceof Relation<?> symbolRepresentation) {
39 addOrCreate(symbolRepresentationsPerHashPerArity, 30 addOrCreate(symbolRepresentationsPerHashPerArity,
40 new SimilarRelationEquivalenceClass(symbolRepresentation), symbolRepresentation); 31 new SimilarRelationEquivalenceClass(symbolRepresentation), symbolRepresentation);
41 } else if (dataRepresentation instanceof AuxilaryData<?, ?>) { 32 } else if (dataRepresentation instanceof AuxiliaryData<?, ?>) {
42 VersionedMapStoreImpl<?, ?> store = new VersionedMapStoreImpl<>(dataRepresentation.getHashProvider(), 33 VersionedMapStoreImpl<?, ?> store = new VersionedMapStoreImpl<>(dataRepresentation.getHashProvider(),
43 dataRepresentation.getDefaultValue()); 34 dataRepresentation.getDefaultValue());
44 result.put(dataRepresentation, store); 35 result.put(dataRepresentation, store);
diff --git a/subprojects/store/src/main/java/tools/refinery/store/model/RelationLike.java b/subprojects/store/src/main/java/tools/refinery/store/model/RelationLike.java
new file mode 100644
index 00000000..6a5fdcd5
--- /dev/null
+++ b/subprojects/store/src/main/java/tools/refinery/store/model/RelationLike.java
@@ -0,0 +1,7 @@
1package tools.refinery.store.model;
2
3public interface RelationLike {
4 String getName();
5
6 int getArity();
7}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/model/representation/AuxilaryData.java b/subprojects/store/src/main/java/tools/refinery/store/model/representation/AuxilaryData.java
deleted file mode 100644
index ddd8a5f2..00000000
--- a/subprojects/store/src/main/java/tools/refinery/store/model/representation/AuxilaryData.java
+++ /dev/null
@@ -1,22 +0,0 @@
1package tools.refinery.store.model.representation;
2
3import tools.refinery.store.map.ContinousHashProvider;
4
5public class AuxilaryData<K,V> extends DataRepresentation<K, V> {
6 private final String name;
7
8 public AuxilaryData(String name, ContinousHashProvider<K> hashProvider, V defaultValue) {
9 super(hashProvider, defaultValue);
10 this.name = name;
11 }
12
13 @Override
14 public String getName() {
15 return name;
16 }
17
18 @Override
19 public boolean isValidKey(K key) {
20 return true;
21 }
22}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/model/representation/AuxiliaryData.java b/subprojects/store/src/main/java/tools/refinery/store/model/representation/AuxiliaryData.java
new file mode 100644
index 00000000..1a968f50
--- /dev/null
+++ b/subprojects/store/src/main/java/tools/refinery/store/model/representation/AuxiliaryData.java
@@ -0,0 +1,22 @@
1package tools.refinery.store.model.representation;
2
3import tools.refinery.store.map.ContinousHashProvider;
4
5public final class AuxiliaryData<K, V> extends DataRepresentation<K, V> {
6 private final ContinousHashProvider<K> hashProvider;
7
8 public AuxiliaryData(String name, ContinousHashProvider<K> hashProvider, V defaultValue) {
9 super(name, defaultValue);
10 this.hashProvider = hashProvider;
11 }
12
13 @Override
14 public ContinousHashProvider<K> getHashProvider() {
15 return hashProvider;
16 }
17
18 @Override
19 public boolean isValidKey(K key) {
20 return true;
21 }
22}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/model/representation/DataRepresentation.java b/subprojects/store/src/main/java/tools/refinery/store/model/representation/DataRepresentation.java
index 585e7b88..49f74717 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/model/representation/DataRepresentation.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/model/representation/DataRepresentation.java
@@ -2,20 +2,22 @@ package tools.refinery.store.model.representation;
2 2
3import tools.refinery.store.map.ContinousHashProvider; 3import tools.refinery.store.map.ContinousHashProvider;
4 4
5public abstract class DataRepresentation<K, V> { 5public abstract sealed class DataRepresentation<K, V> permits Relation, AuxiliaryData {
6 protected final ContinousHashProvider<K> hashProvider; 6 private final String name;
7 protected final V defaultValue;
8 7
9 protected DataRepresentation(ContinousHashProvider<K> hashProvider, V defaultValue) { 8 private final V defaultValue;
10 this.hashProvider = hashProvider; 9
10 protected DataRepresentation(String name, V defaultValue) {
11 this.name = name;
11 this.defaultValue = defaultValue; 12 this.defaultValue = defaultValue;
12 } 13 }
13 14
14 public abstract String getName(); 15 public String getName() {
15 16 return name;
16 public ContinousHashProvider<K> getHashProvider() {
17 return hashProvider;
18 } 17 }
18
19 public abstract ContinousHashProvider<K> getHashProvider();
20
19 public abstract boolean isValidKey(K key); 21 public abstract boolean isValidKey(K key);
20 22
21 public V getDefaultValue() { 23 public V getDefaultValue() {
diff --git a/subprojects/store/src/main/java/tools/refinery/store/model/representation/Relation.java b/subprojects/store/src/main/java/tools/refinery/store/model/representation/Relation.java
index c0f31d08..2e21ea37 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/model/representation/Relation.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/model/representation/Relation.java
@@ -1,31 +1,34 @@
1package tools.refinery.store.model.representation; 1package tools.refinery.store.model.representation;
2 2
3import tools.refinery.store.map.ContinousHashProvider;
4import tools.refinery.store.model.RelationLike;
3import tools.refinery.store.tuple.Tuple; 5import tools.refinery.store.tuple.Tuple;
4import tools.refinery.store.model.TupleHashProvider; 6import tools.refinery.store.model.TupleHashProvider;
5 7
6public class Relation<D> extends DataRepresentation<Tuple, D> { 8public final class Relation<D> extends DataRepresentation<Tuple, D> implements RelationLike {
7 private final String name;
8 private final int arity; 9 private final int arity;
9 10
10 public Relation(String name, int arity, D defaultValue) { 11 public Relation(String name, int arity, D defaultValue) {
11 super(TupleHashProvider.singleton(), defaultValue); 12 super(name, defaultValue);
12 this.name = name;
13 this.arity = arity; 13 this.arity = arity;
14 } 14 }
15 15
16 @Override 16 @Override
17 public String getName() {
18 return name;
19 }
20
21 public int getArity() { 17 public int getArity() {
22 return arity; 18 return arity;
23 } 19 }
24 20
25 @Override 21 @Override
22 public ContinousHashProvider<Tuple> getHashProvider() {
23 return TupleHashProvider.singleton();
24 }
25
26 @Override
26 public boolean isValidKey(Tuple key) { 27 public boolean isValidKey(Tuple key) {
27 if(key == null) { 28 if (key == null) {
28 return false; 29 return false;
29 } else return key.getSize() == getArity(); 30 } else {
31 return key.getSize() == getArity();
32 }
30 } 33 }
31} 34}
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
new file mode 100644
index 00000000..7d4b3091
--- /dev/null
+++ b/subprojects/store/src/main/java/tools/refinery/store/query/DNF.java
@@ -0,0 +1,121 @@
1package tools.refinery.store.query;
2
3import tools.refinery.store.model.RelationLike;
4import tools.refinery.store.query.atom.DNFAtom;
5
6import java.util.*;
7
8public class DNF implements RelationLike {
9 private final String name;
10
11 private final String uniqueName;
12
13 private final List<Variable> parameters;
14
15 private final List<DNFAnd> clauses;
16
17 private DNF(String name, List<Variable> parameters, List<DNFAnd> clauses) {
18 this.name = name;
19 this.uniqueName = DNFUtils.generateUniqueName(name);
20 this.parameters = parameters;
21 this.clauses = clauses;
22 }
23
24 @Override
25 public String getName() {
26 return name;
27 }
28
29 public String getUniqueName() {
30 return uniqueName;
31 }
32
33 public List<Variable> getParameters() {
34 return parameters;
35 }
36
37 @Override
38 public int getArity() {
39 return parameters.size();
40 }
41
42 public List<DNFAnd> getClauses() {
43 return clauses;
44 }
45
46 public static Builder builder() {
47 return builder(null);
48 }
49
50 public static Builder builder(String name) {
51 return new Builder(name);
52 }
53
54 @SuppressWarnings("UnusedReturnValue")
55 public static class Builder {
56 private final String name;
57
58 private final List<Variable> parameters = new ArrayList<>();
59
60 private final List<List<DNFAtom>> clauses = new ArrayList<>();
61
62 private Builder(String name) {
63 this.name = name;
64 }
65
66 public Builder parameter(Variable variable) {
67 this.parameters.add(variable);
68 return this;
69 }
70
71 public Builder parameters(Variable... variables) {
72 return parameters(List.of(variables));
73 }
74
75 public Builder parameters(Collection<Variable> variables) {
76 this.parameters.addAll(variables);
77 return this;
78 }
79
80 public Builder clause(DNFAtom... atoms) {
81 clauses.add(List.of(atoms));
82 return this;
83 }
84
85 public Builder clause(Collection<DNFAtom> atoms) {
86 clauses.add(List.copyOf(atoms));
87 return this;
88 }
89
90 public Builder clause(DNFAnd clause) {
91 return clause(clause.constraints());
92 }
93
94 public Builder clauses(DNFAnd... clauses) {
95 for (var clause : clauses) {
96 this.clause(clause);
97 }
98 return this;
99 }
100
101 public Builder clauses(Collection<DNFAnd> clauses) {
102 for (var clause : clauses) {
103 this.clause(clause);
104 }
105 return this;
106 }
107
108 public DNF build() {
109 var postProcessedClauses = new ArrayList<DNFAnd>();
110 for (var constraints : clauses) {
111 var variables = new HashSet<Variable>();
112 for (var constraint : constraints) {
113 constraint.collectAllVariables(variables);
114 }
115 parameters.forEach(variables::remove);
116 postProcessedClauses.add(new DNFAnd(variables, constraints));
117 }
118 return new DNF(name, List.copyOf(parameters), postProcessedClauses);
119 }
120 }
121}
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
new file mode 100644
index 00000000..8c3bf05d
--- /dev/null
+++ b/subprojects/store/src/main/java/tools/refinery/store/query/DNFAnd.java
@@ -0,0 +1,9 @@
1package tools.refinery.store.query;
2
3import tools.refinery.store.query.atom.DNFAtom;
4
5import java.util.List;
6import java.util.Set;
7
8public 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
new file mode 100644
index 00000000..0ef77d49
--- /dev/null
+++ b/subprojects/store/src/main/java/tools/refinery/store/query/DNFUtils.java
@@ -0,0 +1,19 @@
1package tools.refinery.store.query;
2
3import java.util.UUID;
4
5public 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/QueryableModel.java b/subprojects/store/src/main/java/tools/refinery/store/query/QueryableModel.java
index 648c3a36..9655d1a1 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/query/QueryableModel.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/query/QueryableModel.java
@@ -1,7 +1,6 @@
1package tools.refinery.store.query; 1package tools.refinery.store.query;
2 2
3import tools.refinery.store.model.Model; 3import tools.refinery.store.model.Model;
4import tools.refinery.store.query.building.DNFPredicate;
5import tools.refinery.store.tuple.Tuple; 4import tools.refinery.store.tuple.Tuple;
6import tools.refinery.store.tuple.TupleLike; 5import tools.refinery.store.tuple.TupleLike;
7 6
@@ -10,25 +9,25 @@ import java.util.Set;
10import java.util.stream.Stream; 9import java.util.stream.Stream;
11 10
12public interface QueryableModel extends Model { 11public interface QueryableModel extends Model {
13 Set<DNFPredicate> getPredicates(); 12 Set<DNF> getPredicates();
14 13
15 boolean hasChanges(); 14 boolean hasChanges();
16 15
17 void flushChanges(); 16 void flushChanges();
18 17
19 boolean hasResult(DNFPredicate predicate); 18 boolean hasResult(DNF predicate);
20 19
21 boolean hasResult(DNFPredicate predicate, Tuple parameters); 20 boolean hasResult(DNF predicate, Tuple parameters);
22 21
23 Optional<TupleLike> oneResult(DNFPredicate predicate); 22 Optional<TupleLike> oneResult(DNF predicate);
24 23
25 Optional<TupleLike> oneResult(DNFPredicate predicate, Tuple parameters); 24 Optional<TupleLike> oneResult(DNF predicate, Tuple parameters);
26 25
27 Stream<TupleLike> allResults(DNFPredicate predicate); 26 Stream<TupleLike> allResults(DNF predicate);
28 27
29 Stream<TupleLike> allResults(DNFPredicate predicate, Tuple parameters); 28 Stream<TupleLike> allResults(DNF predicate, Tuple parameters);
30 29
31 int countResults(DNFPredicate predicate); 30 int countResults(DNF predicate);
32 31
33 int countResults(DNFPredicate predicate, Tuple parameters); 32 int countResults(DNF predicate, Tuple parameters);
34} 33}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/QueryableModelStore.java b/subprojects/store/src/main/java/tools/refinery/store/query/QueryableModelStore.java
index 878e1058..41f47e64 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/query/QueryableModelStore.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/query/QueryableModelStore.java
@@ -2,7 +2,6 @@ package tools.refinery.store.query;
2 2
3import tools.refinery.store.model.ModelStore; 3import tools.refinery.store.model.ModelStore;
4import tools.refinery.store.model.representation.DataRepresentation; 4import tools.refinery.store.model.representation.DataRepresentation;
5import tools.refinery.store.query.building.DNFPredicate;
6import tools.refinery.store.query.view.RelationView; 5import tools.refinery.store.query.view.RelationView;
7 6
8import java.util.Set; 7import java.util.Set;
@@ -14,7 +13,7 @@ public interface QueryableModelStore extends ModelStore {
14 @SuppressWarnings("squid:S1452") 13 @SuppressWarnings("squid:S1452")
15 Set<RelationView<?>> getViews(); 14 Set<RelationView<?>> getViews();
16 15
17 Set<DNFPredicate> getPredicates(); 16 Set<DNF> getPredicates();
18 17
19 QueryableModel createModel(); 18 QueryableModel createModel();
20 19
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
new file mode 100644
index 00000000..3632f3c5
--- /dev/null
+++ b/subprojects/store/src/main/java/tools/refinery/store/query/Variable.java
@@ -0,0 +1,43 @@
1package tools.refinery.store.query;
2
3import java.util.Objects;
4
5public 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/AbstractCallAtom.java b/subprojects/store/src/main/java/tools/refinery/store/query/atom/AbstractCallAtom.java
new file mode 100644
index 00000000..fb8d7432
--- /dev/null
+++ b/subprojects/store/src/main/java/tools/refinery/store/query/atom/AbstractCallAtom.java
@@ -0,0 +1,30 @@
1package tools.refinery.store.query.atom;
2
3import tools.refinery.store.model.RelationLike;
4import tools.refinery.store.query.Variable;
5
6import java.util.List;
7import java.util.Set;
8
9public abstract class AbstractCallAtom<T extends RelationLike> extends AbstractSubstitutionAtom<T> {
10 private final CallKind kind;
11
12 protected AbstractCallAtom(CallKind kind, T target, List<Variable> substitution) {
13 super(target, substitution);
14 if (kind.isTransitive() && target.getArity() != 2) {
15 throw new IllegalArgumentException("Transitive closures can only take binary relations");
16 }
17 this.kind = kind;
18 }
19
20 public CallKind getKind() {
21 return kind;
22 }
23
24 @Override
25 public void collectAllVariables(Set<Variable> variables) {
26 if (kind.isPositive()) {
27 super.collectAllVariables(variables);
28 }
29 }
30}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/atom/AbstractSubstitutionAtom.java b/subprojects/store/src/main/java/tools/refinery/store/query/atom/AbstractSubstitutionAtom.java
new file mode 100644
index 00000000..e8a8b5e1
--- /dev/null
+++ b/subprojects/store/src/main/java/tools/refinery/store/query/atom/AbstractSubstitutionAtom.java
@@ -0,0 +1,35 @@
1package tools.refinery.store.query.atom;
2
3import tools.refinery.store.model.RelationLike;
4import tools.refinery.store.query.Variable;
5
6import java.util.List;
7import java.util.Set;
8
9public abstract class AbstractSubstitutionAtom<T extends RelationLike> implements DNFAtom {
10 private final T target;
11
12 private final List<Variable> substitution;
13
14 protected AbstractSubstitutionAtom(T target, List<Variable> substitution) {
15 if (substitution.size() != target.getArity()) {
16 throw new IllegalArgumentException("%s needs %d arguments, but got %s".formatted(target.getName(),
17 target.getArity(), substitution.size()));
18 }
19 this.target = target;
20 this.substitution = substitution;
21 }
22
23 public T getTarget() {
24 return target;
25 }
26
27 public List<Variable> getSubstitution() {
28 return substitution;
29 }
30
31 @Override
32 public void collectAllVariables(Set<Variable> variables) {
33 variables.addAll(substitution);
34 }
35}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/atom/CallKind.java b/subprojects/store/src/main/java/tools/refinery/store/query/atom/CallKind.java
new file mode 100644
index 00000000..c7cbc955
--- /dev/null
+++ b/subprojects/store/src/main/java/tools/refinery/store/query/atom/CallKind.java
@@ -0,0 +1,24 @@
1package tools.refinery.store.query.atom;
2
3public enum CallKind {
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 CallKind(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}
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
new file mode 100644
index 00000000..ebf71236
--- /dev/null
+++ b/subprojects/store/src/main/java/tools/refinery/store/query/atom/DNFAtom.java
@@ -0,0 +1,9 @@
1package tools.refinery.store.query.atom;
2
3import tools.refinery.store.query.Variable;
4
5import java.util.Set;
6
7public 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
new file mode 100644
index 00000000..9d2efa53
--- /dev/null
+++ b/subprojects/store/src/main/java/tools/refinery/store/query/atom/DNFCallAtom.java
@@ -0,0 +1,40 @@
1package tools.refinery.store.query.atom;
2
3import tools.refinery.store.query.DNF;
4import tools.refinery.store.query.Variable;
5
6import java.util.List;
7import java.util.Objects;
8
9public final class DNFCallAtom extends AbstractCallAtom<DNF> {
10 public DNFCallAtom(CallKind kind, DNF target, List<Variable> substitution) {
11 super(kind, target, substitution);
12 }
13
14 public DNFCallAtom(CallKind kind, DNF target, Variable... substitution) {
15 super(kind, target, List.of(substitution));
16 }
17
18 public DNFCallAtom(DNF target, List<Variable> substitution) {
19 this(CallKind.POSITIVE, target, substitution);
20 }
21
22 public DNFCallAtom(DNF target, Variable... substitution) {
23 this(target, List.of(substitution));
24 }
25
26 @Override
27 public boolean equals(Object o) {
28 if (this == o) return true;
29 if (o == null || getClass() != o.getClass()) return false;
30 DNFCallAtom dnfCallAtom = (DNFCallAtom) o;
31 return Objects.equals(getKind(), dnfCallAtom.getKind())
32 && Objects.equals(getTarget(), dnfCallAtom.getTarget())
33 && Objects.equals(getSubstitution(), dnfCallAtom.getSubstitution());
34 }
35
36 @Override
37 public int hashCode() {
38 return Objects.hash(getKind(), getTarget(), getSubstitution());
39 }
40}
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
new file mode 100644
index 00000000..b1b3a6f7
--- /dev/null
+++ b/subprojects/store/src/main/java/tools/refinery/store/query/atom/EquivalenceAtom.java
@@ -0,0 +1,17 @@
1package tools.refinery.store.query.atom;
2
3import tools.refinery.store.query.Variable;
4
5import java.util.Set;
6
7public 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/ModalRelationAtom.java b/subprojects/store/src/main/java/tools/refinery/store/query/atom/ModalRelationAtom.java
new file mode 100644
index 00000000..2480e82e
--- /dev/null
+++ b/subprojects/store/src/main/java/tools/refinery/store/query/atom/ModalRelationAtom.java
@@ -0,0 +1,38 @@
1package tools.refinery.store.query.atom;
2
3import tools.refinery.store.model.representation.Relation;
4import tools.refinery.store.model.representation.TruthValue;
5import tools.refinery.store.query.Variable;
6
7import java.util.List;
8import java.util.Objects;
9
10public final class ModalRelationAtom extends AbstractCallAtom<Relation<TruthValue>> {
11 private final Modality modality;
12
13 public ModalRelationAtom(CallKind kind, Modality modality, Relation<TruthValue> target,
14 List<Variable> substitution) {
15 super(kind, target, substitution);
16 this.modality = modality;
17 }
18
19 public ModalRelationAtom(Modality modality, Relation<TruthValue> target, List<Variable> substitution) {
20 this(CallKind.POSITIVE, modality, target, substitution);
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 ModalRelationAtom modalRelationAtom = (ModalRelationAtom) o;
28 return Objects.equals(getKind(), modalRelationAtom.getKind())
29 && modality == modalRelationAtom.modality
30 && Objects.equals(getTarget(), modalRelationAtom.getTarget())
31 && Objects.equals(getSubstitution(), modalRelationAtom.getSubstitution());
32 }
33
34 @Override
35 public int hashCode() {
36 return Objects.hash(getKind(), modality, getTarget(), getSubstitution());
37 }
38}
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
new file mode 100644
index 00000000..9344a9d3
--- /dev/null
+++ b/subprojects/store/src/main/java/tools/refinery/store/query/atom/Modality.java
@@ -0,0 +1,7 @@
1package tools.refinery.store.query.atom;
2
3public enum Modality {
4 MUST,
5 MAY,
6 CURRENT;
7}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/atom/RelationAtom.java b/subprojects/store/src/main/java/tools/refinery/store/query/atom/RelationAtom.java
new file mode 100644
index 00000000..06098139
--- /dev/null
+++ b/subprojects/store/src/main/java/tools/refinery/store/query/atom/RelationAtom.java
@@ -0,0 +1,32 @@
1package tools.refinery.store.query.atom;
2
3import tools.refinery.store.model.representation.Relation;
4import tools.refinery.store.query.Variable;
5
6import java.util.List;
7import java.util.Objects;
8
9public final class RelationAtom extends AbstractCallAtom<Relation<?>> {
10 public RelationAtom(CallKind kind, Relation<?> target, List<Variable> substitution) {
11 super(kind, target, substitution);
12 }
13
14 public RelationAtom(Relation<?> target, List<Variable> substitution) {
15 this(CallKind.POSITIVE, target, substitution);
16 }
17
18 @Override
19 public boolean equals(Object o) {
20 if (this == o) return true;
21 if (o == null || getClass() != o.getClass()) return false;
22 RelationAtom relationAtom = (RelationAtom) o;
23 return Objects.equals(getKind(), relationAtom.getKind())
24 && Objects.equals(getTarget(), relationAtom.getTarget())
25 && Objects.equals(getSubstitution(), relationAtom.getSubstitution());
26 }
27
28 @Override
29 public int hashCode() {
30 return Objects.hash(getKind(), getTarget(), getSubstitution());
31 }
32}
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
new file mode 100644
index 00000000..762a41f1
--- /dev/null
+++ b/subprojects/store/src/main/java/tools/refinery/store/query/atom/RelationViewAtom.java
@@ -0,0 +1,31 @@
1package tools.refinery.store.query.atom;
2
3import tools.refinery.store.query.Variable;
4import tools.refinery.store.query.view.RelationView;
5
6import java.util.List;
7import java.util.Objects;
8
9public final class RelationViewAtom extends AbstractSubstitutionAtom<RelationView<?>> {
10 public RelationViewAtom(RelationView<?> target, List<Variable> substitution) {
11 super(target, substitution);
12 }
13
14 public RelationViewAtom(RelationView<?> target, Variable... substitution) {
15 this(target, List.of(substitution));
16 }
17
18 @Override
19 public boolean equals(Object o) {
20 if (this == o) return true;
21 if (o == null || getClass() != o.getClass()) return false;
22 RelationViewAtom relationViewAtom = (RelationViewAtom) o;
23 return Objects.equals(getTarget(), relationViewAtom.getTarget())
24 && Objects.equals(getSubstitution(), relationViewAtom.getSubstitution());
25 }
26
27 @Override
28 public int hashCode() {
29 return Objects.hash(getTarget(), getSubstitution());
30 }
31}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/building/DNFAnd.java b/subprojects/store/src/main/java/tools/refinery/store/query/building/DNFAnd.java
deleted file mode 100644
index 48dabce2..00000000
--- a/subprojects/store/src/main/java/tools/refinery/store/query/building/DNFAnd.java
+++ /dev/null
@@ -1,37 +0,0 @@
1package tools.refinery.store.query.building;
2
3import java.util.HashMap;
4import java.util.HashSet;
5import java.util.List;
6import java.util.Map;
7import java.util.Set;
8
9public class DNFAnd {
10 private Set<Variable> existentiallyQuantified;
11 private List<DNFAtom> constraints;
12 public DNFAnd(Set<Variable> quantifiedVariables, List<DNFAtom> constraints) {
13 super();
14 this.existentiallyQuantified = quantifiedVariables;
15 this.constraints = constraints;
16 }
17 public Set<Variable> getExistentiallyQuantified() {
18 return existentiallyQuantified;
19 }
20 public List<DNFAtom> getConstraints() {
21 return constraints;
22 }
23 void unifyVariables(Map<String,Variable> uniqueVariableMap) {
24 Map<String,Variable> uniqueVariableMapForClause = new HashMap<>(uniqueVariableMap);
25 for(DNFAtom atom : constraints) {
26 atom.unifyVariables(uniqueVariableMapForClause);
27 }
28 }
29 void collectQuantifiedVariables(Set<Variable> parameters) {
30 Set<Variable> result = new HashSet<>();
31 for(DNFAtom constraint : constraints) {
32 constraint.collectAllVariables(result);
33 }
34 result.removeAll(parameters);
35 existentiallyQuantified = result;
36 }
37}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/building/DNFAtom.java b/subprojects/store/src/main/java/tools/refinery/store/query/building/DNFAtom.java
deleted file mode 100644
index b047d7c8..00000000
--- a/subprojects/store/src/main/java/tools/refinery/store/query/building/DNFAtom.java
+++ /dev/null
@@ -1,33 +0,0 @@
1package tools.refinery.store.query.building;
2
3import java.util.Collection;
4import java.util.Iterator;
5import java.util.Map;
6import java.util.Set;
7
8public interface DNFAtom {
9 void unifyVariables(Map<String,Variable> variables);
10 static Variable unifyVariables(Map<String,Variable> unifiedVariables, Variable variable) {
11 if(variable != null) {
12 if(variable.isNamed() && unifiedVariables.containsKey(variable.getName())) {
13 return unifiedVariables.get(variable.getName());
14 }
15 return variable;
16 } else {
17 return null;
18 }
19 }
20 void collectAllVariables(Set<Variable> variables);
21 static void addToCollection(Set<Variable> variables, Variable variable) {
22 if(variable != null) {
23 variables.add(variable);
24 }
25 }
26 static void addToCollection(Set<Variable> variables, Collection<Variable> variableCollection) {
27 Iterator<Variable> iterator = variableCollection.iterator();
28 while(iterator.hasNext()) {
29 Variable variable = iterator.next();
30 addToCollection(variables, variable);
31 }
32 }
33}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/building/DNFPredicate.java b/subprojects/store/src/main/java/tools/refinery/store/query/building/DNFPredicate.java
deleted file mode 100644
index f0c9ac42..00000000
--- a/subprojects/store/src/main/java/tools/refinery/store/query/building/DNFPredicate.java
+++ /dev/null
@@ -1,72 +0,0 @@
1package tools.refinery.store.query.building;
2
3import java.util.HashMap;
4import java.util.HashSet;
5import java.util.List;
6import java.util.Map;
7import java.util.UUID;
8
9public class DNFPredicate {
10 private final String name;
11 private final String uniqueName;
12 private final List<Variable> parameters;
13 private final List<DNFAnd> clauses;
14
15 public DNFPredicate(String name, List<Variable> parameters, List<DNFAnd> clauses) {
16 this.name = name;
17 this.uniqueName = generateUniqueName(name,"predicate");
18 this.parameters = parameters;
19 this.clauses = clauses;
20
21 postProcess();
22 }
23
24 public static String generateUniqueName(String originalName, String defaultPrefix) {
25 UUID uuid = UUID.randomUUID();
26 String uniqueString = uuid.toString().replace('-', '_');
27 if(originalName == null) {
28 return defaultPrefix+uniqueString;
29 } else {
30 return originalName+uniqueString;
31 }
32 }
33
34 public String getName() {
35 return name;
36 }
37 public String getUniqueName() {
38 return uniqueName;
39 }
40 public List<Variable> getVariables() {
41 return parameters;
42 }
43 public List<DNFAnd> getClauses() {
44 return clauses;
45 }
46
47 public void unifyVariables() {
48 Map<String,Variable> uniqueVariableMap = new HashMap<>();
49 for(Variable parameter : this.parameters) {
50 if(parameter.isNamed()) {
51 String parameterName = parameter.getName();
52 if(uniqueVariableMap.containsKey(parameterName)) {
53 throw new IllegalArgumentException("Multiple parameters has the name "+parameterName);
54 } else {
55 uniqueVariableMap.put(parameterName, parameter);
56 }
57 }
58 }
59 for(DNFAnd clause : this.clauses) {
60 clause.unifyVariables(uniqueVariableMap);
61 }
62 }
63 public void collectQuantifiedVariables() {
64 for(DNFAnd clause : this.clauses) {
65 clause.collectQuantifiedVariables(new HashSet<>(parameters));
66 }
67 }
68 public void postProcess() {
69 unifyVariables();
70 collectQuantifiedVariables();
71 }
72}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/building/EquivalenceAtom.java b/subprojects/store/src/main/java/tools/refinery/store/query/building/EquivalenceAtom.java
deleted file mode 100644
index fede2518..00000000
--- a/subprojects/store/src/main/java/tools/refinery/store/query/building/EquivalenceAtom.java
+++ /dev/null
@@ -1,44 +0,0 @@
1package tools.refinery.store.query.building;
2
3import java.util.Map;
4import java.util.Set;
5
6public class EquivalenceAtom implements DNFAtom{
7 private boolean positive;
8 private Variable left;
9 private Variable right;
10 public EquivalenceAtom(boolean positive, Variable left, Variable right) {
11 this.positive = positive;
12 this.left = left;
13 this.right = right;
14 }
15 public boolean isPositive() {
16 return positive;
17 }
18 public void setPositive(boolean positive) {
19 this.positive = positive;
20 }
21 public Variable getLeft() {
22 return left;
23 }
24 public void setLeft(Variable left) {
25 this.left = left;
26 }
27 public Variable getRight() {
28 return right;
29 }
30 public void setRight(Variable right) {
31 this.right = right;
32 }
33
34 @Override
35 public void unifyVariables(Map<String, Variable> variables) {
36 this.left = DNFAtom.unifyVariables(variables,left);
37 this.right = DNFAtom.unifyVariables(variables,right);
38 }
39 @Override
40 public void collectAllVariables(Set<Variable> variables) {
41 DNFAtom.addToCollection(variables, left);
42 DNFAtom.addToCollection(variables, right);
43 }
44}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/building/PredicateAtom.java b/subprojects/store/src/main/java/tools/refinery/store/query/building/PredicateAtom.java
deleted file mode 100644
index 42394922..00000000
--- a/subprojects/store/src/main/java/tools/refinery/store/query/building/PredicateAtom.java
+++ /dev/null
@@ -1,66 +0,0 @@
1package tools.refinery.store.query.building;
2
3import java.util.List;
4import java.util.Map;
5import java.util.Set;
6
7public class PredicateAtom implements DNFAtom {
8 private DNFPredicate referred;
9 private List<Variable> substitution;
10 private boolean positive;
11 private boolean transitive;
12
13 public PredicateAtom(boolean positive, boolean transitive, DNFPredicate referred, List<Variable> substitution) {
14 this.positive = positive;
15 this.referred = referred;
16 this.substitution = substitution;
17 this.transitive = transitive;
18 }
19
20 public DNFPredicate getReferred() {
21 return referred;
22 }
23
24 public void setReferred(DNFPredicate referred) {
25 this.referred = referred;
26 }
27
28 public List<Variable> getSubstitution() {
29 return substitution;
30 }
31
32 public void setSubstitution(List<Variable> substitution) {
33 this.substitution = substitution;
34 }
35
36 public boolean isPositive() {
37 return positive;
38 }
39
40 public void setPositive(boolean positive) {
41 this.positive = positive;
42 }
43
44 public boolean isTransitive() {
45 return transitive;
46 }
47
48 public void setTransitive(boolean transitive) {
49 this.transitive = transitive;
50 }
51
52 @Override
53 public void unifyVariables(Map<String, Variable> variables) {
54 for (int i = 0; i < this.substitution.size(); i++) {
55 final Object term = this.substitution.get(i);
56 if (term instanceof Variable variableReference) {
57 this.substitution.set(i, DNFAtom.unifyVariables(variables, variableReference));
58 }
59 }
60 }
61
62 @Override
63 public void collectAllVariables(Set<Variable> variables) {
64 DNFAtom.addToCollection(variables, substitution);
65 }
66}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/building/RelationAtom.java b/subprojects/store/src/main/java/tools/refinery/store/query/building/RelationAtom.java
deleted file mode 100644
index f66245fc..00000000
--- a/subprojects/store/src/main/java/tools/refinery/store/query/building/RelationAtom.java
+++ /dev/null
@@ -1,31 +0,0 @@
1package tools.refinery.store.query.building;
2
3import tools.refinery.store.query.view.RelationView;
4
5import java.util.ArrayList;
6import java.util.List;
7import java.util.Map;
8import java.util.Set;
9
10public record RelationAtom(RelationView<?> view, List<Variable> substitution) implements DNFAtom {
11 public RelationAtom(RelationView<?> view, List<Variable> substitution) {
12 this.view = view;
13 // Create a mutable copy of substitution so that unifyVariables can change it.
14 this.substitution = new ArrayList<>(substitution);
15 }
16
17 @Override
18 public void unifyVariables(Map<String, Variable> variables) {
19 for (int i = 0; i < this.substitution.size(); i++) {
20 final Object term = this.substitution.get(i);
21 if (term instanceof Variable variableReference) {
22 this.substitution.set(i, DNFAtom.unifyVariables(variables, variableReference));
23 }
24 }
25 }
26
27 @Override
28 public void collectAllVariables(Set<Variable> variables) {
29 DNFAtom.addToCollection(variables, substitution);
30 }
31}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/building/Variable.java b/subprojects/store/src/main/java/tools/refinery/store/query/building/Variable.java
deleted file mode 100644
index 9ea7ce83..00000000
--- a/subprojects/store/src/main/java/tools/refinery/store/query/building/Variable.java
+++ /dev/null
@@ -1,22 +0,0 @@
1package tools.refinery.store.query.building;
2
3public class Variable {
4 private final String name;
5 private final String uniqueName;
6
7 public Variable(String name) {
8 super();
9 this.name = name;
10 this.uniqueName = DNFPredicate.generateUniqueName(name, "variable");
11
12 }
13 public String getName() {
14 return name;
15 }
16 public String getUniqueName() {
17 return uniqueName;
18 }
19 public boolean isNamed() {
20 return name != null;
21 }
22}
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
index ceaf7d55..96f8584a 100644
--- 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
@@ -2,6 +2,7 @@ package tools.refinery.store.query.view;
2 2
3import tools.refinery.store.map.CursorAsIterator; 3import tools.refinery.store.map.CursorAsIterator;
4import tools.refinery.store.model.Model; 4import tools.refinery.store.model.Model;
5import tools.refinery.store.model.RelationLike;
5import tools.refinery.store.tuple.Tuple; 6import tools.refinery.store.tuple.Tuple;
6import tools.refinery.store.model.representation.Relation; 7import tools.refinery.store.model.representation.Relation;
7 8
@@ -14,7 +15,7 @@ import java.util.UUID;
14 * @param <D> 15 * @param <D>
15 * @author Oszkar Semerath 16 * @author Oszkar Semerath
16 */ 17 */
17public abstract class RelationView<D> { 18public abstract class RelationView<D> implements RelationLike {
18 private final Relation<D> representation; 19 private final Relation<D> representation;
19 20
20 private final String name; 21 private final String name;
@@ -28,12 +29,11 @@ public abstract class RelationView<D> {
28 this(representation, UUID.randomUUID().toString()); 29 this(representation, UUID.randomUUID().toString());
29 } 30 }
30 31
31 public abstract int getArity();
32
33 public Relation<D> getRepresentation() { 32 public Relation<D> getRepresentation() {
34 return representation; 33 return representation;
35 } 34 }
36 35
36 @Override
37 public String getName() { 37 public String getName() {
38 return representation.getName() + "#" + name; 38 return representation.getName() + "#" + name;
39 } 39 }