diff options
Diffstat (limited to 'subprojects/store-query-viatra')
31 files changed, 1009 insertions, 950 deletions
diff --git a/subprojects/store-query-viatra/build.gradle b/subprojects/store-query-viatra/build.gradle index 32a23fe7..c12b48fe 100644 --- a/subprojects/store-query-viatra/build.gradle +++ b/subprojects/store-query-viatra/build.gradle | |||
@@ -9,7 +9,7 @@ configurations.testRuntimeClasspath { | |||
9 | 9 | ||
10 | dependencies { | 10 | dependencies { |
11 | implementation libs.ecore | 11 | implementation libs.ecore |
12 | implementation libs.viatra | 12 | api libs.viatra |
13 | api project(':refinery-store') | 13 | api project(':refinery-store') |
14 | testImplementation libs.slf4j.simple | 14 | testImplementation libs.slf4j.simple |
15 | testImplementation libs.slf4j.log4j | 15 | testImplementation libs.slf4j.log4j |
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/ViatraModelQuery.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/ViatraModelQuery.java new file mode 100644 index 00000000..ecac570b --- /dev/null +++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/ViatraModelQuery.java | |||
@@ -0,0 +1,22 @@ | |||
1 | package tools.refinery.store.query.viatra; | ||
2 | |||
3 | import tools.refinery.store.adapter.ModelAdapterBuilderFactory; | ||
4 | import tools.refinery.store.model.ModelStoreBuilder; | ||
5 | import tools.refinery.store.query.ModelQuery; | ||
6 | import tools.refinery.store.query.ModelQueryAdapter; | ||
7 | import tools.refinery.store.query.viatra.internal.ViatraModelQueryBuilderImpl; | ||
8 | |||
9 | public final class ViatraModelQuery extends ModelAdapterBuilderFactory<ModelQueryAdapter, ViatraModelQueryStoreAdapter, | ||
10 | ViatraModelQueryBuilder> { | ||
11 | public static final ViatraModelQuery ADAPTER = new ViatraModelQuery(); | ||
12 | |||
13 | private ViatraModelQuery() { | ||
14 | super(ModelQueryAdapter.class, ViatraModelQueryStoreAdapter.class, ViatraModelQueryBuilder.class); | ||
15 | extendsAdapter(ModelQuery.ADAPTER); | ||
16 | } | ||
17 | |||
18 | @Override | ||
19 | public ViatraModelQueryBuilder createBuilder(ModelStoreBuilder storeBuilder) { | ||
20 | return new ViatraModelQueryBuilderImpl(storeBuilder); | ||
21 | } | ||
22 | } | ||
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/ViatraModelQueryBuilder.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/ViatraModelQueryBuilder.java new file mode 100644 index 00000000..ee445a79 --- /dev/null +++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/ViatraModelQueryBuilder.java | |||
@@ -0,0 +1,48 @@ | |||
1 | package tools.refinery.store.query.viatra; | ||
2 | |||
3 | import org.eclipse.viatra.query.runtime.api.ViatraQueryEngineOptions; | ||
4 | import org.eclipse.viatra.query.runtime.matchers.backend.IQueryBackendFactory; | ||
5 | import org.eclipse.viatra.query.runtime.matchers.backend.QueryEvaluationHint; | ||
6 | import tools.refinery.store.model.ModelStore; | ||
7 | import tools.refinery.store.query.DNF; | ||
8 | import tools.refinery.store.query.ModelQueryBuilder; | ||
9 | |||
10 | import java.util.Collection; | ||
11 | import java.util.function.Function; | ||
12 | |||
13 | @SuppressWarnings("UnusedReturnValue") | ||
14 | public interface ViatraModelQueryBuilder extends ModelQueryBuilder { | ||
15 | ViatraModelQueryBuilder engineOptions(ViatraQueryEngineOptions engineOptions); | ||
16 | |||
17 | ViatraModelQueryBuilder defaultHint(QueryEvaluationHint queryEvaluationHint); | ||
18 | |||
19 | ViatraModelQueryBuilder backend(IQueryBackendFactory queryBackendFactory); | ||
20 | |||
21 | ViatraModelQueryBuilder cachingBackend(IQueryBackendFactory queryBackendFactory); | ||
22 | |||
23 | ViatraModelQueryBuilder searchBackend(IQueryBackendFactory queryBackendFactory); | ||
24 | |||
25 | @Override | ||
26 | default ViatraModelQueryBuilder queries(DNF... queries) { | ||
27 | ModelQueryBuilder.super.queries(queries); | ||
28 | return this; | ||
29 | } | ||
30 | |||
31 | @Override | ||
32 | default ViatraModelQueryBuilder queries(Collection<? extends DNF> queries) { | ||
33 | ModelQueryBuilder.super.queries(queries); | ||
34 | return this; | ||
35 | } | ||
36 | |||
37 | @Override | ||
38 | ViatraModelQueryBuilder query(DNF query); | ||
39 | |||
40 | ViatraModelQueryBuilder query(DNF query, QueryEvaluationHint queryEvaluationHint); | ||
41 | |||
42 | ViatraModelQueryBuilder computeHint(Function<DNF, QueryEvaluationHint> computeHint); | ||
43 | |||
44 | ViatraModelQueryBuilder hint(DNF dnf, QueryEvaluationHint queryEvaluationHint); | ||
45 | |||
46 | @Override | ||
47 | ViatraModelQueryStoreAdapter createStoreAdapter(ModelStore store); | ||
48 | } | ||
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/ViatraModelQueryStoreAdapter.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/ViatraModelQueryStoreAdapter.java new file mode 100644 index 00000000..d52575d2 --- /dev/null +++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/ViatraModelQueryStoreAdapter.java | |||
@@ -0,0 +1,8 @@ | |||
1 | package tools.refinery.store.query.viatra; | ||
2 | |||
3 | import org.eclipse.viatra.query.runtime.api.ViatraQueryEngineOptions; | ||
4 | import tools.refinery.store.query.ModelQueryStoreAdapter; | ||
5 | |||
6 | public interface ViatraModelQueryStoreAdapter extends ModelQueryStoreAdapter { | ||
7 | ViatraQueryEngineOptions getEngineOptions(); | ||
8 | } | ||
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 deleted file mode 100644 index 94d2db4f..00000000 --- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/ViatraQueryableModelStore.java +++ /dev/null | |||
@@ -1,140 +0,0 @@ | |||
1 | package tools.refinery.store.query.viatra; | ||
2 | |||
3 | import org.eclipse.viatra.query.runtime.api.GenericQuerySpecification; | ||
4 | import tools.refinery.store.model.ModelDiffCursor; | ||
5 | import tools.refinery.store.model.ModelStore; | ||
6 | import tools.refinery.store.model.ModelStoreImpl; | ||
7 | import tools.refinery.store.model.RelationLike; | ||
8 | import tools.refinery.store.model.representation.AnyDataRepresentation; | ||
9 | import tools.refinery.store.model.representation.DataRepresentation; | ||
10 | import tools.refinery.store.query.DNF; | ||
11 | import tools.refinery.store.query.DNFAnd; | ||
12 | import tools.refinery.store.query.QueryableModel; | ||
13 | import tools.refinery.store.query.QueryableModelStore; | ||
14 | import tools.refinery.store.query.atom.*; | ||
15 | import tools.refinery.store.query.viatra.internal.RawPatternMatcher; | ||
16 | import tools.refinery.store.query.viatra.internal.ViatraQueryableModel; | ||
17 | import tools.refinery.store.query.viatra.internal.pquery.DNF2PQuery; | ||
18 | import tools.refinery.store.query.view.AnyRelationView; | ||
19 | |||
20 | import java.util.Collections; | ||
21 | import java.util.HashMap; | ||
22 | import java.util.Map; | ||
23 | import java.util.Set; | ||
24 | |||
25 | public class ViatraQueryableModelStore implements QueryableModelStore { | ||
26 | protected final ModelStore store; | ||
27 | |||
28 | protected final Set<AnyRelationView> relationViews; | ||
29 | |||
30 | protected final Map<DNF, GenericQuerySpecification<RawPatternMatcher>> predicates; | ||
31 | |||
32 | public ViatraQueryableModelStore(ModelStore store, Set<AnyRelationView> relationViews, | ||
33 | Set<DNF> predicates) { | ||
34 | this.store = store; | ||
35 | validateViews(store.getDataRepresentations(), relationViews); | ||
36 | this.relationViews = Collections.unmodifiableSet(relationViews); | ||
37 | validatePredicates(relationViews, predicates); | ||
38 | this.predicates = initPredicates(predicates); | ||
39 | } | ||
40 | |||
41 | public ViatraQueryableModelStore(Set<AnyDataRepresentation> dataRepresentations, | ||
42 | Set<AnyRelationView> relationViews, Set<DNF> predicates) { | ||
43 | this(new ModelStoreImpl(dataRepresentations), relationViews, predicates); | ||
44 | } | ||
45 | |||
46 | private void validateViews(Set<AnyDataRepresentation> dataRepresentations, Set<AnyRelationView> relationViews) { | ||
47 | for (var relationView : relationViews) { | ||
48 | if (!dataRepresentations.contains(relationView.getRepresentation())) { | ||
49 | throw new IllegalArgumentException("%s %s added to %s without a referred representation.".formatted( | ||
50 | DataRepresentation.class.getSimpleName(), relationView.getName(), | ||
51 | QueryableModelStore.class.getSimpleName())); | ||
52 | } | ||
53 | } | ||
54 | } | ||
55 | |||
56 | private void validatePredicates(Set<AnyRelationView> relationViews, Set<DNF> predicates) { | ||
57 | for (DNF dnfPredicate : predicates) { | ||
58 | for (DNFAnd clause : dnfPredicate.getClauses()) { | ||
59 | for (DNFAtom atom : clause.constraints()) { | ||
60 | if (atom instanceof RelationViewAtom relationViewAtom) { | ||
61 | validateRelationAtom(relationViews, dnfPredicate, relationViewAtom); | ||
62 | } else if (atom instanceof CallAtom<?> queryCallAtom) { | ||
63 | validatePredicateAtom(predicates, dnfPredicate, queryCallAtom); | ||
64 | } else if (!(atom instanceof EquivalenceAtom || atom instanceof ConstantAtom)) { | ||
65 | throw new IllegalArgumentException("Unknown constraint: " + atom.toString()); | ||
66 | } | ||
67 | } | ||
68 | } | ||
69 | } | ||
70 | } | ||
71 | |||
72 | private void validateRelationAtom(Set<AnyRelationView> relationViews, DNF dnfPredicate, | ||
73 | RelationViewAtom relationViewAtom) { | ||
74 | if (!relationViews.contains(relationViewAtom.getTarget())) { | ||
75 | throw new IllegalArgumentException( | ||
76 | "%s %s contains reference to a view %s that is not in the model.".formatted( | ||
77 | DNF.class.getSimpleName(), dnfPredicate.getUniqueName(), | ||
78 | relationViewAtom.getTarget().getName())); | ||
79 | } | ||
80 | } | ||
81 | |||
82 | private void validatePredicateReference(Set<DNF> predicates, DNF dnfPredicate, RelationLike target) { | ||
83 | if (!(target instanceof DNF dnfTarget) || !predicates.contains(dnfTarget)) { | ||
84 | throw new IllegalArgumentException( | ||
85 | "%s %s contains reference to a predicate %s that is not in the model.".formatted( | ||
86 | DNF.class.getSimpleName(), dnfPredicate.getUniqueName(), target.getName())); | ||
87 | } | ||
88 | } | ||
89 | |||
90 | private void validatePredicateAtom(Set<DNF> predicates, DNF dnfPredicate, CallAtom<?> queryCallAtom) { | ||
91 | validatePredicateReference(predicates, dnfPredicate, queryCallAtom.getTarget()); | ||
92 | } | ||
93 | |||
94 | |||
95 | private Map<DNF, GenericQuerySpecification<RawPatternMatcher>> initPredicates(Set<DNF> predicates) { | ||
96 | Map<DNF, GenericQuerySpecification<RawPatternMatcher>> result = new HashMap<>(); | ||
97 | var dnf2PQuery = new DNF2PQuery(); | ||
98 | for (DNF dnfPredicate : predicates) { | ||
99 | GenericQuerySpecification<RawPatternMatcher> query = dnf2PQuery.translate(dnfPredicate).build(); | ||
100 | result.put(dnfPredicate, query); | ||
101 | } | ||
102 | |||
103 | return result; | ||
104 | } | ||
105 | |||
106 | @Override | ||
107 | public Set<AnyDataRepresentation> getDataRepresentations() { | ||
108 | return store.getDataRepresentations(); | ||
109 | } | ||
110 | |||
111 | @Override | ||
112 | public Set<AnyRelationView> getViews() { | ||
113 | return this.relationViews; | ||
114 | } | ||
115 | |||
116 | @Override | ||
117 | public Set<DNF> getPredicates() { | ||
118 | return predicates.keySet(); | ||
119 | } | ||
120 | |||
121 | @Override | ||
122 | public QueryableModel createModel() { | ||
123 | return new ViatraQueryableModel(this, this.store.createModel(), predicates); | ||
124 | } | ||
125 | |||
126 | @Override | ||
127 | public QueryableModel createModel(long state) { | ||
128 | return new ViatraQueryableModel(this, this.store.createModel(state), predicates); | ||
129 | } | ||
130 | |||
131 | @Override | ||
132 | public synchronized Set<Long> getStates() { | ||
133 | return this.store.getStates(); | ||
134 | } | ||
135 | |||
136 | @Override | ||
137 | public synchronized ModelDiffCursor getDiffCursor(long from, long to) { | ||
138 | return this.store.getDiffCursor(from, to); | ||
139 | } | ||
140 | } | ||
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/RelationalScope.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/RelationalScope.java index 133c4c72..21dcaf15 100644 --- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/RelationalScope.java +++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/RelationalScope.java | |||
@@ -6,34 +6,20 @@ import org.eclipse.viatra.query.runtime.api.scope.IEngineContext; | |||
6 | import org.eclipse.viatra.query.runtime.api.scope.IIndexingErrorListener; | 6 | import org.eclipse.viatra.query.runtime.api.scope.IIndexingErrorListener; |
7 | import org.eclipse.viatra.query.runtime.api.scope.QueryScope; | 7 | import org.eclipse.viatra.query.runtime.api.scope.QueryScope; |
8 | import tools.refinery.store.model.Model; | 8 | import tools.refinery.store.model.Model; |
9 | import tools.refinery.store.model.representation.Relation; | ||
10 | import tools.refinery.store.query.viatra.internal.context.RelationalEngineContext; | 9 | import tools.refinery.store.query.viatra.internal.context.RelationalEngineContext; |
11 | import tools.refinery.store.query.viatra.internal.viewupdate.ModelUpdateListener; | 10 | import tools.refinery.store.query.viatra.internal.update.ModelUpdateListener; |
12 | import tools.refinery.store.query.view.AnyRelationView; | 11 | import tools.refinery.store.query.view.AnyRelationView; |
13 | import tools.refinery.store.tuple.Tuple; | ||
14 | 12 | ||
15 | import java.util.Set; | 13 | import java.util.Collection; |
16 | 14 | ||
17 | public class RelationalScope extends QueryScope { | 15 | public class RelationalScope extends QueryScope { |
18 | private final Model model; | 16 | private final Model model; |
19 | 17 | ||
20 | private final ModelUpdateListener updateListener; | 18 | private final ModelUpdateListener updateListener; |
21 | 19 | ||
22 | public RelationalScope(Model model, Set<AnyRelationView> relationViews) { | 20 | public RelationalScope(Model model, Collection<AnyRelationView> relationViews) { |
23 | this.model = model; | 21 | this.model = model; |
24 | this.updateListener = new ModelUpdateListener(relationViews); | 22 | updateListener = new ModelUpdateListener(model, relationViews); |
25 | } | ||
26 | |||
27 | public <D> void processUpdate(Relation<D> relation, Tuple key, D oldValue, D newValue) { | ||
28 | updateListener.addUpdate(relation, key, oldValue, newValue); | ||
29 | } | ||
30 | |||
31 | public boolean hasChanges() { | ||
32 | return updateListener.hasChanges(); | ||
33 | } | ||
34 | |||
35 | public void flush() { | ||
36 | updateListener.flush(); | ||
37 | } | 23 | } |
38 | 24 | ||
39 | @Override | 25 | @Override |
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/ViatraModelQueryAdapterImpl.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/ViatraModelQueryAdapterImpl.java new file mode 100644 index 00000000..3c276935 --- /dev/null +++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/ViatraModelQueryAdapterImpl.java | |||
@@ -0,0 +1,117 @@ | |||
1 | package tools.refinery.store.query.viatra.internal; | ||
2 | |||
3 | import org.eclipse.viatra.query.runtime.api.AdvancedViatraQueryEngine; | ||
4 | import org.eclipse.viatra.query.runtime.api.GenericQueryGroup; | ||
5 | import org.eclipse.viatra.query.runtime.api.IQuerySpecification; | ||
6 | import org.eclipse.viatra.query.runtime.internal.apiimpl.ViatraQueryEngineImpl; | ||
7 | import org.eclipse.viatra.query.runtime.matchers.backend.IQueryBackend; | ||
8 | import org.eclipse.viatra.query.runtime.matchers.backend.IQueryBackendFactory; | ||
9 | import tools.refinery.store.model.Model; | ||
10 | import tools.refinery.store.query.DNF; | ||
11 | import tools.refinery.store.query.ModelQueryAdapter; | ||
12 | import tools.refinery.store.query.ModelQueryStoreAdapter; | ||
13 | import tools.refinery.store.query.ResultSet; | ||
14 | |||
15 | import java.lang.invoke.MethodHandle; | ||
16 | import java.lang.invoke.MethodHandles; | ||
17 | import java.util.*; | ||
18 | |||
19 | public class ViatraModelQueryAdapterImpl implements ModelQueryAdapter { | ||
20 | private static final String DELAY_MESSAGE_DELIVERY_FIELD_NAME = "delayMessageDelivery"; | ||
21 | private static final String QUERY_BACKENDS_FIELD_NAME = "queryBackends"; | ||
22 | |||
23 | private final Model model; | ||
24 | private final ViatraModelQueryStoreAdapterImpl storeAdapter; | ||
25 | private final ViatraQueryEngineImpl queryEngine; | ||
26 | private final MethodHandle setUpdatePropagationDelayedHandle; | ||
27 | private final MethodHandle getQueryBackendsHandle; | ||
28 | private final Map<DNF, ResultSet> resultSets; | ||
29 | |||
30 | ViatraModelQueryAdapterImpl(Model model, ViatraModelQueryStoreAdapterImpl storeAdapter) { | ||
31 | this.model = model; | ||
32 | this.storeAdapter = storeAdapter; | ||
33 | var scope = new RelationalScope(model, storeAdapter.getRelationViews()); | ||
34 | queryEngine = (ViatraQueryEngineImpl) AdvancedViatraQueryEngine.createUnmanagedEngine(scope); | ||
35 | |||
36 | try { | ||
37 | var lookup = MethodHandles.privateLookupIn(ViatraQueryEngineImpl.class, MethodHandles.lookup()); | ||
38 | setUpdatePropagationDelayedHandle = lookup.findSetter(ViatraQueryEngineImpl.class, | ||
39 | DELAY_MESSAGE_DELIVERY_FIELD_NAME, Boolean.TYPE); | ||
40 | getQueryBackendsHandle = lookup.findGetter(ViatraQueryEngineImpl.class, QUERY_BACKENDS_FIELD_NAME, | ||
41 | Map.class); | ||
42 | } catch (IllegalAccessException | NoSuchFieldException e) { | ||
43 | throw new IllegalStateException("Cannot access private members of %s" | ||
44 | .formatted(ViatraQueryEngineImpl.class.getName()), e); | ||
45 | } | ||
46 | |||
47 | var querySpecifications = storeAdapter.getQuerySpecifications(); | ||
48 | GenericQueryGroup.of( | ||
49 | Collections.<IQuerySpecification<?>>unmodifiableCollection(querySpecifications.values()).stream() | ||
50 | ).prepare(queryEngine); | ||
51 | resultSets = new HashMap<>(querySpecifications.size()); | ||
52 | for (var entry : querySpecifications.entrySet()) { | ||
53 | var matcher = queryEngine.getMatcher(entry.getValue()); | ||
54 | resultSets.put(entry.getKey(), matcher); | ||
55 | } | ||
56 | |||
57 | setUpdatePropagationDelayed(true); | ||
58 | } | ||
59 | |||
60 | private void setUpdatePropagationDelayed(boolean value) { | ||
61 | try { | ||
62 | setUpdatePropagationDelayedHandle.invokeExact(queryEngine, value); | ||
63 | } catch (Error e) { | ||
64 | // Fatal JVM errors should not be wrapped. | ||
65 | throw e; | ||
66 | } catch (Throwable e) { | ||
67 | throw new IllegalStateException("Cannot set %s".formatted(DELAY_MESSAGE_DELIVERY_FIELD_NAME), e); | ||
68 | } | ||
69 | } | ||
70 | |||
71 | private Collection<IQueryBackend> getQueryBackends() { | ||
72 | try { | ||
73 | @SuppressWarnings("unchecked") | ||
74 | var backendMap = (Map<IQueryBackendFactory, IQueryBackend>) getQueryBackendsHandle.invokeExact(queryEngine); | ||
75 | return backendMap.values(); | ||
76 | } catch (Error e) { | ||
77 | // Fatal JVM errors should not be wrapped. | ||
78 | throw e; | ||
79 | } catch (Throwable e) { | ||
80 | throw new IllegalStateException("Cannot get %s".formatted(QUERY_BACKENDS_FIELD_NAME), e); | ||
81 | } | ||
82 | } | ||
83 | |||
84 | @Override | ||
85 | public Model getModel() { | ||
86 | return model; | ||
87 | } | ||
88 | |||
89 | @Override | ||
90 | public ModelQueryStoreAdapter getStoreAdapter() { | ||
91 | return storeAdapter; | ||
92 | } | ||
93 | |||
94 | @Override | ||
95 | public ResultSet getResultSet(DNF query) { | ||
96 | var resultSet = resultSets.get(query); | ||
97 | if (resultSet == null) { | ||
98 | throw new IllegalArgumentException("No matcher for query %s in model".formatted(query.name())); | ||
99 | } | ||
100 | return resultSet; | ||
101 | } | ||
102 | |||
103 | @Override | ||
104 | public void flushChanges() { | ||
105 | if (!queryEngine.isUpdatePropagationDelayed()) { | ||
106 | throw new IllegalStateException("Trying to flush changes while changes are already being flushed"); | ||
107 | } | ||
108 | setUpdatePropagationDelayed(false); | ||
109 | try { | ||
110 | for (var queryBackend : getQueryBackends()) { | ||
111 | queryBackend.flushUpdates(); | ||
112 | } | ||
113 | } finally { | ||
114 | setUpdatePropagationDelayed(true); | ||
115 | } | ||
116 | } | ||
117 | } | ||
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/ViatraModelQueryBuilderImpl.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/ViatraModelQueryBuilderImpl.java new file mode 100644 index 00000000..5105c9a7 --- /dev/null +++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/ViatraModelQueryBuilderImpl.java | |||
@@ -0,0 +1,116 @@ | |||
1 | package tools.refinery.store.query.viatra.internal; | ||
2 | |||
3 | import org.eclipse.viatra.query.runtime.api.IQuerySpecification; | ||
4 | import org.eclipse.viatra.query.runtime.api.ViatraQueryEngineOptions; | ||
5 | import org.eclipse.viatra.query.runtime.localsearch.matcher.integration.LocalSearchGenericBackendFactory; | ||
6 | import org.eclipse.viatra.query.runtime.matchers.backend.IQueryBackendFactory; | ||
7 | import org.eclipse.viatra.query.runtime.matchers.backend.QueryEvaluationHint; | ||
8 | import org.eclipse.viatra.query.runtime.rete.matcher.ReteBackendFactory; | ||
9 | import tools.refinery.store.adapter.AbstractModelAdapterBuilder; | ||
10 | import tools.refinery.store.model.ModelStore; | ||
11 | import tools.refinery.store.model.ModelStoreBuilder; | ||
12 | import tools.refinery.store.query.DNF; | ||
13 | import tools.refinery.store.query.viatra.ViatraModelQueryBuilder; | ||
14 | import tools.refinery.store.query.viatra.internal.pquery.DNF2PQuery; | ||
15 | import tools.refinery.store.query.viatra.internal.pquery.RawPatternMatcher; | ||
16 | |||
17 | import java.util.Collections; | ||
18 | import java.util.LinkedHashMap; | ||
19 | import java.util.Map; | ||
20 | import java.util.function.Function; | ||
21 | |||
22 | public class ViatraModelQueryBuilderImpl extends AbstractModelAdapterBuilder implements ViatraModelQueryBuilder { | ||
23 | private ViatraQueryEngineOptions.Builder engineOptionsBuilder; | ||
24 | private final DNF2PQuery dnf2PQuery = new DNF2PQuery(); | ||
25 | private final Map<DNF, IQuerySpecification<RawPatternMatcher>> querySpecifications = new LinkedHashMap<>(); | ||
26 | |||
27 | public ViatraModelQueryBuilderImpl(ModelStoreBuilder storeBuilder) { | ||
28 | super(storeBuilder); | ||
29 | engineOptionsBuilder = new ViatraQueryEngineOptions.Builder() | ||
30 | .withDefaultBackend(ReteBackendFactory.INSTANCE) | ||
31 | .withDefaultCachingBackend(ReteBackendFactory.INSTANCE) | ||
32 | .withDefaultSearchBackend(LocalSearchGenericBackendFactory.INSTANCE); | ||
33 | } | ||
34 | |||
35 | @Override | ||
36 | public ViatraModelQueryBuilder engineOptions(ViatraQueryEngineOptions engineOptions) { | ||
37 | engineOptionsBuilder = new ViatraQueryEngineOptions.Builder(engineOptions); | ||
38 | return this; | ||
39 | } | ||
40 | |||
41 | @Override | ||
42 | public ViatraModelQueryBuilder defaultHint(QueryEvaluationHint queryEvaluationHint) { | ||
43 | engineOptionsBuilder.withDefaultHint(queryEvaluationHint); | ||
44 | return this; | ||
45 | } | ||
46 | |||
47 | @Override | ||
48 | public ViatraModelQueryBuilder backend(IQueryBackendFactory queryBackendFactory) { | ||
49 | engineOptionsBuilder.withDefaultBackend(queryBackendFactory); | ||
50 | return this; | ||
51 | } | ||
52 | |||
53 | @Override | ||
54 | public ViatraModelQueryBuilder cachingBackend(IQueryBackendFactory queryBackendFactory) { | ||
55 | engineOptionsBuilder.withDefaultCachingBackend(queryBackendFactory); | ||
56 | return this; | ||
57 | } | ||
58 | |||
59 | @Override | ||
60 | public ViatraModelQueryBuilder searchBackend(IQueryBackendFactory queryBackendFactory) { | ||
61 | engineOptionsBuilder.withDefaultSearchBackend(queryBackendFactory); | ||
62 | return this; | ||
63 | } | ||
64 | |||
65 | @Override | ||
66 | public ViatraModelQueryBuilder query(DNF query) { | ||
67 | if (querySpecifications.containsKey(query)) { | ||
68 | throw new IllegalArgumentException("%s was already added to the query engine".formatted(query.name())); | ||
69 | } | ||
70 | var pQuery = dnf2PQuery.translate(query); | ||
71 | querySpecifications.put(query, pQuery.build()); | ||
72 | return this; | ||
73 | } | ||
74 | |||
75 | @Override | ||
76 | public ViatraModelQueryBuilder query(DNF query, QueryEvaluationHint queryEvaluationHint) { | ||
77 | query(query); | ||
78 | hint(query, queryEvaluationHint); | ||
79 | return this; | ||
80 | } | ||
81 | |||
82 | @Override | ||
83 | public ViatraModelQueryBuilder computeHint(Function<DNF, QueryEvaluationHint> computeHint) { | ||
84 | dnf2PQuery.setComputeHint(computeHint); | ||
85 | return this; | ||
86 | } | ||
87 | |||
88 | @Override | ||
89 | public ViatraModelQueryBuilder hint(DNF dnf, QueryEvaluationHint queryEvaluationHint) { | ||
90 | var pQuery = dnf2PQuery.getAlreadyTranslated(dnf); | ||
91 | if (pQuery == null) { | ||
92 | throw new IllegalArgumentException( | ||
93 | "Cannot specify hint for %s, because it was not added to the query engine".formatted(dnf.name())); | ||
94 | } | ||
95 | pQuery.setEvaluationHints(queryEvaluationHint); | ||
96 | return this; | ||
97 | } | ||
98 | |||
99 | @Override | ||
100 | public ViatraModelQueryStoreAdapterImpl createStoreAdapter(ModelStore store) { | ||
101 | validateSymbols(store); | ||
102 | return new ViatraModelQueryStoreAdapterImpl(store, engineOptionsBuilder.build(), dnf2PQuery.getRelationViews(), | ||
103 | Collections.unmodifiableMap(querySpecifications)); | ||
104 | } | ||
105 | |||
106 | private void validateSymbols(ModelStore store) { | ||
107 | var symbols = store.getSymbols(); | ||
108 | for (var relationView : dnf2PQuery.getRelationViews()) { | ||
109 | var symbol = relationView.getSymbol(); | ||
110 | if (!symbols.contains(symbol)) { | ||
111 | throw new IllegalArgumentException("Cannot query relation view %s: symbol %s is not in the model" | ||
112 | .formatted(relationView, symbol)); | ||
113 | } | ||
114 | } | ||
115 | } | ||
116 | } | ||
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/ViatraModelQueryStoreAdapterImpl.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/ViatraModelQueryStoreAdapterImpl.java new file mode 100644 index 00000000..d77b7f4b --- /dev/null +++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/ViatraModelQueryStoreAdapterImpl.java | |||
@@ -0,0 +1,58 @@ | |||
1 | package tools.refinery.store.query.viatra.internal; | ||
2 | |||
3 | import org.eclipse.viatra.query.runtime.api.IQuerySpecification; | ||
4 | import org.eclipse.viatra.query.runtime.api.ViatraQueryEngineOptions; | ||
5 | import tools.refinery.store.model.Model; | ||
6 | import tools.refinery.store.model.ModelStore; | ||
7 | import tools.refinery.store.query.DNF; | ||
8 | import tools.refinery.store.query.viatra.ViatraModelQueryStoreAdapter; | ||
9 | import tools.refinery.store.query.viatra.internal.pquery.RawPatternMatcher; | ||
10 | import tools.refinery.store.query.view.AnyRelationView; | ||
11 | |||
12 | import java.util.Collection; | ||
13 | import java.util.Map; | ||
14 | |||
15 | public class ViatraModelQueryStoreAdapterImpl implements ViatraModelQueryStoreAdapter { | ||
16 | private final ModelStore store; | ||
17 | private final ViatraQueryEngineOptions engineOptions; | ||
18 | private final Collection<AnyRelationView> relationViews; | ||
19 | private final Map<DNF, IQuerySpecification<RawPatternMatcher>> querySpecifications; | ||
20 | |||
21 | ViatraModelQueryStoreAdapterImpl(ModelStore store, ViatraQueryEngineOptions engineOptions, | ||
22 | Collection<AnyRelationView> relationViews, | ||
23 | Map<DNF, IQuerySpecification<RawPatternMatcher>> querySpecifications) { | ||
24 | this.store = store; | ||
25 | this.engineOptions = engineOptions; | ||
26 | this.relationViews = relationViews; | ||
27 | this.querySpecifications = querySpecifications; | ||
28 | } | ||
29 | |||
30 | @Override | ||
31 | public ModelStore getStore() { | ||
32 | return store; | ||
33 | } | ||
34 | |||
35 | @Override | ||
36 | public Collection<AnyRelationView> getRelationViews() { | ||
37 | return relationViews; | ||
38 | } | ||
39 | |||
40 | @Override | ||
41 | public Collection<DNF> getQueries() { | ||
42 | return querySpecifications.keySet(); | ||
43 | } | ||
44 | |||
45 | Map<DNF, IQuerySpecification<RawPatternMatcher>> getQuerySpecifications() { | ||
46 | return querySpecifications; | ||
47 | } | ||
48 | |||
49 | @Override | ||
50 | public ViatraQueryEngineOptions getEngineOptions() { | ||
51 | return engineOptions; | ||
52 | } | ||
53 | |||
54 | @Override | ||
55 | public ViatraModelQueryAdapterImpl createModelAdapter(Model model) { | ||
56 | return new ViatraModelQueryAdapterImpl(model, this); | ||
57 | } | ||
58 | } | ||
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 deleted file mode 100644 index 5b06e266..00000000 --- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/ViatraQueryableModel.java +++ /dev/null | |||
@@ -1,222 +0,0 @@ | |||
1 | package tools.refinery.store.query.viatra.internal; | ||
2 | |||
3 | import org.eclipse.viatra.query.runtime.api.AdvancedViatraQueryEngine; | ||
4 | import org.eclipse.viatra.query.runtime.api.GenericQueryGroup; | ||
5 | import org.eclipse.viatra.query.runtime.api.GenericQuerySpecification; | ||
6 | import org.eclipse.viatra.query.runtime.api.IQueryGroup; | ||
7 | import tools.refinery.store.map.Cursor; | ||
8 | import tools.refinery.store.map.DiffCursor; | ||
9 | import tools.refinery.store.model.Model; | ||
10 | import tools.refinery.store.model.ModelDiffCursor; | ||
11 | import tools.refinery.store.model.representation.AnyDataRepresentation; | ||
12 | import tools.refinery.store.model.representation.DataRepresentation; | ||
13 | import tools.refinery.store.model.representation.Relation; | ||
14 | import tools.refinery.store.query.QueryableModel; | ||
15 | import tools.refinery.store.query.QueryableModelStore; | ||
16 | import tools.refinery.store.query.DNF; | ||
17 | import tools.refinery.store.tuple.Tuple; | ||
18 | import tools.refinery.store.tuple.TupleLike; | ||
19 | |||
20 | import java.util.HashMap; | ||
21 | import java.util.Map; | ||
22 | import java.util.Optional; | ||
23 | import java.util.Set; | ||
24 | import java.util.stream.Stream; | ||
25 | |||
26 | public class ViatraQueryableModel implements QueryableModel { | ||
27 | protected final QueryableModelStore store; | ||
28 | |||
29 | protected final Model model; | ||
30 | |||
31 | protected final Map<DNF, GenericQuerySpecification<RawPatternMatcher>> predicates2PQuery; | ||
32 | |||
33 | protected RelationalScope scope; | ||
34 | |||
35 | protected AdvancedViatraQueryEngine engine; | ||
36 | |||
37 | protected Map<DNF, RawPatternMatcher> predicate2Matcher; | ||
38 | |||
39 | public ViatraQueryableModel(QueryableModelStore store, Model model, | ||
40 | Map<DNF, GenericQuerySpecification<RawPatternMatcher>> predicates2PQuery) { | ||
41 | this.store = store; | ||
42 | this.model = model; | ||
43 | this.predicates2PQuery = predicates2PQuery; | ||
44 | initEngine(); | ||
45 | } | ||
46 | |||
47 | private void initEngine() { | ||
48 | this.scope = new RelationalScope(this.model, this.store.getViews()); | ||
49 | this.engine = AdvancedViatraQueryEngine.createUnmanagedEngine(this.scope); | ||
50 | this.predicate2Matcher = initMatchers(this.engine, this.predicates2PQuery); | ||
51 | } | ||
52 | |||
53 | private Map<DNF, RawPatternMatcher> initMatchers( | ||
54 | AdvancedViatraQueryEngine engine, | ||
55 | Map<DNF, GenericQuerySpecification<RawPatternMatcher>> predicates2pQuery) { | ||
56 | // 1. prepare group | ||
57 | IQueryGroup queryGroup = GenericQueryGroup.of(Set.copyOf(predicates2pQuery.values())); | ||
58 | engine.prepareGroup(queryGroup, null); | ||
59 | |||
60 | // 2. then get all matchers | ||
61 | Map<DNF, RawPatternMatcher> result = new HashMap<>(); | ||
62 | for (var entry : predicates2pQuery.entrySet()) { | ||
63 | var matcher = engine.getMatcher(entry.getValue()); | ||
64 | result.put(entry.getKey(), matcher); | ||
65 | } | ||
66 | return result; | ||
67 | } | ||
68 | |||
69 | @Override | ||
70 | public Set<AnyDataRepresentation> getDataRepresentations() { | ||
71 | return model.getDataRepresentations(); | ||
72 | } | ||
73 | |||
74 | @Override | ||
75 | public Set<DNF> getPredicates() { | ||
76 | return store.getPredicates(); | ||
77 | } | ||
78 | |||
79 | @Override | ||
80 | public <K, V> V get(DataRepresentation<K, V> representation, K key) { | ||
81 | return model.get(representation, key); | ||
82 | } | ||
83 | |||
84 | @Override | ||
85 | public <K, V> Cursor<K, V> getAll(DataRepresentation<K, V> representation) { | ||
86 | return model.getAll(representation); | ||
87 | } | ||
88 | |||
89 | @SuppressWarnings("unchecked") | ||
90 | @Override | ||
91 | public <K, V> V put(DataRepresentation<K, V> representation, K key, V value) { | ||
92 | V oldValue = this.model.put(representation, key, value); | ||
93 | if (representation instanceof Relation<?> relation) { | ||
94 | this.scope.processUpdate((Relation<V>) relation, (Tuple) key, oldValue, value); | ||
95 | } | ||
96 | return oldValue; | ||
97 | } | ||
98 | |||
99 | @Override | ||
100 | public <K, V> void putAll(DataRepresentation<K, V> representation, Cursor<K, V> cursor) { | ||
101 | if (representation instanceof Relation<?>) { | ||
102 | //noinspection RedundantSuppression | ||
103 | @SuppressWarnings("unchecked") | ||
104 | Relation<V> relation = (Relation<V>) representation; | ||
105 | while (cursor.move()) { | ||
106 | Tuple key = (Tuple) cursor.getKey(); | ||
107 | V newValue = cursor.getValue(); | ||
108 | V oldValue = this.model.put(relation, key, newValue); | ||
109 | this.scope.processUpdate(relation, key, oldValue, newValue); | ||
110 | } | ||
111 | } else { | ||
112 | this.model.putAll(representation, cursor); | ||
113 | } | ||
114 | } | ||
115 | |||
116 | @Override | ||
117 | public long getSize(AnyDataRepresentation representation) { | ||
118 | return model.getSize(representation); | ||
119 | } | ||
120 | |||
121 | protected RawPatternMatcher getMatcher(DNF predicate) { | ||
122 | var result = this.predicate2Matcher.get(predicate); | ||
123 | if (result == null) { | ||
124 | throw new IllegalArgumentException("Model does not contain predicate %s".formatted(predicate.getName())); | ||
125 | } else | ||
126 | return result; | ||
127 | } | ||
128 | |||
129 | protected void validateParameters(DNF predicate, Tuple parameters) { | ||
130 | int predicateArity = predicate.getParameters().size(); | ||
131 | int parameterArity = parameters.getSize(); | ||
132 | if (parameterArity != predicateArity) { | ||
133 | throw new IllegalArgumentException( | ||
134 | "Predicate %s with %d arity called with different number of parameters (%d)" | ||
135 | .formatted(predicate.getName(), predicateArity, parameterArity)); | ||
136 | } | ||
137 | } | ||
138 | |||
139 | @Override | ||
140 | public boolean hasResult(DNF predicate) { | ||
141 | return getMatcher(predicate).hasResult(); | ||
142 | } | ||
143 | |||
144 | @Override | ||
145 | public boolean hasResult(DNF predicate, Tuple parameters) { | ||
146 | validateParameters(predicate, parameters); | ||
147 | return getMatcher(predicate).hasResult(parameters); | ||
148 | } | ||
149 | |||
150 | @Override | ||
151 | public Optional<TupleLike> oneResult(DNF predicate) { | ||
152 | return getMatcher(predicate).oneResult(); | ||
153 | } | ||
154 | |||
155 | @Override | ||
156 | public Optional<TupleLike> oneResult(DNF predicate, Tuple parameters) { | ||
157 | validateParameters(predicate, parameters); | ||
158 | return getMatcher(predicate).oneResult(parameters); | ||
159 | } | ||
160 | |||
161 | @Override | ||
162 | public Stream<TupleLike> allResults(DNF predicate) { | ||
163 | return getMatcher(predicate).allResults(); | ||
164 | } | ||
165 | |||
166 | @Override | ||
167 | public Stream<TupleLike> allResults(DNF predicate, Tuple parameters) { | ||
168 | validateParameters(predicate, parameters); | ||
169 | return getMatcher(predicate).allResults(parameters); | ||
170 | } | ||
171 | |||
172 | @Override | ||
173 | public int countResults(DNF predicate) { | ||
174 | return getMatcher(predicate).countResults(); | ||
175 | } | ||
176 | |||
177 | @Override | ||
178 | public int countResults(DNF predicate, Tuple parameters) { | ||
179 | validateParameters(predicate, parameters); | ||
180 | return getMatcher(predicate).countResults(parameters); | ||
181 | |||
182 | } | ||
183 | |||
184 | @Override | ||
185 | public boolean hasChanges() { | ||
186 | return scope.hasChanges(); | ||
187 | } | ||
188 | |||
189 | @Override | ||
190 | public void flushChanges() { | ||
191 | this.scope.flush(); | ||
192 | } | ||
193 | |||
194 | @Override | ||
195 | public ModelDiffCursor getDiffCursor(long to) { | ||
196 | return model.getDiffCursor(to); | ||
197 | } | ||
198 | |||
199 | @Override | ||
200 | public long commit() { | ||
201 | return this.model.commit(); | ||
202 | } | ||
203 | |||
204 | @Override | ||
205 | public void restore(long state) { | ||
206 | restoreWithDiffReplay(state); | ||
207 | } | ||
208 | |||
209 | private void restoreWithDiffReplay(long state) { | ||
210 | var modelDiffCursor = getDiffCursor(state); | ||
211 | for (AnyDataRepresentation anyDataRepresentation : this.getDataRepresentations()) { | ||
212 | var dataRepresentation = (DataRepresentation<?, ?>) anyDataRepresentation; | ||
213 | restoreRepresentationWithDiffReplay(modelDiffCursor, dataRepresentation); | ||
214 | } | ||
215 | } | ||
216 | |||
217 | private <K, V> void restoreRepresentationWithDiffReplay(ModelDiffCursor modelDiffCursor, | ||
218 | DataRepresentation<K, V> dataRepresentation) { | ||
219 | DiffCursor<K, V> diffCursor = modelDiffCursor.getCursor(dataRepresentation); | ||
220 | this.putAll(dataRepresentation, diffCursor); | ||
221 | } | ||
222 | } | ||
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/cardinality/UpperCardinalitySumAggregationOperator.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/cardinality/UpperCardinalitySumAggregationOperator.java index ffd5f6de..e0bca9e0 100644 --- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/cardinality/UpperCardinalitySumAggregationOperator.java +++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/cardinality/UpperCardinalitySumAggregationOperator.java | |||
@@ -2,10 +2,10 @@ package tools.refinery.store.query.viatra.internal.cardinality; | |||
2 | 2 | ||
3 | import org.eclipse.viatra.query.runtime.matchers.psystem.aggregations.BoundAggregator; | 3 | import org.eclipse.viatra.query.runtime.matchers.psystem.aggregations.BoundAggregator; |
4 | import org.eclipse.viatra.query.runtime.matchers.psystem.aggregations.IMultisetAggregationOperator; | 4 | import org.eclipse.viatra.query.runtime.matchers.psystem.aggregations.IMultisetAggregationOperator; |
5 | import tools.refinery.store.model.representation.cardinality.FiniteUpperCardinality; | 5 | import tools.refinery.store.representation.cardinality.FiniteUpperCardinality; |
6 | import tools.refinery.store.model.representation.cardinality.UnboundedUpperCardinality; | 6 | import tools.refinery.store.representation.cardinality.UnboundedUpperCardinality; |
7 | import tools.refinery.store.model.representation.cardinality.UpperCardinalities; | 7 | import tools.refinery.store.representation.cardinality.UpperCardinalities; |
8 | import tools.refinery.store.model.representation.cardinality.UpperCardinality; | 8 | import tools.refinery.store.representation.cardinality.UpperCardinality; |
9 | 9 | ||
10 | import java.util.stream.Stream; | 10 | import java.util.stream.Stream; |
11 | 11 | ||
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 d32d49ba..4eb8898b 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 | |||
@@ -5,7 +5,7 @@ import org.eclipse.viatra.query.runtime.api.scope.IEngineContext; | |||
5 | import org.eclipse.viatra.query.runtime.matchers.context.IQueryRuntimeContext; | 5 | import org.eclipse.viatra.query.runtime.matchers.context.IQueryRuntimeContext; |
6 | 6 | ||
7 | import tools.refinery.store.model.Model; | 7 | import tools.refinery.store.model.Model; |
8 | import tools.refinery.store.query.viatra.internal.viewupdate.ModelUpdateListener; | 8 | import tools.refinery.store.query.viatra.internal.update.ModelUpdateListener; |
9 | 9 | ||
10 | public class RelationalEngineContext implements IEngineContext { | 10 | public class RelationalEngineContext implements IEngineContext { |
11 | private final IBaseIndex baseIndex = new DummyBaseIndexer(); | 11 | private final IBaseIndex baseIndex = new DummyBaseIndexer(); |
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 eb3c6fbd..47b83634 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 | |||
@@ -39,7 +39,7 @@ public class RelationalQueryMetaContext extends AbstractQueryMetaContext { | |||
39 | 39 | ||
40 | public void ensureValidKey(IInputKey key) { | 40 | public void ensureValidKey(IInputKey key) { |
41 | if (!(key instanceof RelationViewWrapper)) { | 41 | if (!(key instanceof RelationViewWrapper)) { |
42 | throw new IllegalArgumentException("The input key %s is not a valid input key.".formatted(key)); | 42 | throw new IllegalArgumentException("The input key %s is not a valid input key".formatted(key)); |
43 | } | 43 | } |
44 | } | 44 | } |
45 | } | 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 e01525e0..7375b240 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 | |||
@@ -8,7 +8,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.pquery.RelationViewWrapper; |
11 | import tools.refinery.store.query.viatra.internal.viewupdate.ModelUpdateListener; | 11 | import tools.refinery.store.query.viatra.internal.update.ModelUpdateListener; |
12 | import tools.refinery.store.query.view.AnyRelationView; | 12 | import tools.refinery.store.query.view.AnyRelationView; |
13 | import tools.refinery.store.query.view.RelationView; | 13 | import tools.refinery.store.query.view.RelationView; |
14 | 14 | ||
@@ -48,12 +48,12 @@ public class RelationalRuntimeContext implements IQueryRuntimeContext { | |||
48 | 48 | ||
49 | @Override | 49 | @Override |
50 | public boolean isCoalescing() { | 50 | public boolean isCoalescing() { |
51 | return true; | 51 | return false; |
52 | } | 52 | } |
53 | 53 | ||
54 | @Override | 54 | @Override |
55 | public boolean isIndexed(IInputKey key, IndexingService service) { | 55 | public boolean isIndexed(IInputKey key, IndexingService service) { |
56 | if (key instanceof RelationView<?> relationalKey) { | 56 | if (key instanceof AnyRelationView relationalKey) { |
57 | return this.modelUpdateListener.containsRelationView(relationalKey); | 57 | return this.modelUpdateListener.containsRelationView(relationalKey); |
58 | } else { | 58 | } else { |
59 | return false; | 59 | return false; |
@@ -63,7 +63,7 @@ public class RelationalRuntimeContext implements IQueryRuntimeContext { | |||
63 | @Override | 63 | @Override |
64 | public void ensureIndexed(IInputKey key, IndexingService service) { | 64 | public void ensureIndexed(IInputKey key, IndexingService service) { |
65 | if (!isIndexed(key, service)) { | 65 | if (!isIndexed(key, service)) { |
66 | throw new IllegalStateException("Engine tries to index a new key " + key); | 66 | throw new IllegalStateException("Engine tries to index a new key %s".formatted(key)); |
67 | } | 67 | } |
68 | } | 68 | } |
69 | 69 | ||
@@ -73,7 +73,7 @@ public class RelationalRuntimeContext implements IQueryRuntimeContext { | |||
73 | if (modelUpdateListener.containsRelationView(relationViewKey)) { | 73 | if (modelUpdateListener.containsRelationView(relationViewKey)) { |
74 | return relationViewKey; | 74 | return relationViewKey; |
75 | } else { | 75 | } else { |
76 | throw new IllegalStateException("Query is asking for non-indexed key"); | 76 | throw new IllegalStateException("Query is asking for non-indexed key %s".formatted(relationViewKey)); |
77 | } | 77 | } |
78 | } else { | 78 | } else { |
79 | throw new IllegalStateException("Query is asking for non-relational key"); | 79 | throw new IllegalStateException("Query is asking for non-relational key"); |
@@ -131,7 +131,7 @@ public class RelationalRuntimeContext implements IQueryRuntimeContext { | |||
131 | 131 | ||
132 | @Override | 132 | @Override |
133 | public void addUpdateListener(IInputKey key, Tuple seed, IQueryRuntimeContextListener listener) { | 133 | public void addUpdateListener(IInputKey key, Tuple seed, IQueryRuntimeContextListener listener) { |
134 | var relationViewKey = (RelationView<?>) checkKey(key); | 134 | var relationViewKey = checkKey(key); |
135 | this.modelUpdateListener.addListener(key, relationViewKey, seed, listener); | 135 | this.modelUpdateListener.addListener(key, relationViewKey, seed, listener); |
136 | 136 | ||
137 | } | 137 | } |
@@ -168,7 +168,7 @@ public class RelationalRuntimeContext implements IQueryRuntimeContext { | |||
168 | } | 168 | } |
169 | 169 | ||
170 | @Override | 170 | @Override |
171 | public void executeAfterTraversal(Runnable runnable) throws InvocationTargetException { | 171 | public void executeAfterTraversal(Runnable runnable) { |
172 | runnable.run(); | 172 | runnable.run(); |
173 | } | 173 | } |
174 | } | 174 | } |
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 aa3fba6e..2b5618d2 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 | |||
@@ -1,5 +1,6 @@ | |||
1 | package tools.refinery.store.query.viatra.internal.pquery; | 1 | package tools.refinery.store.query.viatra.internal.pquery; |
2 | 2 | ||
3 | import org.eclipse.viatra.query.runtime.matchers.backend.QueryEvaluationHint; | ||
3 | import org.eclipse.viatra.query.runtime.matchers.psystem.PBody; | 4 | import org.eclipse.viatra.query.runtime.matchers.psystem.PBody; |
4 | import org.eclipse.viatra.query.runtime.matchers.psystem.PVariable; | 5 | import org.eclipse.viatra.query.runtime.matchers.psystem.PVariable; |
5 | import org.eclipse.viatra.query.runtime.matchers.psystem.basicdeferred.Equality; | 6 | import org.eclipse.viatra.query.runtime.matchers.psystem.basicdeferred.Equality; |
@@ -20,20 +21,28 @@ import tools.refinery.store.query.atom.*; | |||
20 | import tools.refinery.store.query.view.AnyRelationView; | 21 | import tools.refinery.store.query.view.AnyRelationView; |
21 | 22 | ||
22 | import java.util.*; | 23 | import java.util.*; |
24 | import java.util.function.Function; | ||
23 | import java.util.stream.Collectors; | 25 | import java.util.stream.Collectors; |
24 | 26 | ||
25 | public class DNF2PQuery { | 27 | public class DNF2PQuery { |
26 | private final Set<DNF> translating = new LinkedHashSet<>(); | 28 | private final Set<DNF> translating = new LinkedHashSet<>(); |
27 | 29 | ||
28 | private final Map<DNF, SimplePQuery> dnf2PQueryMap = new HashMap<>(); | 30 | private final Map<DNF, RawPQuery> dnf2PQueryMap = new HashMap<>(); |
29 | 31 | ||
30 | private final Map<AnyRelationView, RelationViewWrapper> view2WrapperMap = new HashMap<>(); | 32 | private final Map<AnyRelationView, RelationViewWrapper> view2WrapperMap = new LinkedHashMap<>(); |
31 | 33 | ||
32 | public SimplePQuery translate(DNF dnfQuery) { | 34 | private Function<DNF, QueryEvaluationHint> computeHint = dnf -> new QueryEvaluationHint(null, |
35 | QueryEvaluationHint.BackendRequirement.UNSPECIFIED); | ||
36 | |||
37 | public void setComputeHint(Function<DNF, QueryEvaluationHint> computeHint) { | ||
38 | this.computeHint = computeHint; | ||
39 | } | ||
40 | |||
41 | public RawPQuery translate(DNF dnfQuery) { | ||
33 | if (translating.contains(dnfQuery)) { | 42 | if (translating.contains(dnfQuery)) { |
34 | var path = translating.stream().map(DNF::getName).collect(Collectors.joining(" -> ")); | 43 | var path = translating.stream().map(DNF::name).collect(Collectors.joining(" -> ")); |
35 | throw new IllegalStateException("Circular reference %s -> %s detected".formatted(path, | 44 | throw new IllegalStateException("Circular reference %s -> %s detected".formatted(path, |
36 | dnfQuery.getName())); | 45 | dnfQuery.name())); |
37 | } | 46 | } |
38 | // We can't use computeIfAbsent here, because translating referenced queries calls this method in a reentrant | 47 | // We can't use computeIfAbsent here, because translating referenced queries calls this method in a reentrant |
39 | // way, which would cause a ConcurrentModificationException with computeIfAbsent. | 48 | // way, which would cause a ConcurrentModificationException with computeIfAbsent. |
@@ -50,8 +59,17 @@ public class DNF2PQuery { | |||
50 | return pQuery; | 59 | return pQuery; |
51 | } | 60 | } |
52 | 61 | ||
53 | private SimplePQuery doTranslate(DNF dnfQuery) { | 62 | public Collection<AnyRelationView> getRelationViews() { |
54 | var pQuery = new SimplePQuery(dnfQuery.getUniqueName()); | 63 | return Collections.unmodifiableCollection(view2WrapperMap.keySet()); |
64 | } | ||
65 | |||
66 | public RawPQuery getAlreadyTranslated(DNF dnfQuery) { | ||
67 | return dnf2PQueryMap.get(dnfQuery); | ||
68 | } | ||
69 | |||
70 | private RawPQuery doTranslate(DNF dnfQuery) { | ||
71 | var pQuery = new RawPQuery(dnfQuery.getUniqueName()); | ||
72 | pQuery.setEvaluationHints(computeHint.apply(dnfQuery)); | ||
55 | 73 | ||
56 | Map<Variable, PParameter> parameters = new HashMap<>(); | 74 | Map<Variable, PParameter> parameters = new HashMap<>(); |
57 | for (Variable variable : dnfQuery.getParameters()) { | 75 | for (Variable variable : dnfQuery.getParameters()) { |
@@ -86,7 +104,7 @@ public class DNF2PQuery { | |||
86 | translateEquivalenceAtom(equivalenceAtom, body); | 104 | translateEquivalenceAtom(equivalenceAtom, body); |
87 | } else if (constraint instanceof RelationViewAtom relationViewAtom) { | 105 | } else if (constraint instanceof RelationViewAtom relationViewAtom) { |
88 | translateRelationViewAtom(relationViewAtom, body); | 106 | translateRelationViewAtom(relationViewAtom, body); |
89 | } else if (constraint instanceof CallAtom<?> callAtom) { | 107 | } else if (constraint instanceof DNFCallAtom callAtom) { |
90 | translateCallAtom(callAtom, body); | 108 | translateCallAtom(callAtom, body); |
91 | } else if (constraint instanceof ConstantAtom constantAtom) { | 109 | } else if (constraint instanceof ConstantAtom constantAtom) { |
92 | translateConstantAtom(constantAtom, body); | 110 | translateConstantAtom(constantAtom, body); |
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/SimplePQuery.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/RawPQuery.java index a367cbf2..5d0b9e82 100644 --- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/SimplePQuery.java +++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/RawPQuery.java | |||
@@ -3,27 +3,24 @@ package tools.refinery.store.query.viatra.internal.pquery; | |||
3 | import org.eclipse.viatra.query.runtime.api.GenericQuerySpecification; | 3 | import org.eclipse.viatra.query.runtime.api.GenericQuerySpecification; |
4 | import org.eclipse.viatra.query.runtime.api.ViatraQueryEngine; | 4 | import org.eclipse.viatra.query.runtime.api.ViatraQueryEngine; |
5 | import org.eclipse.viatra.query.runtime.api.scope.QueryScope; | 5 | import org.eclipse.viatra.query.runtime.api.scope.QueryScope; |
6 | import org.eclipse.viatra.query.runtime.matchers.backend.QueryEvaluationHint; | ||
7 | import org.eclipse.viatra.query.runtime.matchers.psystem.PBody; | 6 | import org.eclipse.viatra.query.runtime.matchers.psystem.PBody; |
8 | import org.eclipse.viatra.query.runtime.matchers.psystem.queries.BasePQuery; | 7 | import org.eclipse.viatra.query.runtime.matchers.psystem.queries.BasePQuery; |
9 | import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PParameter; | 8 | import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PParameter; |
10 | import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PVisibility; | 9 | import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PVisibility; |
11 | import tools.refinery.store.query.viatra.internal.RawPatternMatcher; | ||
12 | import tools.refinery.store.query.viatra.internal.RelationalScope; | 10 | import tools.refinery.store.query.viatra.internal.RelationalScope; |
13 | 11 | ||
14 | import java.util.LinkedHashSet; | 12 | import java.util.LinkedHashSet; |
15 | import java.util.List; | 13 | import java.util.List; |
16 | import java.util.Set; | 14 | import java.util.Set; |
17 | 15 | ||
18 | public class SimplePQuery extends BasePQuery { | 16 | public class RawPQuery extends BasePQuery { |
19 | private final String fullyQualifiedName; | 17 | private final String fullyQualifiedName; |
20 | private List<PParameter> parameters; | 18 | private List<PParameter> parameters; |
21 | private final LinkedHashSet<PBody> bodies = new LinkedHashSet<>(); | 19 | private final LinkedHashSet<PBody> bodies = new LinkedHashSet<>(); |
22 | 20 | ||
23 | public SimplePQuery(String name) { | 21 | public RawPQuery(String name) { |
24 | super(PVisibility.PUBLIC); | 22 | super(PVisibility.PUBLIC); |
25 | fullyQualifiedName = name; | 23 | fullyQualifiedName = name; |
26 | setEvaluationHints(new QueryEvaluationHint(null, QueryEvaluationHint.BackendRequirement.UNSPECIFIED)); | ||
27 | } | 24 | } |
28 | 25 | ||
29 | @Override | 26 | @Override |
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/RawPatternMatcher.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/RawPatternMatcher.java index 2c488319..e944e873 100644 --- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/RawPatternMatcher.java +++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/RawPatternMatcher.java | |||
@@ -1,7 +1,8 @@ | |||
1 | package tools.refinery.store.query.viatra.internal; | 1 | package tools.refinery.store.query.viatra.internal.pquery; |
2 | 2 | ||
3 | import org.eclipse.viatra.query.runtime.api.GenericPatternMatcher; | 3 | import org.eclipse.viatra.query.runtime.api.GenericPatternMatcher; |
4 | import org.eclipse.viatra.query.runtime.api.GenericQuerySpecification; | 4 | import org.eclipse.viatra.query.runtime.api.GenericQuerySpecification; |
5 | import tools.refinery.store.query.ResultSet; | ||
5 | import tools.refinery.store.query.viatra.ViatraTupleLike; | 6 | import tools.refinery.store.query.viatra.ViatraTupleLike; |
6 | import tools.refinery.store.tuple.Tuple; | 7 | import tools.refinery.store.tuple.Tuple; |
7 | import tools.refinery.store.tuple.TupleLike; | 8 | import tools.refinery.store.tuple.TupleLike; |
@@ -9,7 +10,7 @@ import tools.refinery.store.tuple.TupleLike; | |||
9 | import java.util.Optional; | 10 | import java.util.Optional; |
10 | import java.util.stream.Stream; | 11 | import java.util.stream.Stream; |
11 | 12 | ||
12 | public class RawPatternMatcher extends GenericPatternMatcher { | 13 | public class RawPatternMatcher extends GenericPatternMatcher implements ResultSet { |
13 | protected final Object[] empty; | 14 | protected final Object[] empty; |
14 | 15 | ||
15 | public RawPatternMatcher(GenericQuerySpecification<? extends GenericPatternMatcher> specification) { | 16 | public RawPatternMatcher(GenericQuerySpecification<? extends GenericPatternMatcher> specification) { |
@@ -17,34 +18,42 @@ public class RawPatternMatcher extends GenericPatternMatcher { | |||
17 | empty = new Object[specification.getParameterNames().size()]; | 18 | empty = new Object[specification.getParameterNames().size()]; |
18 | } | 19 | } |
19 | 20 | ||
21 | @Override | ||
20 | public boolean hasResult() { | 22 | public boolean hasResult() { |
21 | return backend.hasMatch(empty); | 23 | return backend.hasMatch(empty); |
22 | } | 24 | } |
23 | 25 | ||
26 | @Override | ||
24 | public boolean hasResult(Tuple parameters) { | 27 | public boolean hasResult(Tuple parameters) { |
25 | return backend.hasMatch(toParametersArray(parameters)); | 28 | return backend.hasMatch(toParametersArray(parameters)); |
26 | } | 29 | } |
27 | 30 | ||
31 | @Override | ||
28 | public Optional<TupleLike> oneResult() { | 32 | public Optional<TupleLike> oneResult() { |
29 | return backend.getOneArbitraryMatch(empty).map(ViatraTupleLike::new); | 33 | return backend.getOneArbitraryMatch(empty).map(ViatraTupleLike::new); |
30 | } | 34 | } |
31 | 35 | ||
36 | @Override | ||
32 | public Optional<TupleLike> oneResult(Tuple parameters) { | 37 | public Optional<TupleLike> oneResult(Tuple parameters) { |
33 | return backend.getOneArbitraryMatch(toParametersArray(parameters)).map(ViatraTupleLike::new); | 38 | return backend.getOneArbitraryMatch(toParametersArray(parameters)).map(ViatraTupleLike::new); |
34 | } | 39 | } |
35 | 40 | ||
41 | @Override | ||
36 | public Stream<TupleLike> allResults() { | 42 | public Stream<TupleLike> allResults() { |
37 | return backend.getAllMatches(empty).map(ViatraTupleLike::new); | 43 | return backend.getAllMatches(empty).map(ViatraTupleLike::new); |
38 | } | 44 | } |
39 | 45 | ||
46 | @Override | ||
40 | public Stream<TupleLike> allResults(Tuple parameters) { | 47 | public Stream<TupleLike> allResults(Tuple parameters) { |
41 | return backend.getAllMatches(toParametersArray(parameters)).map(ViatraTupleLike::new); | 48 | return backend.getAllMatches(toParametersArray(parameters)).map(ViatraTupleLike::new); |
42 | } | 49 | } |
43 | 50 | ||
51 | @Override | ||
44 | public int countResults() { | 52 | public int countResults() { |
45 | return backend.countMatches(empty); | 53 | return backend.countMatches(empty); |
46 | } | 54 | } |
47 | 55 | ||
56 | @Override | ||
48 | public int countResults(Tuple parameters) { | 57 | public int countResults(Tuple parameters) { |
49 | return backend.countMatches(toParametersArray(parameters)); | 58 | return backend.countMatches(toParametersArray(parameters)); |
50 | } | 59 | } |
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 index e48648bf..c442add8 100644 --- 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 | |||
@@ -10,7 +10,7 @@ public class RelationViewWrapper extends BaseInputKeyWrapper<AnyRelationView> { | |||
10 | 10 | ||
11 | @Override | 11 | @Override |
12 | public String getPrettyPrintableName() { | 12 | public String getPrettyPrintableName() { |
13 | return wrappedKey.getName(); | 13 | return wrappedKey.name(); |
14 | } | 14 | } |
15 | 15 | ||
16 | @Override | 16 | @Override |
@@ -20,7 +20,7 @@ public class RelationViewWrapper extends BaseInputKeyWrapper<AnyRelationView> { | |||
20 | 20 | ||
21 | @Override | 21 | @Override |
22 | public int getArity() { | 22 | public int getArity() { |
23 | return wrappedKey.getArity(); | 23 | return wrappedKey.arity(); |
24 | } | 24 | } |
25 | 25 | ||
26 | @Override | 26 | @Override |
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/update/ModelUpdateListener.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/update/ModelUpdateListener.java new file mode 100644 index 00000000..1ae3daa7 --- /dev/null +++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/update/ModelUpdateListener.java | |||
@@ -0,0 +1,46 @@ | |||
1 | package tools.refinery.store.query.viatra.internal.update; | ||
2 | |||
3 | import org.eclipse.viatra.query.runtime.matchers.context.IInputKey; | ||
4 | import org.eclipse.viatra.query.runtime.matchers.context.IQueryRuntimeContextListener; | ||
5 | import org.eclipse.viatra.query.runtime.matchers.tuple.ITuple; | ||
6 | import tools.refinery.store.model.Model; | ||
7 | import tools.refinery.store.query.view.AnyRelationView; | ||
8 | import tools.refinery.store.query.view.RelationView; | ||
9 | |||
10 | import java.util.Collection; | ||
11 | import java.util.HashMap; | ||
12 | import java.util.Map; | ||
13 | |||
14 | public class ModelUpdateListener { | ||
15 | private final Map<AnyRelationView, RelationViewUpdateListener<?>> relationViewUpdateListeners; | ||
16 | |||
17 | public ModelUpdateListener(Model model, Collection<AnyRelationView> relationViews) { | ||
18 | relationViewUpdateListeners = new HashMap<>(relationViews.size()); | ||
19 | for (var relationView : relationViews) { | ||
20 | registerView(model, (RelationView<?>) relationView); | ||
21 | } | ||
22 | } | ||
23 | |||
24 | private <T> void registerView(Model model, RelationView<T> relationView) { | ||
25 | var listener = RelationViewUpdateListener.of(relationView); | ||
26 | var interpretation = model.getInterpretation(relationView.getSymbol()); | ||
27 | interpretation.addListener(listener, true); | ||
28 | relationViewUpdateListeners.put(relationView, listener); | ||
29 | } | ||
30 | |||
31 | public boolean containsRelationView(AnyRelationView relationView) { | ||
32 | return relationViewUpdateListeners.containsKey(relationView); | ||
33 | } | ||
34 | |||
35 | public void addListener(IInputKey key, AnyRelationView relationView, ITuple seed, | ||
36 | IQueryRuntimeContextListener listener) { | ||
37 | var relationViewUpdateListener = relationViewUpdateListeners.get(relationView); | ||
38 | relationViewUpdateListener.addFilter(key, seed, listener); | ||
39 | } | ||
40 | |||
41 | public void removeListener(IInputKey key, AnyRelationView relationView, ITuple seed, | ||
42 | IQueryRuntimeContextListener listener) { | ||
43 | var relationViewUpdateListener = relationViewUpdateListeners.get(relationView); | ||
44 | relationViewUpdateListener.removeFilter(key, seed, listener); | ||
45 | } | ||
46 | } | ||
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/update/RelationViewFilter.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/update/RelationViewFilter.java new file mode 100644 index 00000000..221f1b4a --- /dev/null +++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/update/RelationViewFilter.java | |||
@@ -0,0 +1,66 @@ | |||
1 | package tools.refinery.store.query.viatra.internal.update; | ||
2 | |||
3 | import org.eclipse.viatra.query.runtime.matchers.context.IInputKey; | ||
4 | import org.eclipse.viatra.query.runtime.matchers.context.IQueryRuntimeContextListener; | ||
5 | import org.eclipse.viatra.query.runtime.matchers.tuple.ITuple; | ||
6 | import org.eclipse.viatra.query.runtime.matchers.tuple.Tuple; | ||
7 | |||
8 | import java.util.Arrays; | ||
9 | import java.util.Objects; | ||
10 | |||
11 | public final class RelationViewFilter { | ||
12 | private final IInputKey inputKey; | ||
13 | private final Object[] seed; | ||
14 | private final IQueryRuntimeContextListener listener; | ||
15 | |||
16 | public RelationViewFilter(IInputKey inputKey, ITuple seed, IQueryRuntimeContextListener listener) { | ||
17 | this.inputKey = inputKey; | ||
18 | this.seed = seedToArray(seed); | ||
19 | this.listener = listener; | ||
20 | } | ||
21 | |||
22 | public void update(Tuple updateTuple, boolean isInsertion) { | ||
23 | if (isMatching(updateTuple)) { | ||
24 | listener.update(inputKey, updateTuple, isInsertion); | ||
25 | } | ||
26 | } | ||
27 | |||
28 | private boolean isMatching(ITuple tuple) { | ||
29 | if (seed == null) { | ||
30 | return true; | ||
31 | } | ||
32 | int size = seed.length; | ||
33 | for (int i = 0; i < size; i++) { | ||
34 | var filterElement = seed[i]; | ||
35 | if (filterElement != null && !filterElement.equals(tuple.get(i))) { | ||
36 | return false; | ||
37 | } | ||
38 | } | ||
39 | return true; | ||
40 | } | ||
41 | |||
42 | // Use <code>null</code> instead of an empty array to speed up comparisons. | ||
43 | @SuppressWarnings("squid:S1168") | ||
44 | private static Object[] seedToArray(ITuple seed) { | ||
45 | for (var element : seed.getElements()) { | ||
46 | if (element != null) { | ||
47 | return seed.getElements(); | ||
48 | } | ||
49 | } | ||
50 | return null; | ||
51 | } | ||
52 | |||
53 | @Override | ||
54 | public boolean equals(Object obj) { | ||
55 | if (obj == this) return true; | ||
56 | if (obj == null || obj.getClass() != this.getClass()) return false; | ||
57 | var that = (RelationViewFilter) obj; | ||
58 | return Objects.equals(this.inputKey, that.inputKey) && Arrays.equals(this.seed, that.seed) && | ||
59 | Objects.equals(this.listener, that.listener); | ||
60 | } | ||
61 | |||
62 | @Override | ||
63 | public int hashCode() { | ||
64 | return Objects.hash(inputKey, Arrays.hashCode(seed), listener); | ||
65 | } | ||
66 | } | ||
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/update/RelationViewUpdateListener.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/update/RelationViewUpdateListener.java new file mode 100644 index 00000000..e0d44e34 --- /dev/null +++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/update/RelationViewUpdateListener.java | |||
@@ -0,0 +1,40 @@ | |||
1 | package tools.refinery.store.query.viatra.internal.update; | ||
2 | |||
3 | import org.eclipse.viatra.query.runtime.matchers.context.IInputKey; | ||
4 | import org.eclipse.viatra.query.runtime.matchers.context.IQueryRuntimeContextListener; | ||
5 | import org.eclipse.viatra.query.runtime.matchers.tuple.ITuple; | ||
6 | import org.eclipse.viatra.query.runtime.matchers.tuple.Tuple; | ||
7 | import tools.refinery.store.model.InterpretationListener; | ||
8 | import tools.refinery.store.query.view.RelationView; | ||
9 | import tools.refinery.store.query.view.TuplePreservingRelationView; | ||
10 | |||
11 | import java.util.ArrayList; | ||
12 | import java.util.List; | ||
13 | |||
14 | public abstract class RelationViewUpdateListener<T> implements InterpretationListener<T> { | ||
15 | private final List<RelationViewFilter> filters = new ArrayList<>(); | ||
16 | |||
17 | public void addFilter(IInputKey inputKey, ITuple seed, IQueryRuntimeContextListener listener) { | ||
18 | filters.add(new RelationViewFilter(inputKey, seed, listener)); | ||
19 | } | ||
20 | |||
21 | public void removeFilter(IInputKey inputKey, ITuple seed, IQueryRuntimeContextListener listener) { | ||
22 | filters.remove(new RelationViewFilter(inputKey, seed, listener)); | ||
23 | } | ||
24 | |||
25 | protected void processUpdate(Tuple tuple, boolean isInsertion) { | ||
26 | int size = filters.size(); | ||
27 | // Use a for loop instead of a for-each loop to avoid <code>Iterator</code> allocation overhead. | ||
28 | //noinspection ForLoopReplaceableByForEach | ||
29 | for (int i = 0; i < size; i++) { | ||
30 | filters.get(i).update(tuple, isInsertion); | ||
31 | } | ||
32 | } | ||
33 | |||
34 | public static <T> RelationViewUpdateListener<T> of(RelationView<T> relationView) { | ||
35 | if (relationView instanceof TuplePreservingRelationView<T> tuplePreservingRelationView) { | ||
36 | return new TuplePreservingRelationViewUpdateListener<>(tuplePreservingRelationView); | ||
37 | } | ||
38 | return new TupleChangingRelationViewUpdateListener<>(relationView); | ||
39 | } | ||
40 | } | ||
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/update/TupleChangingRelationViewUpdateListener.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/update/TupleChangingRelationViewUpdateListener.java new file mode 100644 index 00000000..c17e826d --- /dev/null +++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/update/TupleChangingRelationViewUpdateListener.java | |||
@@ -0,0 +1,35 @@ | |||
1 | package tools.refinery.store.query.viatra.internal.update; | ||
2 | |||
3 | import org.eclipse.viatra.query.runtime.matchers.tuple.Tuples; | ||
4 | import tools.refinery.store.query.view.RelationView; | ||
5 | import tools.refinery.store.tuple.Tuple; | ||
6 | |||
7 | import java.util.Arrays; | ||
8 | |||
9 | public class TupleChangingRelationViewUpdateListener<T> extends RelationViewUpdateListener<T> { | ||
10 | private final RelationView<T> relationView; | ||
11 | |||
12 | TupleChangingRelationViewUpdateListener(RelationView<T> relationView) { | ||
13 | this.relationView = relationView; | ||
14 | } | ||
15 | |||
16 | @Override | ||
17 | public void put(Tuple key, T fromValue, T toValue, boolean restoring) { | ||
18 | boolean fromPresent = relationView.filter(key, fromValue); | ||
19 | boolean toPresent = relationView.filter(key, toValue); | ||
20 | if (fromPresent) { | ||
21 | if (toPresent) { // value change | ||
22 | var fromArray = relationView.forwardMap(key, fromValue); | ||
23 | var toArray = relationView.forwardMap(key, toValue); | ||
24 | if (!Arrays.equals(fromArray, toArray)) { | ||
25 | processUpdate(Tuples.flatTupleOf(fromArray), false); | ||
26 | processUpdate(Tuples.flatTupleOf(toArray), true); | ||
27 | } | ||
28 | } else { // fromValue disappears | ||
29 | processUpdate(Tuples.flatTupleOf(relationView.forwardMap(key, fromValue)), false); | ||
30 | } | ||
31 | } else if (toPresent) { // toValue disappears | ||
32 | processUpdate(Tuples.flatTupleOf(relationView.forwardMap(key, toValue)), true); | ||
33 | } | ||
34 | } | ||
35 | } | ||
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/update/TuplePreservingRelationViewUpdateListener.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/update/TuplePreservingRelationViewUpdateListener.java new file mode 100644 index 00000000..9c3ef61c --- /dev/null +++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/update/TuplePreservingRelationViewUpdateListener.java | |||
@@ -0,0 +1,24 @@ | |||
1 | package tools.refinery.store.query.viatra.internal.update; | ||
2 | |||
3 | import org.eclipse.viatra.query.runtime.matchers.tuple.Tuples; | ||
4 | import tools.refinery.store.query.view.TuplePreservingRelationView; | ||
5 | import tools.refinery.store.tuple.Tuple; | ||
6 | |||
7 | public class TuplePreservingRelationViewUpdateListener<T> extends RelationViewUpdateListener<T> { | ||
8 | private final TuplePreservingRelationView<T> view; | ||
9 | |||
10 | TuplePreservingRelationViewUpdateListener(TuplePreservingRelationView<T> view) { | ||
11 | this.view = view; | ||
12 | } | ||
13 | |||
14 | @Override | ||
15 | public void put(Tuple key, T fromValue, T toValue, boolean restoring) { | ||
16 | boolean fromPresent = view.filter(key, fromValue); | ||
17 | boolean toPresent = view.filter(key, toValue); | ||
18 | if (fromPresent == toPresent) { | ||
19 | return; | ||
20 | } | ||
21 | var translated = Tuples.flatTupleOf(view.forwardMap(key)); | ||
22 | processUpdate(translated, toPresent); | ||
23 | } | ||
24 | } | ||
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 deleted file mode 100644 index 6a1d06a9..00000000 --- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/viewupdate/ModelUpdateListener.java +++ /dev/null | |||
@@ -1,112 +0,0 @@ | |||
1 | package tools.refinery.store.query.viatra.internal.viewupdate; | ||
2 | |||
3 | import org.eclipse.viatra.query.runtime.matchers.context.IInputKey; | ||
4 | import org.eclipse.viatra.query.runtime.matchers.context.IQueryRuntimeContextListener; | ||
5 | import org.eclipse.viatra.query.runtime.matchers.tuple.ITuple; | ||
6 | import tools.refinery.store.model.representation.AnyRelation; | ||
7 | import tools.refinery.store.query.view.AnyRelationView; | ||
8 | import tools.refinery.store.tuple.Tuple; | ||
9 | import tools.refinery.store.model.representation.Relation; | ||
10 | import tools.refinery.store.query.view.RelationView; | ||
11 | |||
12 | import java.util.HashMap; | ||
13 | import java.util.HashSet; | ||
14 | import java.util.Map; | ||
15 | import java.util.Set; | ||
16 | |||
17 | public class ModelUpdateListener { | ||
18 | /** | ||
19 | * Collections of Relations and their Views. | ||
20 | */ | ||
21 | private final Map<AnyRelation, Set<AnyRelationView>> relation2View; | ||
22 | |||
23 | /** | ||
24 | * Collection of Views and their buffers. | ||
25 | */ | ||
26 | private final Map<AnyRelationView, Set<ViewUpdateBuffer<?>>> view2Buffers; | ||
27 | |||
28 | public ModelUpdateListener(Set<AnyRelationView> relationViews) { | ||
29 | this.relation2View = new HashMap<>(); | ||
30 | this.view2Buffers = new HashMap<>(); | ||
31 | |||
32 | for (var relationView : relationViews) { | ||
33 | registerView(relationView); | ||
34 | } | ||
35 | } | ||
36 | |||
37 | private void registerView(AnyRelationView view) { | ||
38 | AnyRelation relation = view.getRepresentation(); | ||
39 | |||
40 | // 1. register views to relations, if necessary | ||
41 | var views = relation2View.computeIfAbsent(relation, x -> new HashSet<>()); | ||
42 | views.add(view); | ||
43 | |||
44 | // 2. register notifier map to views, if necessary | ||
45 | view2Buffers.computeIfAbsent(view, x -> new HashSet<>()); | ||
46 | } | ||
47 | |||
48 | public boolean containsRelationView(AnyRelationView relationalKey) { | ||
49 | return view2Buffers.containsKey(relationalKey); | ||
50 | } | ||
51 | |||
52 | public <D> void addListener(IInputKey key, RelationView<D> relationView, ITuple seed, | ||
53 | IQueryRuntimeContextListener listener) { | ||
54 | if (view2Buffers.containsKey(relationView)) { | ||
55 | ViewUpdateTranslator<D> updateListener = new ViewUpdateTranslator<>(key, relationView, seed, listener); | ||
56 | ViewUpdateBuffer<D> updateBuffer = new ViewUpdateBuffer<>(updateListener); | ||
57 | view2Buffers.get(relationView).add(updateBuffer); | ||
58 | } else { | ||
59 | throw new IllegalArgumentException(); | ||
60 | } | ||
61 | } | ||
62 | |||
63 | public void removeListener(IInputKey key, AnyRelationView relationView, ITuple seed, | ||
64 | IQueryRuntimeContextListener listener) { | ||
65 | if (view2Buffers.containsKey(relationView)) { | ||
66 | Set<ViewUpdateBuffer<?>> buffers = this.view2Buffers.get(relationView); | ||
67 | for (var buffer : buffers) { | ||
68 | if (buffer.getUpdateListener().equals(key, relationView, seed, listener)) { | ||
69 | // remove buffer and terminate immediately, or it will break iterator. | ||
70 | buffers.remove(buffer); | ||
71 | return; | ||
72 | } | ||
73 | } | ||
74 | } else { | ||
75 | throw new IllegalArgumentException("Relation view is not registered for updates"); | ||
76 | } | ||
77 | } | ||
78 | |||
79 | public <D> void addUpdate(Relation<D> relation, Tuple key, D oldValue, D newValue) { | ||
80 | var views = this.relation2View.get(relation); | ||
81 | if (views == null) { | ||
82 | return; | ||
83 | } | ||
84 | for (var view : views) { | ||
85 | var buffers = this.view2Buffers.get(view); | ||
86 | for (var buffer : buffers) { | ||
87 | @SuppressWarnings("unchecked") | ||
88 | var typedBuffer = (ViewUpdateBuffer<D>) buffer; | ||
89 | typedBuffer.addChange(key, oldValue, newValue); | ||
90 | } | ||
91 | } | ||
92 | } | ||
93 | |||
94 | public boolean hasChanges() { | ||
95 | for (var bufferCollection : this.view2Buffers.values()) { | ||
96 | for (ViewUpdateBuffer<?> buffer : bufferCollection) { | ||
97 | if (buffer.hasChanges()) { | ||
98 | return true; | ||
99 | } | ||
100 | } | ||
101 | } | ||
102 | return false; | ||
103 | } | ||
104 | |||
105 | public void flush() { | ||
106 | for (var bufferCollection : this.view2Buffers.values()) { | ||
107 | for (ViewUpdateBuffer<?> buffer : bufferCollection) { | ||
108 | buffer.flush(); | ||
109 | } | ||
110 | } | ||
111 | } | ||
112 | } | ||
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 deleted file mode 100644 index b9406018..00000000 --- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/viewupdate/ViewUpdate.java +++ /dev/null | |||
@@ -1,32 +0,0 @@ | |||
1 | package tools.refinery.store.query.viatra.internal.viewupdate; | ||
2 | |||
3 | import java.util.Arrays; | ||
4 | import java.util.Objects; | ||
5 | |||
6 | record ViewUpdate(Object[] tuple, boolean isInsertion) { | ||
7 | @Override | ||
8 | public int hashCode() { | ||
9 | final int prime = 31; | ||
10 | int result = 1; | ||
11 | result = prime * result + Arrays.deepHashCode(tuple); | ||
12 | result = prime * result + Objects.hash(isInsertion); | ||
13 | return result; | ||
14 | } | ||
15 | |||
16 | @Override | ||
17 | public boolean equals(Object obj) { | ||
18 | if (this == obj) | ||
19 | return true; | ||
20 | if (obj == null) | ||
21 | return false; | ||
22 | if (getClass() != obj.getClass()) | ||
23 | return false; | ||
24 | ViewUpdate other = (ViewUpdate) obj; | ||
25 | return isInsertion == other.isInsertion && Arrays.deepEquals(tuple, other.tuple); | ||
26 | } | ||
27 | |||
28 | @Override | ||
29 | public String toString() { | ||
30 | return "ViewUpdate [" + Arrays.toString(tuple) + "insertion= " + this.isInsertion + "]"; | ||
31 | } | ||
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 deleted file mode 100644 index 49f4c501..00000000 --- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/viewupdate/ViewUpdateBuffer.java +++ /dev/null | |||
@@ -1,47 +0,0 @@ | |||
1 | package tools.refinery.store.query.viatra.internal.viewupdate; | ||
2 | |||
3 | import tools.refinery.store.tuple.Tuple; | ||
4 | |||
5 | import java.util.ArrayList; | ||
6 | import java.util.Arrays; | ||
7 | import java.util.List; | ||
8 | |||
9 | public class ViewUpdateBuffer<D> { | ||
10 | protected final ViewUpdateTranslator<D> updateListener; | ||
11 | |||
12 | protected final List<ViewUpdate> buffer = new ArrayList<>(); | ||
13 | |||
14 | public ViewUpdateBuffer(ViewUpdateTranslator<D> updateListener) { | ||
15 | this.updateListener = updateListener; | ||
16 | } | ||
17 | |||
18 | public ViewUpdateTranslator<D> getUpdateListener() { | ||
19 | return updateListener; | ||
20 | } | ||
21 | |||
22 | public boolean hasChanges() { | ||
23 | return !buffer.isEmpty(); | ||
24 | } | ||
25 | |||
26 | public void addChange(Tuple tuple, D oldValue, D newValue) { | ||
27 | if (oldValue != newValue) { | ||
28 | Object[] oldTuple = updateListener.isMatching(tuple, oldValue); | ||
29 | Object[] newTuple = updateListener.isMatching(tuple, newValue); | ||
30 | if (!Arrays.equals(oldTuple, newTuple)) { | ||
31 | if (oldTuple != null) { | ||
32 | buffer.add(new ViewUpdate(oldTuple, false)); | ||
33 | } | ||
34 | if (newTuple != null) { | ||
35 | buffer.add(new ViewUpdate(newTuple, true)); | ||
36 | } | ||
37 | } | ||
38 | } | ||
39 | } | ||
40 | |||
41 | public void flush() { | ||
42 | for (ViewUpdate viewChange : buffer) { | ||
43 | updateListener.processChange(viewChange); | ||
44 | } | ||
45 | buffer.clear(); | ||
46 | } | ||
47 | } | ||
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 deleted file mode 100644 index c324c84a..00000000 --- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/viewupdate/ViewUpdateTranslator.java +++ /dev/null | |||
@@ -1,73 +0,0 @@ | |||
1 | package tools.refinery.store.query.viatra.internal.viewupdate; | ||
2 | |||
3 | import org.eclipse.viatra.query.runtime.matchers.context.IInputKey; | ||
4 | import org.eclipse.viatra.query.runtime.matchers.context.IQueryRuntimeContextListener; | ||
5 | import org.eclipse.viatra.query.runtime.matchers.tuple.ITuple; | ||
6 | import org.eclipse.viatra.query.runtime.matchers.tuple.Tuples; | ||
7 | import tools.refinery.store.query.view.AnyRelationView; | ||
8 | import tools.refinery.store.query.view.RelationView; | ||
9 | import tools.refinery.store.tuple.Tuple; | ||
10 | |||
11 | import java.util.Objects; | ||
12 | |||
13 | public class ViewUpdateTranslator<D> { | ||
14 | private final IInputKey wrappedKey; | ||
15 | |||
16 | private final RelationView<D> key; | ||
17 | |||
18 | private final ITuple filter; | ||
19 | |||
20 | private final IQueryRuntimeContextListener listener; | ||
21 | |||
22 | public ViewUpdateTranslator(IInputKey wrappedKey, RelationView<D> key, ITuple filter, | ||
23 | IQueryRuntimeContextListener listener) { | ||
24 | super(); | ||
25 | this.wrappedKey = wrappedKey; | ||
26 | this.key = key; | ||
27 | this.filter = filter; | ||
28 | this.listener = listener; | ||
29 | } | ||
30 | |||
31 | public boolean equals(IInputKey wrappedKey, AnyRelationView relationView, ITuple seed, | ||
32 | IQueryRuntimeContextListener listener) { | ||
33 | return this.wrappedKey == wrappedKey && key == relationView && filter.equals(seed) && this.listener == listener; | ||
34 | } | ||
35 | |||
36 | public void processChange(ViewUpdate change) { | ||
37 | listener.update(wrappedKey, Tuples.flatTupleOf(change.tuple()), change.isInsertion()); | ||
38 | } | ||
39 | |||
40 | @SuppressWarnings("squid:S1168") | ||
41 | public Object[] isMatching(Tuple tuple, D value) { | ||
42 | if (!key.filter(tuple, value)) { | ||
43 | return null; | ||
44 | } | ||
45 | return isMatching(key.forwardMap(tuple, value), filter); | ||
46 | } | ||
47 | |||
48 | @SuppressWarnings("squid:S1168") | ||
49 | private Object[] isMatching(Object[] tuple, ITuple filter) { | ||
50 | for (int i = 0; i < filter.getSize(); i++) { | ||
51 | final Object filterObject = filter.get(i); | ||
52 | if (filterObject != null && !filterObject.equals(tuple[i])) { | ||
53 | return null; | ||
54 | } | ||
55 | } | ||
56 | return tuple; | ||
57 | } | ||
58 | |||
59 | @Override | ||
60 | public int hashCode() { | ||
61 | return Objects.hash(filter, key, listener); | ||
62 | } | ||
63 | |||
64 | @Override | ||
65 | public boolean equals(Object obj) { | ||
66 | if (this == obj) | ||
67 | return true; | ||
68 | if (!(obj instanceof ViewUpdateTranslator<?> other)) | ||
69 | return false; | ||
70 | return Objects.equals(filter, other.filter) && Objects.equals(key, other.key) | ||
71 | && Objects.equals(listener, other.listener); | ||
72 | } | ||
73 | } | ||
diff --git a/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/QueryTest.java b/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/QueryTest.java index e82e006c..72e8d7e5 100644 --- a/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/QueryTest.java +++ b/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/QueryTest.java | |||
@@ -1,17 +1,20 @@ | |||
1 | package tools.refinery.store.query.viatra; | 1 | package tools.refinery.store.query.viatra; |
2 | 2 | ||
3 | import org.junit.jupiter.api.Test; | 3 | import org.junit.jupiter.api.Test; |
4 | import tools.refinery.store.model.representation.Relation; | 4 | import tools.refinery.store.model.ModelStore; |
5 | import tools.refinery.store.model.representation.TruthValue; | 5 | import tools.refinery.store.query.DNF; |
6 | import tools.refinery.store.query.*; | 6 | import tools.refinery.store.query.ModelQuery; |
7 | import tools.refinery.store.query.Variable; | ||
7 | import tools.refinery.store.query.atom.*; | 8 | import tools.refinery.store.query.atom.*; |
8 | import tools.refinery.store.query.view.FilteredRelationView; | 9 | import tools.refinery.store.query.view.FilteredRelationView; |
9 | import tools.refinery.store.query.view.KeyOnlyRelationView; | 10 | import tools.refinery.store.query.view.KeyOnlyRelationView; |
10 | import tools.refinery.store.query.view.RelationView; | 11 | import tools.refinery.store.representation.Symbol; |
12 | import tools.refinery.store.representation.TruthValue; | ||
11 | import tools.refinery.store.tuple.Tuple; | 13 | import tools.refinery.store.tuple.Tuple; |
12 | import tools.refinery.store.tuple.TupleLike; | 14 | import tools.refinery.store.tuple.TupleLike; |
13 | 15 | ||
14 | import java.util.*; | 16 | import java.util.HashSet; |
17 | import java.util.Set; | ||
15 | import java.util.stream.Stream; | 18 | import java.util.stream.Stream; |
16 | 19 | ||
17 | import static org.junit.jupiter.api.Assertions.assertEquals; | 20 | import static org.junit.jupiter.api.Assertions.assertEquals; |
@@ -19,41 +22,49 @@ import static org.junit.jupiter.api.Assertions.assertEquals; | |||
19 | class QueryTest { | 22 | class QueryTest { |
20 | @Test | 23 | @Test |
21 | void typeConstraintTest() { | 24 | void typeConstraintTest() { |
22 | Relation<Boolean> person = new Relation<>("Person", 1, Boolean.class, false); | 25 | var person = new Symbol<>("Person", 1, Boolean.class, false); |
23 | Relation<Boolean> asset = new Relation<>("Asset", 1, Boolean.class, false); | 26 | var asset = new Symbol<>("Asset", 1, Boolean.class, false); |
24 | RelationView<Boolean> personView = new KeyOnlyRelationView(person); | 27 | var personView = new KeyOnlyRelationView<>(person); |
25 | 28 | ||
26 | var p1 = new Variable("p1"); | 29 | var p1 = new Variable("p1"); |
27 | DNF predicate = DNF.builder("TypeConstraint") | 30 | var predicate = DNF.builder("TypeConstraint") |
28 | .parameters(p1) | 31 | .parameters(p1) |
29 | .clause(new RelationViewAtom(personView, p1)) | 32 | .clause(new RelationViewAtom(personView, p1)) |
30 | .build(); | 33 | .build(); |
31 | 34 | ||
32 | QueryableModelStore store = new ViatraQueryableModelStore(Set.of(person, asset), Set.of(personView), | 35 | var store = ModelStore.builder() |
33 | Set.of(predicate)); | 36 | .symbols(person, asset) |
34 | QueryableModel model = store.createModel(); | 37 | .with(ViatraModelQuery.ADAPTER) |
38 | .queries(predicate) | ||
39 | .build(); | ||
40 | |||
41 | var model = store.createModel(); | ||
42 | var personInterpretation = model.getInterpretation(person); | ||
43 | var assetInterpretation = model.getInterpretation(asset); | ||
44 | var queryEngine = model.getAdapter(ModelQuery.ADAPTER); | ||
45 | var predicateResultSet = queryEngine.getResultSet(predicate); | ||
35 | 46 | ||
36 | model.put(person, Tuple.of(0), true); | 47 | personInterpretation.put(Tuple.of(0), true); |
37 | model.put(person, Tuple.of(1), true); | 48 | personInterpretation.put(Tuple.of(1), true); |
38 | model.put(asset, Tuple.of(1), true); | ||
39 | model.put(asset, Tuple.of(2), true); | ||
40 | 49 | ||
41 | model.flushChanges(); | 50 | assetInterpretation.put(Tuple.of(1), true); |
42 | assertEquals(2, model.countResults(predicate)); | 51 | assetInterpretation.put(Tuple.of(2), true); |
43 | compareMatchSets(model.allResults(predicate), Set.of(Tuple.of(0), Tuple.of(1))); | 52 | |
53 | queryEngine.flushChanges(); | ||
54 | assertEquals(2, predicateResultSet.countResults()); | ||
55 | compareMatchSets(predicateResultSet.allResults(), Set.of(Tuple.of(0), Tuple.of(1))); | ||
44 | } | 56 | } |
45 | 57 | ||
46 | @Test | 58 | @Test |
47 | void relationConstraintTest() { | 59 | void relationConstraintTest() { |
48 | Relation<Boolean> person = new Relation<>("Person", 1, Boolean.class, false); | 60 | var person = new Symbol<>("Person", 1, Boolean.class, false); |
49 | Relation<TruthValue> friend = new Relation<>("friend", 2, TruthValue.class, TruthValue.FALSE); | 61 | var friend = new Symbol<>("friend", 2, TruthValue.class, TruthValue.FALSE); |
50 | RelationView<Boolean> personView = new KeyOnlyRelationView(person); | 62 | var personView = new KeyOnlyRelationView<>(person); |
51 | RelationView<TruthValue> friendMustView = new FilteredRelationView<>(friend, "must", | 63 | var friendMustView = new FilteredRelationView<>(friend, "must", TruthValue::must); |
52 | TruthValue::must); | 64 | |
53 | 65 | var p1 = new Variable("p1"); | |
54 | Variable p1 = new Variable("p1"); | 66 | var p2 = new Variable("p2"); |
55 | Variable p2 = new Variable("p2"); | 67 | var predicate = DNF.builder("RelationConstraint") |
56 | DNF predicate = DNF.builder("RelationConstraint") | ||
57 | .parameters(p1, p2) | 68 | .parameters(p1, p2) |
58 | .clause( | 69 | .clause( |
59 | new RelationViewAtom(personView, p1), | 70 | new RelationViewAtom(personView, p1), |
@@ -62,37 +73,45 @@ class QueryTest { | |||
62 | ) | 73 | ) |
63 | .build(); | 74 | .build(); |
64 | 75 | ||
65 | QueryableModelStore store = new ViatraQueryableModelStore(Set.of(person, friend), | 76 | var store = ModelStore.builder() |
66 | Set.of(personView, friendMustView), Set.of(predicate)); | 77 | .symbols(person, friend) |
67 | QueryableModel model = store.createModel(); | 78 | .with(ViatraModelQuery.ADAPTER) |
79 | .queries(predicate) | ||
80 | .build(); | ||
81 | |||
82 | var model = store.createModel(); | ||
83 | var personInterpretation = model.getInterpretation(person); | ||
84 | var friendInterpretation = model.getInterpretation(friend); | ||
85 | var queryEngine = model.getAdapter(ModelQuery.ADAPTER); | ||
86 | var predicateResultSet = queryEngine.getResultSet(predicate); | ||
68 | 87 | ||
69 | assertEquals(0, model.countResults(predicate)); | 88 | assertEquals(0, predicateResultSet.countResults()); |
70 | 89 | ||
71 | model.put(person, Tuple.of(0), true); | 90 | personInterpretation.put(Tuple.of(0), true); |
72 | model.put(person, Tuple.of(1), true); | 91 | personInterpretation.put(Tuple.of(1), true); |
73 | model.put(person, Tuple.of(2), true); | 92 | personInterpretation.put(Tuple.of(2), true); |
74 | model.put(friend, Tuple.of(0, 1), TruthValue.TRUE); | ||
75 | model.put(friend, Tuple.of(1, 0), TruthValue.TRUE); | ||
76 | model.put(friend, Tuple.of(1, 2), TruthValue.TRUE); | ||
77 | 93 | ||
78 | assertEquals(0, model.countResults(predicate)); | 94 | friendInterpretation.put(Tuple.of(0, 1), TruthValue.TRUE); |
95 | friendInterpretation.put(Tuple.of(1, 0), TruthValue.TRUE); | ||
96 | friendInterpretation.put(Tuple.of(1, 2), TruthValue.TRUE); | ||
79 | 97 | ||
80 | model.flushChanges(); | 98 | assertEquals(0, predicateResultSet.countResults()); |
81 | assertEquals(3, model.countResults(predicate)); | 99 | |
82 | compareMatchSets(model.allResults(predicate), Set.of(Tuple.of(0, 1), Tuple.of(1, 0), Tuple.of(1, 2))); | 100 | queryEngine.flushChanges(); |
101 | assertEquals(3, predicateResultSet.countResults()); | ||
102 | compareMatchSets(predicateResultSet.allResults(), Set.of(Tuple.of(0, 1), Tuple.of(1, 0), Tuple.of(1, 2))); | ||
83 | } | 103 | } |
84 | 104 | ||
85 | @Test | 105 | @Test |
86 | void andTest() { | 106 | void andTest() { |
87 | Relation<Boolean> person = new Relation<>("Person", 1, Boolean.class, false); | 107 | var person = new Symbol<>("Person", 1, Boolean.class, false); |
88 | Relation<TruthValue> friend = new Relation<>("friend", 2, TruthValue.class, TruthValue.FALSE); | 108 | var friend = new Symbol<>("friend", 2, TruthValue.class, TruthValue.FALSE); |
89 | RelationView<Boolean> personView = new KeyOnlyRelationView(person); | 109 | var personView = new KeyOnlyRelationView<>(person); |
90 | RelationView<TruthValue> friendMustView = new FilteredRelationView<>(friend, "must", | 110 | var friendMustView = new FilteredRelationView<>(friend, "must", TruthValue::must); |
91 | TruthValue::must); | 111 | |
92 | 112 | var p1 = new Variable("p1"); | |
93 | Variable p1 = new Variable("p1"); | 113 | var p2 = new Variable("p2"); |
94 | Variable p2 = new Variable("p2"); | 114 | var predicate = DNF.builder("RelationConstraint") |
95 | DNF predicate = DNF.builder("RelationConstraint") | ||
96 | .parameters(p1, p2) | 115 | .parameters(p1, p2) |
97 | .clause( | 116 | .clause( |
98 | new RelationViewAtom(personView, p1), | 117 | new RelationViewAtom(personView, p1), |
@@ -102,45 +121,52 @@ class QueryTest { | |||
102 | ) | 121 | ) |
103 | .build(); | 122 | .build(); |
104 | 123 | ||
105 | QueryableModelStore store = new ViatraQueryableModelStore(Set.of(person, friend), | 124 | var store = ModelStore.builder() |
106 | Set.of(personView, friendMustView), Set.of(predicate)); | 125 | .symbols(person, friend) |
107 | QueryableModel model = store.createModel(); | 126 | .with(ViatraModelQuery.ADAPTER) |
127 | .queries(predicate) | ||
128 | .build(); | ||
129 | |||
130 | var model = store.createModel(); | ||
131 | var personInterpretation = model.getInterpretation(person); | ||
132 | var friendInterpretation = model.getInterpretation(friend); | ||
133 | var queryEngine = model.getAdapter(ModelQuery.ADAPTER); | ||
134 | var predicateResultSet = queryEngine.getResultSet(predicate); | ||
108 | 135 | ||
109 | assertEquals(0, model.countResults(predicate)); | 136 | assertEquals(0, predicateResultSet.countResults()); |
110 | 137 | ||
111 | model.put(person, Tuple.of(0), true); | 138 | personInterpretation.put(Tuple.of(0), true); |
112 | model.put(person, Tuple.of(1), true); | 139 | personInterpretation.put(Tuple.of(1), true); |
113 | model.put(person, Tuple.of(2), true); | 140 | personInterpretation.put(Tuple.of(2), true); |
114 | 141 | ||
115 | model.put(friend, Tuple.of(0, 1), TruthValue.TRUE); | 142 | friendInterpretation.put(Tuple.of(0, 1), TruthValue.TRUE); |
116 | model.put(friend, Tuple.of(0, 2), TruthValue.TRUE); | 143 | friendInterpretation.put(Tuple.of(0, 2), TruthValue.TRUE); |
117 | 144 | ||
118 | model.flushChanges(); | 145 | queryEngine.flushChanges(); |
119 | assertEquals(0, model.countResults(predicate)); | 146 | assertEquals(0, predicateResultSet.countResults()); |
120 | 147 | ||
121 | model.put(friend, Tuple.of(1, 0), TruthValue.TRUE); | 148 | friendInterpretation.put(Tuple.of(1, 0), TruthValue.TRUE); |
122 | model.flushChanges(); | 149 | queryEngine.flushChanges(); |
123 | assertEquals(2, model.countResults(predicate)); | 150 | assertEquals(2, predicateResultSet.countResults()); |
124 | compareMatchSets(model.allResults(predicate), Set.of(Tuple.of(0, 1), Tuple.of(1, 0))); | 151 | compareMatchSets(predicateResultSet.allResults(), Set.of(Tuple.of(0, 1), Tuple.of(1, 0))); |
125 | 152 | ||
126 | model.put(friend, Tuple.of(2, 0), TruthValue.TRUE); | 153 | friendInterpretation.put(Tuple.of(2, 0), TruthValue.TRUE); |
127 | model.flushChanges(); | 154 | queryEngine.flushChanges(); |
128 | assertEquals(4, model.countResults(predicate)); | 155 | assertEquals(4, predicateResultSet.countResults()); |
129 | compareMatchSets(model.allResults(predicate), Set.of(Tuple.of(0, 1), Tuple.of(1, 0), Tuple.of(0, 2), | 156 | compareMatchSets(predicateResultSet.allResults(), Set.of(Tuple.of(0, 1), Tuple.of(1, 0), Tuple.of(0, 2), |
130 | Tuple.of(2, 0))); | 157 | Tuple.of(2, 0))); |
131 | } | 158 | } |
132 | 159 | ||
133 | @Test | 160 | @Test |
134 | void existTest() { | 161 | void existTest() { |
135 | Relation<Boolean> person = new Relation<>("Person", 1, Boolean.class, false); | 162 | var person = new Symbol<>("Person", 1, Boolean.class, false); |
136 | Relation<TruthValue> friend = new Relation<>("friend", 2, TruthValue.class, TruthValue.FALSE); | 163 | var friend = new Symbol<>("friend", 2, TruthValue.class, TruthValue.FALSE); |
137 | RelationView<Boolean> personView = new KeyOnlyRelationView(person); | 164 | var personView = new KeyOnlyRelationView<>(person); |
138 | RelationView<TruthValue> friendMustView = new FilteredRelationView<>(friend, "must", | 165 | var friendMustView = new FilteredRelationView<>(friend, "must", TruthValue::must); |
139 | TruthValue::must); | 166 | |
140 | 167 | var p1 = new Variable("p1"); | |
141 | Variable p1 = new Variable("p1"); | 168 | var p2 = new Variable("p2"); |
142 | Variable p2 = new Variable("p2"); | 169 | var predicate = DNF.builder("RelationConstraint") |
143 | DNF predicate = DNF.builder("RelationConstraint") | ||
144 | .parameters(p1) | 170 | .parameters(p1) |
145 | .clause( | 171 | .clause( |
146 | new RelationViewAtom(personView, p1), | 172 | new RelationViewAtom(personView, p1), |
@@ -149,39 +175,45 @@ class QueryTest { | |||
149 | ) | 175 | ) |
150 | .build(); | 176 | .build(); |
151 | 177 | ||
152 | QueryableModelStore store = new ViatraQueryableModelStore(Set.of(person, friend), | 178 | var store = ModelStore.builder() |
153 | Set.of(personView, friendMustView), Set.of(predicate)); | 179 | .symbols(person, friend) |
154 | QueryableModel model = store.createModel(); | 180 | .with(ViatraModelQuery.ADAPTER) |
181 | .queries(predicate) | ||
182 | .build(); | ||
183 | |||
184 | var model = store.createModel(); | ||
185 | var personInterpretation = model.getInterpretation(person); | ||
186 | var friendInterpretation = model.getInterpretation(friend); | ||
187 | var queryEngine = model.getAdapter(ModelQuery.ADAPTER); | ||
188 | var predicateResultSet = queryEngine.getResultSet(predicate); | ||
155 | 189 | ||
156 | assertEquals(0, model.countResults(predicate)); | 190 | personInterpretation.put(Tuple.of(0), true); |
191 | personInterpretation.put(Tuple.of(1), true); | ||
192 | personInterpretation.put(Tuple.of(2), true); | ||
157 | 193 | ||
158 | model.put(person, Tuple.of(0), true); | 194 | friendInterpretation.put(Tuple.of(0, 1), TruthValue.TRUE); |
159 | model.put(person, Tuple.of(1), true); | 195 | friendInterpretation.put(Tuple.of(1, 0), TruthValue.TRUE); |
160 | model.put(person, Tuple.of(2), true); | 196 | friendInterpretation.put(Tuple.of(1, 2), TruthValue.TRUE); |
161 | model.put(friend, Tuple.of(0, 1), TruthValue.TRUE); | ||
162 | model.put(friend, Tuple.of(1, 0), TruthValue.TRUE); | ||
163 | model.put(friend, Tuple.of(1, 2), TruthValue.TRUE); | ||
164 | 197 | ||
165 | assertEquals(0, model.countResults(predicate)); | 198 | assertEquals(0, predicateResultSet.countResults()); |
166 | 199 | ||
167 | model.flushChanges(); | 200 | queryEngine.flushChanges(); |
168 | assertEquals(2, model.countResults(predicate)); | 201 | assertEquals(2, predicateResultSet.countResults()); |
169 | compareMatchSets(model.allResults(predicate), Set.of(Tuple.of(0), Tuple.of(1))); | 202 | compareMatchSets(predicateResultSet.allResults(), Set.of(Tuple.of(0), Tuple.of(1))); |
170 | } | 203 | } |
171 | 204 | ||
172 | @Test | 205 | @Test |
173 | void orTest() { | 206 | void orTest() { |
174 | Relation<Boolean> person = new Relation<>("Person", 1, Boolean.class, false); | 207 | var person = new Symbol<>("Person", 1, Boolean.class, false); |
175 | Relation<Boolean> animal = new Relation<>("Animal", 1, Boolean.class, false); | 208 | var animal = new Symbol<>("Animal", 1, Boolean.class, false); |
176 | Relation<TruthValue> friend = new Relation<>("friend", 2, TruthValue.class, TruthValue.FALSE); | 209 | var friend = new Symbol<>("friend", 2, TruthValue.class, TruthValue.FALSE); |
177 | RelationView<Boolean> personView = new KeyOnlyRelationView(person); | 210 | var personView = new KeyOnlyRelationView<>(person); |
178 | RelationView<Boolean> animalView = new KeyOnlyRelationView(animal); | 211 | var animalView = new KeyOnlyRelationView<>(animal); |
179 | RelationView<TruthValue> friendMustView = new FilteredRelationView<>(friend, "must", | 212 | var friendMustView = new FilteredRelationView<>(friend, "must", TruthValue::must); |
180 | TruthValue::must); | 213 | |
181 | 214 | var p1 = new Variable("p1"); | |
182 | Variable p1 = new Variable("p1"); | 215 | var p2 = new Variable("p2"); |
183 | Variable p2 = new Variable("p2"); | 216 | var predicate = DNF.builder("Or") |
184 | DNF predicate = DNF.builder("Or") | ||
185 | .parameters(p1, p2) | 217 | .parameters(p1, p2) |
186 | .clause( | 218 | .clause( |
187 | new RelationViewAtom(personView, p1), | 219 | new RelationViewAtom(personView, p1), |
@@ -195,32 +227,43 @@ class QueryTest { | |||
195 | ) | 227 | ) |
196 | .build(); | 228 | .build(); |
197 | 229 | ||
198 | QueryableModelStore store = new ViatraQueryableModelStore(Set.of(person, animal, friend), | 230 | var store = ModelStore.builder() |
199 | Set.of(personView, animalView, friendMustView), Set.of(predicate)); | 231 | .symbols(person, animal, friend) |
200 | QueryableModel model = store.createModel(); | 232 | .with(ViatraModelQuery.ADAPTER) |
201 | 233 | .queries(predicate) | |
202 | model.put(person, Tuple.of(0), true); | 234 | .build(); |
203 | model.put(person, Tuple.of(1), true); | 235 | |
204 | model.put(animal, Tuple.of(2), true); | 236 | var model = store.createModel(); |
205 | model.put(animal, Tuple.of(3), true); | 237 | var personInterpretation = model.getInterpretation(person); |
206 | model.put(friend, Tuple.of(0, 1), TruthValue.TRUE); | 238 | var animalInterpretation = model.getInterpretation(animal); |
207 | model.put(friend, Tuple.of(0, 2), TruthValue.TRUE); | 239 | var friendInterpretation = model.getInterpretation(friend); |
208 | model.put(friend, Tuple.of(2, 3), TruthValue.TRUE); | 240 | var queryEngine = model.getAdapter(ModelQuery.ADAPTER); |
209 | model.put(friend, Tuple.of(3, 0), TruthValue.TRUE); | 241 | var predicateResultSet = queryEngine.getResultSet(predicate); |
210 | 242 | ||
211 | model.flushChanges(); | 243 | personInterpretation.put(Tuple.of(0), true); |
212 | assertEquals(2, model.countResults(predicate)); | 244 | personInterpretation.put(Tuple.of(1), true); |
213 | compareMatchSets(model.allResults(predicate), Set.of(Tuple.of(0, 1), Tuple.of(2, 3))); | 245 | |
246 | animalInterpretation.put(Tuple.of(2), true); | ||
247 | animalInterpretation.put(Tuple.of(3), true); | ||
248 | |||
249 | friendInterpretation.put(Tuple.of(0, 1), TruthValue.TRUE); | ||
250 | friendInterpretation.put(Tuple.of(0, 2), TruthValue.TRUE); | ||
251 | friendInterpretation.put(Tuple.of(2, 3), TruthValue.TRUE); | ||
252 | friendInterpretation.put(Tuple.of(3, 0), TruthValue.TRUE); | ||
253 | |||
254 | queryEngine.flushChanges(); | ||
255 | assertEquals(2, predicateResultSet.countResults()); | ||
256 | compareMatchSets(predicateResultSet.allResults(), Set.of(Tuple.of(0, 1), Tuple.of(2, 3))); | ||
214 | } | 257 | } |
215 | 258 | ||
216 | @Test | 259 | @Test |
217 | void equalityTest() { | 260 | void equalityTest() { |
218 | Relation<Boolean> person = new Relation<>("Person", 1, Boolean.class, false); | 261 | var person = new Symbol<>("Person", 1, Boolean.class, false); |
219 | RelationView<Boolean> personView = new KeyOnlyRelationView(person); | 262 | var personView = new KeyOnlyRelationView<>(person); |
220 | 263 | ||
221 | Variable p1 = new Variable("p1"); | 264 | var p1 = new Variable("p1"); |
222 | Variable p2 = new Variable("p2"); | 265 | var p2 = new Variable("p2"); |
223 | DNF predicate = DNF.builder("Equality") | 266 | var predicate = DNF.builder("Equality") |
224 | .parameters(p1, p2) | 267 | .parameters(p1, p2) |
225 | .clause( | 268 | .clause( |
226 | new RelationViewAtom(personView, p1), | 269 | new RelationViewAtom(personView, p1), |
@@ -229,30 +272,37 @@ class QueryTest { | |||
229 | ) | 272 | ) |
230 | .build(); | 273 | .build(); |
231 | 274 | ||
232 | QueryableModelStore store = new ViatraQueryableModelStore(Set.of(person), Set.of(personView), Set.of(predicate)); | 275 | var store = ModelStore.builder() |
233 | QueryableModel model = store.createModel(); | 276 | .symbols(person) |
277 | .with(ViatraModelQuery.ADAPTER) | ||
278 | .queries(predicate) | ||
279 | .build(); | ||
280 | |||
281 | var model = store.createModel(); | ||
282 | var personInterpretation = model.getInterpretation(person); | ||
283 | var queryEngine = model.getAdapter(ModelQuery.ADAPTER); | ||
284 | var predicateResultSet = queryEngine.getResultSet(predicate); | ||
234 | 285 | ||
235 | model.put(person, Tuple.of(0), true); | 286 | personInterpretation.put(Tuple.of(0), true); |
236 | model.put(person, Tuple.of(1), true); | 287 | personInterpretation.put(Tuple.of(1), true); |
237 | model.put(person, Tuple.of(2), true); | 288 | personInterpretation.put(Tuple.of(2), true); |
238 | 289 | ||
239 | model.flushChanges(); | 290 | queryEngine.flushChanges(); |
240 | assertEquals(3, model.countResults(predicate)); | 291 | assertEquals(3, predicateResultSet.countResults()); |
241 | compareMatchSets(model.allResults(predicate), Set.of(Tuple.of(0, 0), Tuple.of(1, 1), Tuple.of(2, 2))); | 292 | compareMatchSets(predicateResultSet.allResults(), Set.of(Tuple.of(0, 0), Tuple.of(1, 1), Tuple.of(2, 2))); |
242 | } | 293 | } |
243 | 294 | ||
244 | @Test | 295 | @Test |
245 | void inequalityTest() { | 296 | void inequalityTest() { |
246 | Relation<Boolean> person = new Relation<>("Person", 1, Boolean.class, false); | 297 | var person = new Symbol<>("Person", 1, Boolean.class, false); |
247 | Relation<TruthValue> friend = new Relation<>("friend", 2, TruthValue.class, TruthValue.FALSE); | 298 | var friend = new Symbol<>("friend", 2, TruthValue.class, TruthValue.FALSE); |
248 | RelationView<Boolean> personView = new KeyOnlyRelationView(person); | 299 | var personView = new KeyOnlyRelationView<>(person); |
249 | RelationView<TruthValue> friendMustView = new FilteredRelationView<>(friend, "must", | 300 | var friendMustView = new FilteredRelationView<>(friend, "must", TruthValue::must); |
250 | TruthValue::must); | 301 | |
251 | 302 | var p1 = new Variable("p1"); | |
252 | Variable p1 = new Variable("p1"); | 303 | var p2 = new Variable("p2"); |
253 | Variable p2 = new Variable("p2"); | 304 | var p3 = new Variable("p3"); |
254 | Variable p3 = new Variable("p3"); | 305 | var predicate = DNF.builder("Inequality") |
255 | DNF predicate = DNF.builder("Inequality") | ||
256 | .parameters(p1, p2, p3) | 306 | .parameters(p1, p2, p3) |
257 | .clause( | 307 | .clause( |
258 | new RelationViewAtom(personView, p1), | 308 | new RelationViewAtom(personView, p1), |
@@ -263,32 +313,40 @@ class QueryTest { | |||
263 | ) | 313 | ) |
264 | .build(); | 314 | .build(); |
265 | 315 | ||
266 | QueryableModelStore store = new ViatraQueryableModelStore(Set.of(person, friend), | 316 | var store = ModelStore.builder() |
267 | Set.of(personView, friendMustView), Set.of(predicate)); | 317 | .symbols(person, friend) |
268 | QueryableModel model = store.createModel(); | 318 | .with(ViatraModelQuery.ADAPTER) |
319 | .queries(predicate) | ||
320 | .build(); | ||
321 | |||
322 | var model = store.createModel(); | ||
323 | var personInterpretation = model.getInterpretation(person); | ||
324 | var friendInterpretation = model.getInterpretation(friend); | ||
325 | var queryEngine = model.getAdapter(ModelQuery.ADAPTER); | ||
326 | var predicateResultSet = queryEngine.getResultSet(predicate); | ||
327 | |||
328 | personInterpretation.put(Tuple.of(0), true); | ||
329 | personInterpretation.put(Tuple.of(1), true); | ||
330 | personInterpretation.put(Tuple.of(2), true); | ||
269 | 331 | ||
270 | model.put(person, Tuple.of(0), true); | 332 | friendInterpretation.put(Tuple.of(0, 2), TruthValue.TRUE); |
271 | model.put(person, Tuple.of(1), true); | 333 | friendInterpretation.put(Tuple.of(1, 2), TruthValue.TRUE); |
272 | model.put(person, Tuple.of(2), true); | ||
273 | model.put(friend, Tuple.of(0, 2), TruthValue.TRUE); | ||
274 | model.put(friend, Tuple.of(1, 2), TruthValue.TRUE); | ||
275 | 334 | ||
276 | model.flushChanges(); | 335 | queryEngine.flushChanges(); |
277 | assertEquals(2, model.countResults(predicate)); | 336 | assertEquals(2, predicateResultSet.countResults()); |
278 | compareMatchSets(model.allResults(predicate), Set.of(Tuple.of(0, 1, 2), Tuple.of(1, 0, 2))); | 337 | compareMatchSets(predicateResultSet.allResults(), Set.of(Tuple.of(0, 1, 2), Tuple.of(1, 0, 2))); |
279 | } | 338 | } |
280 | 339 | ||
281 | @Test | 340 | @Test |
282 | void patternCallTest() { | 341 | void patternCallTest() { |
283 | Relation<Boolean> person = new Relation<>("Person", 1, Boolean.class, false); | 342 | var person = new Symbol<>("Person", 1, Boolean.class, false); |
284 | Relation<TruthValue> friend = new Relation<>("friend", 2, TruthValue.class, TruthValue.FALSE); | 343 | var friend = new Symbol<>("friend", 2, TruthValue.class, TruthValue.FALSE); |
285 | RelationView<Boolean> personView = new KeyOnlyRelationView(person); | 344 | var personView = new KeyOnlyRelationView<>(person); |
286 | RelationView<TruthValue> friendMustView = new FilteredRelationView<>(friend, "must", | 345 | var friendMustView = new FilteredRelationView<>(friend, "must", TruthValue::must); |
287 | TruthValue::must); | 346 | |
288 | 347 | var p1 = new Variable("p1"); | |
289 | Variable p1 = new Variable("p1"); | 348 | var p2 = new Variable("p2"); |
290 | Variable p2 = new Variable("p2"); | 349 | var friendPredicate = DNF.builder("RelationConstraint") |
291 | DNF friendPredicate = DNF.builder("RelationConstraint") | ||
292 | .parameters(p1, p2) | 350 | .parameters(p1, p2) |
293 | .clause( | 351 | .clause( |
294 | new RelationViewAtom(personView, p1), | 352 | new RelationViewAtom(personView, p1), |
@@ -297,44 +355,51 @@ class QueryTest { | |||
297 | ) | 355 | ) |
298 | .build(); | 356 | .build(); |
299 | 357 | ||
300 | Variable p3 = new Variable("p3"); | 358 | var p3 = new Variable("p3"); |
301 | Variable p4 = new Variable("p4"); | 359 | var p4 = new Variable("p4"); |
302 | DNF predicate = DNF.builder("PositivePatternCall") | 360 | var predicate = DNF.builder("PositivePatternCall") |
303 | .parameters(p3, p4) | 361 | .parameters(p3, p4) |
304 | .clause( | 362 | .clause( |
305 | new RelationViewAtom(personView, p3), | 363 | new RelationViewAtom(personView, p3), |
306 | new RelationViewAtom(personView, p4), | 364 | new RelationViewAtom(personView, p4), |
307 | new CallAtom<>(friendPredicate, p3, p4) | 365 | new DNFCallAtom(friendPredicate, p3, p4) |
308 | ) | 366 | ) |
309 | .build(); | 367 | .build(); |
310 | 368 | ||
311 | QueryableModelStore store = new ViatraQueryableModelStore(Set.of(person, friend), | 369 | var store = ModelStore.builder() |
312 | Set.of(personView, friendMustView), Set.of(friendPredicate, predicate)); | 370 | .symbols(person, friend) |
313 | QueryableModel model = store.createModel(); | 371 | .with(ViatraModelQuery.ADAPTER) |
372 | .queries(predicate) | ||
373 | .build(); | ||
374 | |||
375 | var model = store.createModel(); | ||
376 | var personInterpretation = model.getInterpretation(person); | ||
377 | var friendInterpretation = model.getInterpretation(friend); | ||
378 | var queryEngine = model.getAdapter(ModelQuery.ADAPTER); | ||
379 | var predicateResultSet = queryEngine.getResultSet(predicate); | ||
314 | 380 | ||
315 | model.put(person, Tuple.of(0), true); | 381 | personInterpretation.put(Tuple.of(0), true); |
316 | model.put(person, Tuple.of(1), true); | 382 | personInterpretation.put(Tuple.of(1), true); |
317 | model.put(person, Tuple.of(2), true); | 383 | personInterpretation.put(Tuple.of(2), true); |
318 | model.put(friend, Tuple.of(0, 1), TruthValue.TRUE); | ||
319 | model.put(friend, Tuple.of(1, 0), TruthValue.TRUE); | ||
320 | model.put(friend, Tuple.of(1, 2), TruthValue.TRUE); | ||
321 | 384 | ||
322 | model.flushChanges(); | 385 | friendInterpretation.put(Tuple.of(0, 1), TruthValue.TRUE); |
386 | friendInterpretation.put(Tuple.of(1, 0), TruthValue.TRUE); | ||
387 | friendInterpretation.put(Tuple.of(1, 2), TruthValue.TRUE); | ||
323 | 388 | ||
324 | assertEquals(3, model.countResults(friendPredicate)); | 389 | queryEngine.flushChanges(); |
390 | assertEquals(3, predicateResultSet.countResults()); | ||
325 | } | 391 | } |
326 | 392 | ||
327 | @Test | 393 | @Test |
328 | void negativePatternCallTest() { | 394 | void negativePatternCallTest() { |
329 | Relation<Boolean> person = new Relation<>("Person", 1, Boolean.class, false); | 395 | var person = new Symbol<>("Person", 1, Boolean.class, false); |
330 | Relation<TruthValue> friend = new Relation<>("friend", 2, TruthValue.class, TruthValue.FALSE); | 396 | var friend = new Symbol<>("friend", 2, TruthValue.class, TruthValue.FALSE); |
331 | RelationView<Boolean> personView = new KeyOnlyRelationView(person); | 397 | var personView = new KeyOnlyRelationView<>(person); |
332 | RelationView<TruthValue> friendMustView = new FilteredRelationView<>(friend, "must", | 398 | var friendMustView = new FilteredRelationView<>(friend, "must", TruthValue::must); |
333 | TruthValue::must); | 399 | |
334 | 400 | var p1 = new Variable("p1"); | |
335 | Variable p1 = new Variable("p1"); | 401 | var p2 = new Variable("p2"); |
336 | Variable p2 = new Variable("p2"); | 402 | var friendPredicate = DNF.builder("RelationConstraint") |
337 | DNF friendPredicate = DNF.builder("RelationConstraint") | ||
338 | .parameters(p1, p2) | 403 | .parameters(p1, p2) |
339 | .clause( | 404 | .clause( |
340 | new RelationViewAtom(personView, p1), | 405 | new RelationViewAtom(personView, p1), |
@@ -343,44 +408,52 @@ class QueryTest { | |||
343 | ) | 408 | ) |
344 | .build(); | 409 | .build(); |
345 | 410 | ||
346 | Variable p3 = new Variable("p3"); | 411 | var p3 = new Variable("p3"); |
347 | Variable p4 = new Variable("p4"); | 412 | var p4 = new Variable("p4"); |
348 | DNF predicate = DNF.builder("NegativePatternCall") | 413 | var predicate = DNF.builder("NegativePatternCall") |
349 | .parameters(p3, p4) | 414 | .parameters(p3, p4) |
350 | .clause( | 415 | .clause( |
351 | new RelationViewAtom(personView, p3), | 416 | new RelationViewAtom(personView, p3), |
352 | new RelationViewAtom(personView, p4), | 417 | new RelationViewAtom(personView, p4), |
353 | new CallAtom<>(false, friendPredicate, p3, p4) | 418 | new DNFCallAtom(false, friendPredicate, p3, p4) |
354 | ) | 419 | ) |
355 | .build(); | 420 | .build(); |
356 | 421 | ||
357 | QueryableModelStore store = new ViatraQueryableModelStore(Set.of(person, friend), | 422 | var store = ModelStore.builder() |
358 | Set.of(personView, friendMustView), Set.of(friendPredicate, predicate)); | 423 | .symbols(person, friend) |
359 | QueryableModel model = store.createModel(); | 424 | .with(ViatraModelQuery.ADAPTER) |
425 | .queries(predicate) | ||
426 | .build(); | ||
427 | |||
428 | var model = store.createModel(); | ||
429 | var personInterpretation = model.getInterpretation(person); | ||
430 | var friendInterpretation = model.getInterpretation(friend); | ||
431 | var queryEngine = model.getAdapter(ModelQuery.ADAPTER); | ||
432 | var predicateResultSet = queryEngine.getResultSet(predicate); | ||
433 | |||
434 | personInterpretation.put(Tuple.of(0), true); | ||
435 | personInterpretation.put(Tuple.of(1), true); | ||
436 | personInterpretation.put(Tuple.of(2), true); | ||
360 | 437 | ||
361 | model.put(person, Tuple.of(0), true); | 438 | friendInterpretation.put(Tuple.of(0, 1), TruthValue.TRUE); |
362 | model.put(person, Tuple.of(1), true); | 439 | friendInterpretation.put(Tuple.of(1, 0), TruthValue.TRUE); |
363 | model.put(person, Tuple.of(2), true); | 440 | friendInterpretation.put(Tuple.of(1, 2), TruthValue.TRUE); |
364 | model.put(friend, Tuple.of(0, 1), TruthValue.TRUE); | ||
365 | model.put(friend, Tuple.of(1, 0), TruthValue.TRUE); | ||
366 | model.put(friend, Tuple.of(1, 2), TruthValue.TRUE); | ||
367 | 441 | ||
368 | model.flushChanges(); | 442 | queryEngine.flushChanges(); |
369 | assertEquals(6, model.countResults(predicate)); | 443 | assertEquals(6, predicateResultSet.countResults()); |
370 | } | 444 | } |
371 | 445 | ||
372 | @Test | 446 | @Test |
373 | void negativeWithQuantificationTest() { | 447 | void negativeWithQuantificationTest() { |
374 | Relation<Boolean> person = new Relation<>("Person", 1, Boolean.class, false); | 448 | var person = new Symbol<>("Person", 1, Boolean.class, false); |
375 | Relation<TruthValue> friend = new Relation<>("friend", 2, TruthValue.class, TruthValue.FALSE); | 449 | var friend = new Symbol<>("friend", 2, TruthValue.class, TruthValue.FALSE); |
376 | RelationView<Boolean> personView = new KeyOnlyRelationView(person); | 450 | var personView = new KeyOnlyRelationView<>(person); |
377 | RelationView<TruthValue> friendMustView = new FilteredRelationView<>(friend, "must", | 451 | var friendMustView = new FilteredRelationView<>(friend, "must", TruthValue::must); |
378 | TruthValue::must); | ||
379 | 452 | ||
380 | Variable p1 = new Variable("p1"); | 453 | var p1 = new Variable("p1"); |
381 | Variable p2 = new Variable("p2"); | 454 | var p2 = new Variable("p2"); |
382 | 455 | ||
383 | DNF called = DNF.builder("Called") | 456 | var called = DNF.builder("Called") |
384 | .parameters(p1, p2) | 457 | .parameters(p1, p2) |
385 | .clause( | 458 | .clause( |
386 | new RelationViewAtom(personView, p1), | 459 | new RelationViewAtom(personView, p1), |
@@ -389,39 +462,47 @@ class QueryTest { | |||
389 | ) | 462 | ) |
390 | .build(); | 463 | .build(); |
391 | 464 | ||
392 | DNF predicate = DNF.builder("Count") | 465 | var predicate = DNF.builder("Count") |
393 | .parameters(p1) | 466 | .parameters(p1) |
394 | .clause( | 467 | .clause( |
395 | new RelationViewAtom(personView, p1), | 468 | new RelationViewAtom(personView, p1), |
396 | new CallAtom<>(false, called, p1, p2) | 469 | new DNFCallAtom(false, called, p1, p2) |
397 | ) | 470 | ) |
398 | .build(); | 471 | .build(); |
399 | 472 | ||
400 | QueryableModelStore store = new ViatraQueryableModelStore(Set.of(person, friend), | 473 | var store = ModelStore.builder() |
401 | Set.of(personView, friendMustView), Set.of(called, predicate)); | 474 | .symbols(person, friend) |
402 | QueryableModel model = store.createModel(); | 475 | .with(ViatraModelQuery.ADAPTER) |
476 | .queries(predicate) | ||
477 | .build(); | ||
478 | |||
479 | var model = store.createModel(); | ||
480 | var personInterpretation = model.getInterpretation(person); | ||
481 | var friendInterpretation = model.getInterpretation(friend); | ||
482 | var queryEngine = model.getAdapter(ModelQuery.ADAPTER); | ||
483 | var predicateResultSet = queryEngine.getResultSet(predicate); | ||
403 | 484 | ||
404 | model.put(person, Tuple.of(0), true); | 485 | personInterpretation.put(Tuple.of(0), true); |
405 | model.put(person, Tuple.of(1), true); | 486 | personInterpretation.put(Tuple.of(1), true); |
406 | model.put(person, Tuple.of(2), true); | 487 | personInterpretation.put(Tuple.of(2), true); |
407 | model.put(friend, Tuple.of(0, 1), TruthValue.TRUE); | ||
408 | model.put(friend, Tuple.of(0, 2), TruthValue.TRUE); | ||
409 | 488 | ||
410 | model.flushChanges(); | 489 | friendInterpretation.put(Tuple.of(0, 1), TruthValue.TRUE); |
411 | assertEquals(2, model.countResults(predicate)); | 490 | friendInterpretation.put(Tuple.of(0, 2), TruthValue.TRUE); |
491 | |||
492 | queryEngine.flushChanges(); | ||
493 | assertEquals(2, predicateResultSet.countResults()); | ||
412 | } | 494 | } |
413 | 495 | ||
414 | @Test | 496 | @Test |
415 | void transitivePatternCallTest() { | 497 | void transitivePatternCallTest() { |
416 | Relation<Boolean> person = new Relation<>("Person", 1, Boolean.class, false); | 498 | var person = new Symbol<>("Person", 1, Boolean.class, false); |
417 | Relation<TruthValue> friend = new Relation<>("friend", 2, TruthValue.class, TruthValue.FALSE); | 499 | var friend = new Symbol<>("friend", 2, TruthValue.class, TruthValue.FALSE); |
418 | RelationView<Boolean> personView = new KeyOnlyRelationView(person); | 500 | var personView = new KeyOnlyRelationView<>(person); |
419 | RelationView<TruthValue> friendMustView = new FilteredRelationView<>(friend, "must", | 501 | var friendMustView = new FilteredRelationView<>(friend, "must", TruthValue::must); |
420 | TruthValue::must); | 502 | |
421 | 503 | var p1 = new Variable("p1"); | |
422 | Variable p1 = new Variable("p1"); | 504 | var p2 = new Variable("p2"); |
423 | Variable p2 = new Variable("p2"); | 505 | var friendPredicate = DNF.builder("RelationConstraint") |
424 | DNF friendPredicate = DNF.builder("RelationConstraint") | ||
425 | .parameters(p1, p2) | 506 | .parameters(p1, p2) |
426 | .clause( | 507 | .clause( |
427 | new RelationViewAtom(personView, p1), | 508 | new RelationViewAtom(personView, p1), |
@@ -430,29 +511,38 @@ class QueryTest { | |||
430 | ) | 511 | ) |
431 | .build(); | 512 | .build(); |
432 | 513 | ||
433 | Variable p3 = new Variable("p3"); | 514 | var p3 = new Variable("p3"); |
434 | Variable p4 = new Variable("p4"); | 515 | var p4 = new Variable("p4"); |
435 | DNF predicate = DNF.builder("TransitivePatternCall") | 516 | var predicate = DNF.builder("TransitivePatternCall") |
436 | .parameters(p3, p4) | 517 | .parameters(p3, p4) |
437 | .clause( | 518 | .clause( |
438 | new RelationViewAtom(personView, p3), | 519 | new RelationViewAtom(personView, p3), |
439 | new RelationViewAtom(personView, p4), | 520 | new RelationViewAtom(personView, p4), |
440 | new CallAtom<>(CallPolarity.TRANSITIVE, friendPredicate, p3, p4) | 521 | new DNFCallAtom(CallPolarity.TRANSITIVE, friendPredicate, p3, p4) |
441 | ) | 522 | ) |
442 | .build(); | 523 | .build(); |
443 | 524 | ||
444 | QueryableModelStore store = new ViatraQueryableModelStore(Set.of(person, friend), | 525 | var store = ModelStore.builder() |
445 | Set.of(personView, friendMustView), Set.of(friendPredicate, predicate)); | 526 | .symbols(person, friend) |
446 | QueryableModel model = store.createModel(); | 527 | .with(ViatraModelQuery.ADAPTER) |
528 | .queries(predicate) | ||
529 | .build(); | ||
530 | |||
531 | var model = store.createModel(); | ||
532 | var personInterpretation = model.getInterpretation(person); | ||
533 | var friendInterpretation = model.getInterpretation(friend); | ||
534 | var queryEngine = model.getAdapter(ModelQuery.ADAPTER); | ||
535 | var predicateResultSet = queryEngine.getResultSet(predicate); | ||
536 | |||
537 | personInterpretation.put(Tuple.of(0), true); | ||
538 | personInterpretation.put(Tuple.of(1), true); | ||
539 | personInterpretation.put(Tuple.of(2), true); | ||
447 | 540 | ||
448 | model.put(person, Tuple.of(0), true); | 541 | friendInterpretation.put(Tuple.of(0, 1), TruthValue.TRUE); |
449 | model.put(person, Tuple.of(1), true); | 542 | friendInterpretation.put(Tuple.of(1, 2), TruthValue.TRUE); |
450 | model.put(person, Tuple.of(2), true); | ||
451 | model.put(friend, Tuple.of(0, 1), TruthValue.TRUE); | ||
452 | model.put(friend, Tuple.of(1, 2), TruthValue.TRUE); | ||
453 | 543 | ||
454 | model.flushChanges(); | 544 | queryEngine.flushChanges(); |
455 | assertEquals(3, model.countResults(predicate)); | 545 | assertEquals(3, predicateResultSet.countResults()); |
456 | } | 546 | } |
457 | 547 | ||
458 | static void compareMatchSets(Stream<TupleLike> matchSet, Set<Tuple> expected) { | 548 | static void compareMatchSets(Stream<TupleLike> matchSet, Set<Tuple> expected) { |
diff --git a/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/QueryTransactionTest.java b/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/QueryTransactionTest.java index e8fa6ed1..49087a8d 100644 --- a/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/QueryTransactionTest.java +++ b/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/QueryTransactionTest.java | |||
@@ -1,54 +1,59 @@ | |||
1 | package tools.refinery.store.query.viatra; | 1 | package tools.refinery.store.query.viatra; |
2 | 2 | ||
3 | import org.junit.jupiter.api.Test; | 3 | import org.junit.jupiter.api.Test; |
4 | import tools.refinery.store.model.representation.Relation; | 4 | import tools.refinery.store.model.ModelStore; |
5 | import tools.refinery.store.query.DNF; | 5 | import tools.refinery.store.query.DNF; |
6 | import tools.refinery.store.query.QueryableModel; | 6 | import tools.refinery.store.query.ModelQuery; |
7 | import tools.refinery.store.query.QueryableModelStore; | ||
8 | import tools.refinery.store.query.Variable; | 7 | import tools.refinery.store.query.Variable; |
9 | import tools.refinery.store.query.atom.RelationViewAtom; | 8 | import tools.refinery.store.query.atom.RelationViewAtom; |
10 | import tools.refinery.store.query.viatra.ViatraQueryableModelStore; | ||
11 | import tools.refinery.store.query.view.KeyOnlyRelationView; | 9 | import tools.refinery.store.query.view.KeyOnlyRelationView; |
12 | import tools.refinery.store.query.view.RelationView; | 10 | import tools.refinery.store.representation.Symbol; |
13 | import tools.refinery.store.tuple.Tuple; | 11 | import tools.refinery.store.tuple.Tuple; |
14 | 12 | ||
15 | import java.util.Set; | ||
16 | |||
17 | import static org.junit.jupiter.api.Assertions.assertEquals; | 13 | import static org.junit.jupiter.api.Assertions.assertEquals; |
18 | 14 | ||
19 | class QueryTransactionTest { | 15 | class QueryTransactionTest { |
20 | @Test | 16 | @Test |
21 | void flushTest() { | 17 | void flushTest() { |
22 | Relation<Boolean> person = new Relation<>("Person", 1, Boolean.class, false); | 18 | var person = new Symbol<>("Person", 1, Boolean.class, false); |
23 | Relation<Boolean> asset = new Relation<>("Asset", 1, Boolean.class, false); | 19 | var asset = new Symbol<>("Asset", 1, Boolean.class, false); |
24 | RelationView<Boolean> personView = new KeyOnlyRelationView(person); | 20 | var personView = new KeyOnlyRelationView<>(person); |
25 | 21 | ||
26 | var p1 = new Variable("p1"); | 22 | var p1 = new Variable("p1"); |
27 | DNF predicate = DNF.builder("TypeConstraint") | 23 | var predicate = DNF.builder("TypeConstraint") |
28 | .parameters(p1) | 24 | .parameters(p1) |
29 | .clause(new RelationViewAtom(personView, p1)) | 25 | .clause(new RelationViewAtom(personView, p1)) |
30 | .build(); | 26 | .build(); |
31 | 27 | ||
32 | QueryableModelStore store = new ViatraQueryableModelStore(Set.of(person, asset), Set.of(personView), | 28 | var store = ModelStore.builder() |
33 | Set.of(predicate)); | 29 | .symbols(person, asset) |
34 | QueryableModel model = store.createModel(); | 30 | .with(ViatraModelQuery.ADAPTER) |
31 | .queries(predicate) | ||
32 | .build(); | ||
33 | |||
34 | var model = store.createModel(); | ||
35 | var personInterpretation = model.getInterpretation(person); | ||
36 | var assetInterpretation = model.getInterpretation(asset); | ||
37 | var queryEngine = model.getAdapter(ModelQuery.ADAPTER); | ||
38 | var predicateResultSet = queryEngine.getResultSet(predicate); | ||
39 | |||
40 | assertEquals(0, predicateResultSet.countResults()); | ||
35 | 41 | ||
36 | assertEquals(0, model.countResults(predicate)); | 42 | personInterpretation.put(Tuple.of(0), true); |
43 | personInterpretation.put(Tuple.of(1), true); | ||
37 | 44 | ||
38 | model.put(person, Tuple.of(0), true); | 45 | assetInterpretation.put(Tuple.of(1), true); |
39 | model.put(person, Tuple.of(1), true); | 46 | assetInterpretation.put(Tuple.of(2), true); |
40 | model.put(asset, Tuple.of(1), true); | ||
41 | model.put(asset, Tuple.of(2), true); | ||
42 | 47 | ||
43 | assertEquals(0, model.countResults(predicate)); | 48 | assertEquals(0, predicateResultSet.countResults()); |
44 | 49 | ||
45 | model.flushChanges(); | 50 | queryEngine.flushChanges(); |
46 | assertEquals(2, model.countResults(predicate)); | 51 | assertEquals(2, predicateResultSet.countResults()); |
47 | 52 | ||
48 | model.put(person, Tuple.of(4), true); | 53 | personInterpretation.put(Tuple.of(4), true); |
49 | assertEquals(2, model.countResults(predicate)); | 54 | assertEquals(2, predicateResultSet.countResults()); |
50 | 55 | ||
51 | model.flushChanges(); | 56 | queryEngine.flushChanges(); |
52 | assertEquals(3, model.countResults(predicate)); | 57 | assertEquals(3, predicateResultSet.countResults()); |
53 | } | 58 | } |
54 | } | 59 | } |
diff --git a/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/internal/cardinality/UpperCardinalitySumAggregationOperatorStreamTest.java b/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/internal/cardinality/UpperCardinalitySumAggregationOperatorStreamTest.java index 07869050..69491fda 100644 --- a/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/internal/cardinality/UpperCardinalitySumAggregationOperatorStreamTest.java +++ b/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/internal/cardinality/UpperCardinalitySumAggregationOperatorStreamTest.java | |||
@@ -3,8 +3,8 @@ package tools.refinery.store.query.viatra.internal.cardinality; | |||
3 | import org.junit.jupiter.params.ParameterizedTest; | 3 | import org.junit.jupiter.params.ParameterizedTest; |
4 | import org.junit.jupiter.params.provider.Arguments; | 4 | import org.junit.jupiter.params.provider.Arguments; |
5 | import org.junit.jupiter.params.provider.MethodSource; | 5 | import org.junit.jupiter.params.provider.MethodSource; |
6 | import tools.refinery.store.model.representation.cardinality.UpperCardinalities; | 6 | import tools.refinery.store.representation.cardinality.UpperCardinalities; |
7 | import tools.refinery.store.model.representation.cardinality.UpperCardinality; | 7 | import tools.refinery.store.representation.cardinality.UpperCardinality; |
8 | 8 | ||
9 | import java.util.stream.Stream; | 9 | import java.util.stream.Stream; |
10 | 10 | ||
diff --git a/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/internal/cardinality/UpperCardinalitySumAggregationOperatorTest.java b/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/internal/cardinality/UpperCardinalitySumAggregationOperatorTest.java index afc4a2f3..20dad543 100644 --- a/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/internal/cardinality/UpperCardinalitySumAggregationOperatorTest.java +++ b/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/internal/cardinality/UpperCardinalitySumAggregationOperatorTest.java | |||
@@ -2,8 +2,8 @@ package tools.refinery.store.query.viatra.internal.cardinality; | |||
2 | 2 | ||
3 | import org.junit.jupiter.api.BeforeEach; | 3 | import org.junit.jupiter.api.BeforeEach; |
4 | import org.junit.jupiter.api.Test; | 4 | import org.junit.jupiter.api.Test; |
5 | import tools.refinery.store.model.representation.cardinality.UpperCardinalities; | 5 | import tools.refinery.store.representation.cardinality.UpperCardinalities; |
6 | import tools.refinery.store.model.representation.cardinality.UpperCardinality; | 6 | import tools.refinery.store.representation.cardinality.UpperCardinality; |
7 | 7 | ||
8 | import static org.hamcrest.MatcherAssert.assertThat; | 8 | import static org.hamcrest.MatcherAssert.assertThat; |
9 | import static org.hamcrest.Matchers.equalTo; | 9 | import static org.hamcrest.Matchers.equalTo; |