diff options
Diffstat (limited to 'subprojects/store-query-viatra/src/main/java/tools')
10 files changed, 136 insertions, 66 deletions
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 5a02ca08..a63abc3a 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 | |||
@@ -8,10 +8,9 @@ import tools.refinery.store.model.representation.DataRepresentation; | |||
8 | import tools.refinery.store.query.QueryableModel; | 8 | import tools.refinery.store.query.QueryableModel; |
9 | import tools.refinery.store.query.QueryableModelStore; | 9 | import tools.refinery.store.query.QueryableModelStore; |
10 | import tools.refinery.store.query.building.*; | 10 | import tools.refinery.store.query.building.*; |
11 | import tools.refinery.store.query.viatra.internal.RawPatternMatcher; | ||
11 | import tools.refinery.store.query.viatra.internal.ViatraQueryableModel; | 12 | import tools.refinery.store.query.viatra.internal.ViatraQueryableModel; |
12 | import tools.refinery.store.query.viatra.internal.pquery.DNF2PQuery; | 13 | import tools.refinery.store.query.viatra.internal.pquery.DNF2PQuery; |
13 | import tools.refinery.store.query.viatra.internal.RawPatternMatcher; | ||
14 | import tools.refinery.store.query.viatra.internal.pquery.SimplePQuery; | ||
15 | import tools.refinery.store.query.view.RelationView; | 14 | import tools.refinery.store.query.view.RelationView; |
16 | 15 | ||
17 | import java.util.Collections; | 16 | import java.util.Collections; |
@@ -21,7 +20,9 @@ import java.util.Set; | |||
21 | 20 | ||
22 | public class ViatraQueryableModelStore implements QueryableModelStore { | 21 | public class ViatraQueryableModelStore implements QueryableModelStore { |
23 | protected final ModelStore store; | 22 | protected final ModelStore store; |
23 | |||
24 | protected final Set<RelationView<?>> relationViews; | 24 | protected final Set<RelationView<?>> relationViews; |
25 | |||
25 | protected final Map<DNFPredicate, GenericQuerySpecification<RawPatternMatcher>> predicates; | 26 | protected final Map<DNFPredicate, GenericQuerySpecification<RawPatternMatcher>> predicates; |
26 | 27 | ||
27 | public ViatraQueryableModelStore(ModelStore store, Set<RelationView<?>> relationViews, | 28 | public ViatraQueryableModelStore(ModelStore store, Set<RelationView<?>> relationViews, |
@@ -41,9 +42,9 @@ public class ViatraQueryableModelStore implements QueryableModelStore { | |||
41 | private void validateViews(Set<DataRepresentation<?, ?>> dataRepresentations, Set<RelationView<?>> relationViews) { | 42 | private void validateViews(Set<DataRepresentation<?, ?>> dataRepresentations, Set<RelationView<?>> relationViews) { |
42 | for (RelationView<?> relationView : relationViews) { | 43 | for (RelationView<?> relationView : relationViews) { |
43 | if (!dataRepresentations.contains(relationView.getRepresentation())) { | 44 | if (!dataRepresentations.contains(relationView.getRepresentation())) { |
44 | throw new IllegalArgumentException( | 45 | throw new IllegalArgumentException("%s %s added to %s without a referred representation.".formatted( |
45 | DataRepresentation.class.getSimpleName() + " " + relationView.getStringID() + " added to " | 46 | DataRepresentation.class.getSimpleName(), relationView.getName(), |
46 | + QueryableModelStore.class.getSimpleName() + " without a referred representation."); | 47 | QueryableModelStore.class.getSimpleName())); |
47 | } | 48 | } |
48 | } | 49 | } |
49 | } | 50 | } |
@@ -65,10 +66,10 @@ public class ViatraQueryableModelStore implements QueryableModelStore { | |||
65 | private void validateRelationAtom(Set<RelationView<?>> relationViews, DNFPredicate dnfPredicate, | 66 | private void validateRelationAtom(Set<RelationView<?>> relationViews, DNFPredicate dnfPredicate, |
66 | RelationAtom relationAtom) { | 67 | RelationAtom relationAtom) { |
67 | if (!relationViews.contains(relationAtom.view())) { | 68 | if (!relationViews.contains(relationAtom.view())) { |
68 | throw new IllegalArgumentException(DNFPredicate.class.getSimpleName() + " " | 69 | throw new IllegalArgumentException( |
69 | + dnfPredicate.getUniqueName() + " contains reference to a view of " | 70 | "%s %s contains reference to a view %s that is not in the model.".formatted( |
70 | + relationAtom.view().getRepresentation().getName() | 71 | DNFPredicate.class.getSimpleName(), dnfPredicate.getUniqueName(), |
71 | + " that is not in the model."); | 72 | relationAtom.view().getName())); |
72 | } | 73 | } |
73 | } | 74 | } |
74 | 75 | ||
@@ -76,19 +77,17 @@ public class ViatraQueryableModelStore implements QueryableModelStore { | |||
76 | PredicateAtom predicateAtom) { | 77 | PredicateAtom predicateAtom) { |
77 | if (!predicates.contains(predicateAtom.getReferred())) { | 78 | if (!predicates.contains(predicateAtom.getReferred())) { |
78 | throw new IllegalArgumentException( | 79 | throw new IllegalArgumentException( |
79 | DNFPredicate.class.getSimpleName() + " " + dnfPredicate.getUniqueName() | 80 | "%s %s contains reference to a predicate %s that is not in the model.".formatted( |
80 | + " contains reference to a predicate " | 81 | DNFPredicate.class.getSimpleName(), dnfPredicate.getUniqueName(), |
81 | + predicateAtom.getReferred().getName() | 82 | predicateAtom.getReferred().getName())); |
82 | + "that is not in the model."); | ||
83 | } | 83 | } |
84 | } | 84 | } |
85 | 85 | ||
86 | private Map<DNFPredicate, GenericQuerySpecification<RawPatternMatcher>> initPredicates(Set<DNFPredicate> predicates) { | 86 | private Map<DNFPredicate, GenericQuerySpecification<RawPatternMatcher>> initPredicates(Set<DNFPredicate> predicates) { |
87 | Map<DNFPredicate, GenericQuerySpecification<RawPatternMatcher>> result = new HashMap<>(); | 87 | Map<DNFPredicate, GenericQuerySpecification<RawPatternMatcher>> result = new HashMap<>(); |
88 | Map<DNFPredicate, SimplePQuery> dnf2PQueryMap = new HashMap<>(); | 88 | var dnf2PQuery = new DNF2PQuery(); |
89 | for (DNFPredicate dnfPredicate : predicates) { | 89 | for (DNFPredicate dnfPredicate : predicates) { |
90 | GenericQuerySpecification<RawPatternMatcher> query = | 90 | GenericQuerySpecification<RawPatternMatcher> query = dnf2PQuery.translate(dnfPredicate).build(); |
91 | DNF2PQuery.translate(dnfPredicate, dnf2PQueryMap).build(); | ||
92 | result.put(dnfPredicate, query); | 91 | result.put(dnfPredicate, query); |
93 | } | 92 | } |
94 | 93 | ||
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/context/RelationalEngineContext.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/context/RelationalEngineContext.java index 882734cb..d32d49ba 100644 --- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/context/RelationalEngineContext.java +++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/context/RelationalEngineContext.java | |||
@@ -29,5 +29,4 @@ public class RelationalEngineContext implements IEngineContext { | |||
29 | public IQueryRuntimeContext getQueryRuntimeContext() { | 29 | public IQueryRuntimeContext getQueryRuntimeContext() { |
30 | return runtimeContext; | 30 | return runtimeContext; |
31 | } | 31 | } |
32 | |||
33 | } | 32 | } |
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/context/RelationalQueryMetaContext.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/context/RelationalQueryMetaContext.java index 64c23c61..eb3c6fbd 100644 --- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/context/RelationalQueryMetaContext.java +++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/context/RelationalQueryMetaContext.java | |||
@@ -3,9 +3,11 @@ package tools.refinery.store.query.viatra.internal.context; | |||
3 | import org.eclipse.viatra.query.runtime.matchers.context.AbstractQueryMetaContext; | 3 | import org.eclipse.viatra.query.runtime.matchers.context.AbstractQueryMetaContext; |
4 | import org.eclipse.viatra.query.runtime.matchers.context.IInputKey; | 4 | import org.eclipse.viatra.query.runtime.matchers.context.IInputKey; |
5 | import org.eclipse.viatra.query.runtime.matchers.context.InputKeyImplication; | 5 | import org.eclipse.viatra.query.runtime.matchers.context.InputKeyImplication; |
6 | import tools.refinery.store.query.view.RelationView; | 6 | import tools.refinery.store.query.viatra.internal.pquery.RelationViewWrapper; |
7 | 7 | ||
8 | import java.util.*; | 8 | import java.util.Collection; |
9 | import java.util.Map; | ||
10 | import java.util.Set; | ||
9 | 11 | ||
10 | /** | 12 | /** |
11 | * The meta context information for String scopes. | 13 | * The meta context information for String scopes. |
@@ -36,9 +38,8 @@ public class RelationalQueryMetaContext extends AbstractQueryMetaContext { | |||
36 | } | 38 | } |
37 | 39 | ||
38 | public void ensureValidKey(IInputKey key) { | 40 | public void ensureValidKey(IInputKey key) { |
39 | if (key instanceof RelationView<?>) { | 41 | if (!(key instanceof RelationViewWrapper)) { |
40 | return; | 42 | throw new IllegalArgumentException("The input key %s is not a valid input key.".formatted(key)); |
41 | } | 43 | } |
42 | throw new IllegalArgumentException("The input key %s is not a valid input key.".formatted(key)); | ||
43 | } | 44 | } |
44 | } | 45 | } |
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/context/RelationalRuntimeContext.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/context/RelationalRuntimeContext.java index 0bd1b807..c007d630 100644 --- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/context/RelationalRuntimeContext.java +++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/context/RelationalRuntimeContext.java | |||
@@ -7,6 +7,7 @@ import org.eclipse.viatra.query.runtime.matchers.tuple.TupleMask; | |||
7 | import org.eclipse.viatra.query.runtime.matchers.tuple.Tuples; | 7 | import org.eclipse.viatra.query.runtime.matchers.tuple.Tuples; |
8 | import org.eclipse.viatra.query.runtime.matchers.util.Accuracy; | 8 | import org.eclipse.viatra.query.runtime.matchers.util.Accuracy; |
9 | import tools.refinery.store.model.Model; | 9 | import tools.refinery.store.model.Model; |
10 | import tools.refinery.store.query.viatra.internal.pquery.RelationViewWrapper; | ||
10 | import tools.refinery.store.query.viatra.internal.viewupdate.ModelUpdateListener; | 11 | import tools.refinery.store.query.viatra.internal.viewupdate.ModelUpdateListener; |
11 | import tools.refinery.store.query.view.RelationView; | 12 | import tools.refinery.store.query.view.RelationView; |
12 | 13 | ||
@@ -67,7 +68,8 @@ public class RelationalRuntimeContext implements IQueryRuntimeContext { | |||
67 | 68 | ||
68 | @SuppressWarnings("squid:S1452") | 69 | @SuppressWarnings("squid:S1452") |
69 | RelationView<?> checkKey(IInputKey key) { | 70 | RelationView<?> checkKey(IInputKey key) { |
70 | if (key instanceof RelationView<?> relationViewKey) { | 71 | if (key instanceof RelationViewWrapper wrappedKey) { |
72 | var relationViewKey = wrappedKey.getWrappedKey(); | ||
71 | if (modelUpdateListener.containsRelationalView(relationViewKey)) { | 73 | if (modelUpdateListener.containsRelationalView(relationViewKey)) { |
72 | return relationViewKey; | 74 | return relationViewKey; |
73 | } else { | 75 | } else { |
@@ -117,7 +119,7 @@ public class RelationalRuntimeContext implements IQueryRuntimeContext { | |||
117 | } | 119 | } |
118 | 120 | ||
119 | @Override | 121 | @Override |
120 | public Iterable<? extends Object> enumerateValues(IInputKey key, TupleMask seedMask, ITuple seed) { | 122 | public Iterable<?> enumerateValues(IInputKey key, TupleMask seedMask, ITuple seed) { |
121 | return enumerateTuples(key, seedMask, seed); | 123 | return enumerateTuples(key, seedMask, seed); |
122 | } | 124 | } |
123 | 125 | ||
@@ -130,14 +132,14 @@ public class RelationalRuntimeContext implements IQueryRuntimeContext { | |||
130 | @Override | 132 | @Override |
131 | public void addUpdateListener(IInputKey key, Tuple seed, IQueryRuntimeContextListener listener) { | 133 | public void addUpdateListener(IInputKey key, Tuple seed, IQueryRuntimeContextListener listener) { |
132 | RelationView<?> relationalKey = checkKey(key); | 134 | RelationView<?> relationalKey = checkKey(key); |
133 | this.modelUpdateListener.addListener(relationalKey, seed, listener); | 135 | this.modelUpdateListener.addListener(key, relationalKey, seed, listener); |
134 | 136 | ||
135 | } | 137 | } |
136 | 138 | ||
137 | @Override | 139 | @Override |
138 | public void removeUpdateListener(IInputKey key, Tuple seed, IQueryRuntimeContextListener listener) { | 140 | public void removeUpdateListener(IInputKey key, Tuple seed, IQueryRuntimeContextListener listener) { |
139 | RelationView<?> relationalKey = checkKey(key); | 141 | RelationView<?> relationalKey = checkKey(key); |
140 | this.modelUpdateListener.removeListener(relationalKey, seed, listener); | 142 | this.modelUpdateListener.removeListener(key, relationalKey, seed, listener); |
141 | } | 143 | } |
142 | 144 | ||
143 | @Override | 145 | @Override |
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 c093be47..b6468e76 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 | |||
@@ -12,28 +12,53 @@ import org.eclipse.viatra.query.runtime.matchers.psystem.basicenumerables.TypeCo | |||
12 | import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PParameter; | 12 | import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PParameter; |
13 | import org.eclipse.viatra.query.runtime.matchers.tuple.Tuples; | 13 | import org.eclipse.viatra.query.runtime.matchers.tuple.Tuples; |
14 | import tools.refinery.store.query.building.*; | 14 | import tools.refinery.store.query.building.*; |
15 | import tools.refinery.store.query.view.RelationView; | ||
15 | 16 | ||
16 | import java.util.*; | 17 | import java.util.*; |
18 | import java.util.stream.Collectors; | ||
17 | 19 | ||
18 | public class DNF2PQuery { | 20 | public class DNF2PQuery { |
19 | private DNF2PQuery() { | 21 | private final Set<DNFPredicate> translating = new LinkedHashSet<>(); |
20 | throw new IllegalStateException("This is a static utility class and should not be instantiated directly"); | 22 | |
21 | } | 23 | private final Map<DNFPredicate, SimplePQuery> dnf2PQueryMap = new HashMap<>(); |
22 | 24 | ||
23 | public static SimplePQuery translate(DNFPredicate predicate, Map<DNFPredicate, SimplePQuery> dnf2PQueryMap) { | 25 | private final Map<RelationView<?>, RelationViewWrapper> view2WrapperMap = new HashMap<>(); |
24 | SimplePQuery query = dnf2PQueryMap.get(predicate); | 26 | |
25 | if (query != null) { | 27 | public SimplePQuery translate(DNFPredicate predicate) { |
26 | return query; | 28 | if (translating.contains(predicate)) { |
29 | var path = translating.stream().map(DNFPredicate::getName).collect(Collectors.joining(" -> ")); | ||
30 | throw new IllegalStateException("Circular reference %s -> %s detected".formatted(path, | ||
31 | predicate.getName())); | ||
27 | } | 32 | } |
28 | query = new SimplePQuery(predicate.getName()); | 33 | // 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. | ||
35 | var pQuery = dnf2PQueryMap.get(predicate); | ||
36 | if (pQuery == null) { | ||
37 | translating.add(predicate); | ||
38 | try { | ||
39 | pQuery = doTranslate(predicate); | ||
40 | dnf2PQueryMap.put(predicate, pQuery); | ||
41 | } finally { | ||
42 | translating.remove(predicate); | ||
43 | } | ||
44 | } | ||
45 | return pQuery; | ||
46 | } | ||
47 | |||
48 | private SimplePQuery doTranslate(DNFPredicate predicate) { | ||
49 | var query = new SimplePQuery(predicate.getName()); | ||
50 | |||
29 | Map<Variable, PParameter> parameters = new HashMap<>(); | 51 | Map<Variable, PParameter> parameters = new HashMap<>(); |
52 | for (Variable variable : predicate.getVariables()) { | ||
53 | parameters.put(variable, new PParameter(variable.getName())); | ||
54 | } | ||
30 | 55 | ||
31 | predicate.getVariables().forEach(variable -> parameters.put(variable, new PParameter(variable.getName()))); | ||
32 | List<PParameter> parameterList = new ArrayList<>(); | 56 | List<PParameter> parameterList = new ArrayList<>(); |
33 | for (var param : predicate.getVariables()) { | 57 | for (var param : predicate.getVariables()) { |
34 | parameterList.add(parameters.get(param)); | 58 | parameterList.add(parameters.get(param)); |
35 | } | 59 | } |
36 | query.setParameters(parameterList); | 60 | query.setParameters(parameterList); |
61 | |||
37 | for (DNFAnd clause : predicate.getClauses()) { | 62 | for (DNFAnd clause : predicate.getClauses()) { |
38 | PBody body = new PBody(query); | 63 | PBody body = new PBody(query); |
39 | List<ExportedParameter> symbolicParameters = new ArrayList<>(); | 64 | List<ExportedParameter> symbolicParameters = new ArrayList<>(); |
@@ -44,15 +69,14 @@ public class DNF2PQuery { | |||
44 | body.setSymbolicParameters(symbolicParameters); | 69 | body.setSymbolicParameters(symbolicParameters); |
45 | query.addBody(body); | 70 | query.addBody(body); |
46 | for (DNFAtom constraint : clause.getConstraints()) { | 71 | for (DNFAtom constraint : clause.getConstraints()) { |
47 | translateDNFAtom(constraint, body, dnf2PQueryMap); | 72 | translateDNFAtom(constraint, body); |
48 | } | 73 | } |
49 | } | 74 | } |
50 | dnf2PQueryMap.put(predicate, query); | 75 | |
51 | return query; | 76 | return query; |
52 | } | 77 | } |
53 | 78 | ||
54 | private static void translateDNFAtom(DNFAtom constraint, PBody body, | 79 | private void translateDNFAtom(DNFAtom constraint, PBody body) { |
55 | Map<DNFPredicate, SimplePQuery> dnf2PQueryMap) { | ||
56 | if (constraint instanceof EquivalenceAtom equivalence) { | 80 | if (constraint instanceof EquivalenceAtom equivalence) { |
57 | translateEquivalenceAtom(equivalence, body); | 81 | translateEquivalenceAtom(equivalence, body); |
58 | } | 82 | } |
@@ -60,11 +84,11 @@ public class DNF2PQuery { | |||
60 | translateRelationAtom(relation, body); | 84 | translateRelationAtom(relation, body); |
61 | } | 85 | } |
62 | if (constraint instanceof PredicateAtom predicate) { | 86 | if (constraint instanceof PredicateAtom predicate) { |
63 | translatePredicateAtom(predicate, body, dnf2PQueryMap); | 87 | translatePredicateAtom(predicate, body); |
64 | } | 88 | } |
65 | } | 89 | } |
66 | 90 | ||
67 | private static void translateEquivalenceAtom(EquivalenceAtom equivalence, PBody body) { | 91 | private void translateEquivalenceAtom(EquivalenceAtom equivalence, PBody body) { |
68 | PVariable varSource = body.getOrCreateVariableByName(equivalence.getLeft().getName()); | 92 | PVariable varSource = body.getOrCreateVariableByName(equivalence.getLeft().getName()); |
69 | PVariable varTarget = body.getOrCreateVariableByName(equivalence.getRight().getName()); | 93 | PVariable varTarget = body.getOrCreateVariableByName(equivalence.getRight().getName()); |
70 | if (equivalence.isPositive()) | 94 | if (equivalence.isPositive()) |
@@ -73,7 +97,7 @@ public class DNF2PQuery { | |||
73 | new Inequality(body, varSource, varTarget); | 97 | new Inequality(body, varSource, varTarget); |
74 | } | 98 | } |
75 | 99 | ||
76 | private static void translateRelationAtom(RelationAtom relation, PBody body) { | 100 | private void translateRelationAtom(RelationAtom relation, PBody body) { |
77 | if (relation.substitution().size() != relation.view().getArity()) { | 101 | if (relation.substitution().size() != relation.view().getArity()) { |
78 | throw new IllegalArgumentException("Arity (%d) does not match parameter numbers (%d)".formatted( | 102 | throw new IllegalArgumentException("Arity (%d) does not match parameter numbers (%d)".formatted( |
79 | relation.view().getArity(), relation.substitution().size())); | 103 | relation.view().getArity(), relation.substitution().size())); |
@@ -82,32 +106,34 @@ public class DNF2PQuery { | |||
82 | for (int i = 0; i < relation.substitution().size(); i++) { | 106 | for (int i = 0; i < relation.substitution().size(); i++) { |
83 | variables[i] = body.getOrCreateVariableByName(relation.substitution().get(i).getName()); | 107 | variables[i] = body.getOrCreateVariableByName(relation.substitution().get(i).getName()); |
84 | } | 108 | } |
85 | new TypeConstraint(body, Tuples.flatTupleOf(variables), relation.view()); | 109 | new TypeConstraint(body, Tuples.flatTupleOf(variables), wrapView(relation.view())); |
110 | } | ||
111 | |||
112 | private RelationViewWrapper wrapView(RelationView<?> relationView) { | ||
113 | return view2WrapperMap.computeIfAbsent(relationView, RelationViewWrapper::new); | ||
86 | } | 114 | } |
87 | 115 | ||
88 | private static void translatePredicateAtom(PredicateAtom predicate, PBody body, | 116 | private void translatePredicateAtom(PredicateAtom predicate, PBody body) { |
89 | Map<DNFPredicate, SimplePQuery> dnf2PQueryMap) { | ||
90 | Object[] variables = new Object[predicate.getSubstitution().size()]; | 117 | Object[] variables = new Object[predicate.getSubstitution().size()]; |
91 | for (int i = 0; i < predicate.getSubstitution().size(); i++) { | 118 | for (int i = 0; i < predicate.getSubstitution().size(); i++) { |
92 | variables[i] = body.getOrCreateVariableByName(predicate.getSubstitution().get(i).getName()); | 119 | variables[i] = body.getOrCreateVariableByName(predicate.getSubstitution().get(i).getName()); |
93 | } | 120 | } |
121 | var variablesTuple = Tuples.flatTupleOf(variables); | ||
122 | var translatedReferred = translate(predicate.getReferred()); | ||
94 | if (predicate.isPositive()) { | 123 | if (predicate.isPositive()) { |
95 | if (predicate.isTransitive()) { | 124 | if (predicate.isTransitive()) { |
96 | if (predicate.getSubstitution().size() != 2) { | 125 | if (predicate.getSubstitution().size() != 2) { |
97 | throw new IllegalArgumentException("Transitive Predicate Atoms must be binary."); | 126 | throw new IllegalArgumentException("Transitive Predicate Atoms must be binary."); |
98 | } | 127 | } |
99 | new BinaryTransitiveClosure(body, Tuples.flatTupleOf(variables), | 128 | new BinaryTransitiveClosure(body, variablesTuple, translatedReferred); |
100 | DNF2PQuery.translate(predicate.getReferred(), dnf2PQueryMap)); | ||
101 | } else { | 129 | } else { |
102 | new PositivePatternCall(body, Tuples.flatTupleOf(variables), | 130 | new PositivePatternCall(body, variablesTuple, translatedReferred); |
103 | DNF2PQuery.translate(predicate.getReferred(), dnf2PQueryMap)); | ||
104 | } | 131 | } |
105 | } else { | 132 | } else { |
106 | if (predicate.isTransitive()) { | 133 | if (predicate.isTransitive()) { |
107 | throw new InputMismatchException("Transitive Predicate Atoms cannot be negative."); | 134 | throw new IllegalArgumentException("Transitive Predicate Atoms cannot be negative."); |
108 | } else { | 135 | } else { |
109 | new NegativePatternCall(body, Tuples.flatTupleOf(variables), | 136 | new NegativePatternCall(body, variablesTuple, translatedReferred); |
110 | DNF2PQuery.translate(predicate.getReferred(), dnf2PQueryMap)); | ||
111 | } | 137 | } |
112 | } | 138 | } |
113 | } | 139 | } |
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/RelationViewWrapper.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/RelationViewWrapper.java new file mode 100644 index 00000000..2a4148dc --- /dev/null +++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/RelationViewWrapper.java | |||
@@ -0,0 +1,30 @@ | |||
1 | package tools.refinery.store.query.viatra.internal.pquery; | ||
2 | |||
3 | import org.eclipse.viatra.query.runtime.matchers.context.common.BaseInputKeyWrapper; | ||
4 | import tools.refinery.store.query.view.RelationView; | ||
5 | |||
6 | public class RelationViewWrapper extends BaseInputKeyWrapper<RelationView<?>> { | ||
7 | public RelationViewWrapper(RelationView<?> wrappedKey) { | ||
8 | super(wrappedKey); | ||
9 | } | ||
10 | |||
11 | @Override | ||
12 | public String getPrettyPrintableName() { | ||
13 | return wrappedKey.getName(); | ||
14 | } | ||
15 | |||
16 | @Override | ||
17 | public String getStringID() { | ||
18 | return getPrettyPrintableName(); | ||
19 | } | ||
20 | |||
21 | @Override | ||
22 | public int getArity() { | ||
23 | return wrappedKey.getArity(); | ||
24 | } | ||
25 | |||
26 | @Override | ||
27 | public boolean isEnumerable() { | ||
28 | return true; | ||
29 | } | ||
30 | } | ||
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/viewupdate/ModelUpdateListener.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/viewupdate/ModelUpdateListener.java index 25919888..5a0da315 100644 --- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/viewupdate/ModelUpdateListener.java +++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/viewupdate/ModelUpdateListener.java | |||
@@ -1,5 +1,6 @@ | |||
1 | package tools.refinery.store.query.viatra.internal.viewupdate; | 1 | package tools.refinery.store.query.viatra.internal.viewupdate; |
2 | 2 | ||
3 | import org.eclipse.viatra.query.runtime.matchers.context.IInputKey; | ||
3 | import org.eclipse.viatra.query.runtime.matchers.context.IQueryRuntimeContextListener; | 4 | import org.eclipse.viatra.query.runtime.matchers.context.IQueryRuntimeContextListener; |
4 | import org.eclipse.viatra.query.runtime.matchers.tuple.ITuple; | 5 | import org.eclipse.viatra.query.runtime.matchers.tuple.ITuple; |
5 | import tools.refinery.store.model.Tuple; | 6 | import tools.refinery.store.model.Tuple; |
@@ -46,20 +47,23 @@ public class ModelUpdateListener { | |||
46 | return view2Buffers.containsKey(relationalKey); | 47 | return view2Buffers.containsKey(relationalKey); |
47 | } | 48 | } |
48 | 49 | ||
49 | public <D> void addListener(RelationView<D> relationView, ITuple seed, IQueryRuntimeContextListener listener) { | 50 | public <D> void addListener(IInputKey key, RelationView<D> relationView, ITuple seed, |
51 | IQueryRuntimeContextListener listener) { | ||
50 | if (view2Buffers.containsKey(relationView)) { | 52 | if (view2Buffers.containsKey(relationView)) { |
51 | ViewUpdateTranslator<D> updateListener = new ViewUpdateTranslator<>(relationView, seed, listener); | 53 | ViewUpdateTranslator<D> updateListener = new ViewUpdateTranslator<>(key, relationView, seed, listener); |
52 | ViewUpdateBuffer<D> updateBuffer = new ViewUpdateBuffer<>(updateListener); | 54 | ViewUpdateBuffer<D> updateBuffer = new ViewUpdateBuffer<>(updateListener); |
53 | view2Buffers.get(relationView).add(updateBuffer); | 55 | view2Buffers.get(relationView).add(updateBuffer); |
54 | } else | 56 | } else { |
55 | throw new IllegalArgumentException(); | 57 | throw new IllegalArgumentException(); |
58 | } | ||
56 | } | 59 | } |
57 | 60 | ||
58 | public void removeListener(RelationView<?> relationView, ITuple seed, IQueryRuntimeContextListener listener) { | 61 | public void removeListener(IInputKey key, RelationView<?> relationView, ITuple seed, |
62 | IQueryRuntimeContextListener listener) { | ||
59 | if (view2Buffers.containsKey(relationView)) { | 63 | if (view2Buffers.containsKey(relationView)) { |
60 | Set<ViewUpdateBuffer<?>> buffers = this.view2Buffers.get(relationView); | 64 | Set<ViewUpdateBuffer<?>> buffers = this.view2Buffers.get(relationView); |
61 | for (var buffer : buffers) { | 65 | for (var buffer : buffers) { |
62 | if (buffer.getUpdateListener().equals(relationView, seed, listener)) { | 66 | if (buffer.getUpdateListener().equals(key, relationView, seed, listener)) { |
63 | // remove buffer and terminate immediately, or it will break iterator. | 67 | // remove buffer and terminate immediately, or it will break iterator. |
64 | buffers.remove(buffer); | 68 | buffers.remove(buffer); |
65 | return; | 69 | return; |
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/viewupdate/ViewUpdate.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/viewupdate/ViewUpdate.java index c727f046..b9406018 100644 --- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/viewupdate/ViewUpdate.java +++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/viewupdate/ViewUpdate.java | |||
@@ -3,8 +3,7 @@ package tools.refinery.store.query.viatra.internal.viewupdate; | |||
3 | import java.util.Arrays; | 3 | import java.util.Arrays; |
4 | import java.util.Objects; | 4 | import java.util.Objects; |
5 | 5 | ||
6 | record ViewUpdate (Object[] tuple, boolean isInsertion) { | 6 | record ViewUpdate(Object[] tuple, boolean isInsertion) { |
7 | |||
8 | @Override | 7 | @Override |
9 | public int hashCode() { | 8 | public int hashCode() { |
10 | final int prime = 31; | 9 | final int prime = 31; |
@@ -28,7 +27,6 @@ record ViewUpdate (Object[] tuple, boolean isInsertion) { | |||
28 | 27 | ||
29 | @Override | 28 | @Override |
30 | public String toString() { | 29 | public String toString() { |
31 | return "ViewUpdate [" + Arrays.toString(tuple) + "insertion= "+this.isInsertion+"]"; | 30 | return "ViewUpdate [" + Arrays.toString(tuple) + "insertion= " + this.isInsertion + "]"; |
32 | } | 31 | } |
33 | |||
34 | } | 32 | } |
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/viewupdate/ViewUpdateBuffer.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/viewupdate/ViewUpdateBuffer.java index 5a4243f2..e13a9cb8 100644 --- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/viewupdate/ViewUpdateBuffer.java +++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/viewupdate/ViewUpdateBuffer.java | |||
@@ -8,6 +8,7 @@ import java.util.List; | |||
8 | 8 | ||
9 | public class ViewUpdateBuffer<D> { | 9 | public class ViewUpdateBuffer<D> { |
10 | protected final ViewUpdateTranslator<D> updateListener; | 10 | protected final ViewUpdateTranslator<D> updateListener; |
11 | |||
11 | protected final List<ViewUpdate> buffer = new ArrayList<>(); | 12 | protected final List<ViewUpdate> buffer = new ArrayList<>(); |
12 | 13 | ||
13 | public ViewUpdateBuffer(ViewUpdateTranslator<D> updateListener) { | 14 | public ViewUpdateBuffer(ViewUpdateTranslator<D> updateListener) { |
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/viewupdate/ViewUpdateTranslator.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/viewupdate/ViewUpdateTranslator.java index 2f7f9a9c..62a10e45 100644 --- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/viewupdate/ViewUpdateTranslator.java +++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/viewupdate/ViewUpdateTranslator.java | |||
@@ -1,5 +1,6 @@ | |||
1 | package tools.refinery.store.query.viatra.internal.viewupdate; | 1 | package tools.refinery.store.query.viatra.internal.viewupdate; |
2 | 2 | ||
3 | import org.eclipse.viatra.query.runtime.matchers.context.IInputKey; | ||
3 | import org.eclipse.viatra.query.runtime.matchers.context.IQueryRuntimeContextListener; | 4 | import org.eclipse.viatra.query.runtime.matchers.context.IQueryRuntimeContextListener; |
4 | import org.eclipse.viatra.query.runtime.matchers.tuple.ITuple; | 5 | import org.eclipse.viatra.query.runtime.matchers.tuple.ITuple; |
5 | import org.eclipse.viatra.query.runtime.matchers.tuple.Tuples; | 6 | import org.eclipse.viatra.query.runtime.matchers.tuple.Tuples; |
@@ -9,29 +10,38 @@ import tools.refinery.store.query.view.RelationView; | |||
9 | import java.util.Objects; | 10 | import java.util.Objects; |
10 | 11 | ||
11 | public class ViewUpdateTranslator<D> { | 12 | public class ViewUpdateTranslator<D> { |
13 | private final IInputKey wrappedKey; | ||
14 | |||
12 | private final RelationView<D> key; | 15 | private final RelationView<D> key; |
13 | 16 | ||
14 | private final ITuple filter; | 17 | private final ITuple filter; |
15 | 18 | ||
16 | private final IQueryRuntimeContextListener listener; | 19 | private final IQueryRuntimeContextListener listener; |
17 | 20 | ||
18 | public ViewUpdateTranslator(RelationView<D> key, ITuple filter, IQueryRuntimeContextListener listener) { | 21 | public ViewUpdateTranslator(IInputKey wrappedKey, RelationView<D> key, ITuple filter, |
22 | IQueryRuntimeContextListener listener) { | ||
19 | super(); | 23 | super(); |
24 | this.wrappedKey = wrappedKey; | ||
20 | this.key = key; | 25 | this.key = key; |
21 | this.filter = filter; | 26 | this.filter = filter; |
22 | this.listener = listener; | 27 | this.listener = listener; |
23 | } | 28 | } |
24 | 29 | ||
25 | public boolean equals(RelationView<?> relationView, ITuple seed, IQueryRuntimeContextListener listener) { | 30 | public boolean equals(IInputKey wrappedKey, RelationView<?> relationView, ITuple seed, |
26 | return key == relationView && filter.equals(seed) && this.listener == listener; | 31 | IQueryRuntimeContextListener listener) { |
32 | return this.wrappedKey == wrappedKey && key == relationView && filter.equals(seed) && this.listener == listener; | ||
27 | } | 33 | } |
28 | 34 | ||
29 | public void processChange(ViewUpdate change) { | 35 | public void processChange(ViewUpdate change) { |
30 | listener.update(key, Tuples.flatTupleOf(change.tuple()), change.isInsertion()); | 36 | listener.update(wrappedKey, Tuples.flatTupleOf(change.tuple()), change.isInsertion()); |
31 | } | 37 | } |
32 | 38 | ||
39 | @SuppressWarnings("squid:S1168") | ||
33 | public Object[] isMatching(Tuple tuple, D value) { | 40 | public Object[] isMatching(Tuple tuple, D value) { |
34 | return isMatching(key.getWrappedKey().transform(tuple, value), filter); | 41 | if (!key.filter(tuple, value)) { |
42 | return null; | ||
43 | } | ||
44 | return isMatching(key.forwardMap(tuple, value), filter); | ||
35 | } | 45 | } |
36 | 46 | ||
37 | @SuppressWarnings("squid:S1168") | 47 | @SuppressWarnings("squid:S1168") |