From 1be64083c2c38eedeffc7cea9f51afbed4d46d28 Mon Sep 17 00:00:00 2001 From: Kristóf Marussy Date: Mon, 26 Sep 2022 01:42:58 +0200 Subject: refactor: remove viatra dependency from store --- .../query/viatra/ViatraQueryableModelStore.java | 31 +++++---- .../internal/context/RelationalEngineContext.java | 1 - .../context/RelationalQueryMetaContext.java | 11 +-- .../internal/context/RelationalRuntimeContext.java | 10 +-- .../query/viatra/internal/pquery/DNF2PQuery.java | 78 ++++++++++++++-------- .../internal/pquery/RelationViewWrapper.java | 30 +++++++++ .../internal/viewupdate/ModelUpdateListener.java | 14 ++-- .../viatra/internal/viewupdate/ViewUpdate.java | 6 +- .../internal/viewupdate/ViewUpdateBuffer.java | 1 + .../internal/viewupdate/ViewUpdateTranslator.java | 20 ++++-- subprojects/store/build.gradle | 5 -- .../query/view/AbstractFilteredRelationView.java | 44 ++++++++++++ .../store/query/view/FilteredRelationView.java | 52 ++++++--------- .../store/query/view/FunctionalRelationView.java | 35 +++++----- .../store/query/view/KeyOnlyRelationView.java | 14 ++-- .../refinery/store/query/view/RelationView.java | 52 +++++---------- 16 files changed, 245 insertions(+), 159 deletions(-) create mode 100644 subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/RelationViewWrapper.java create mode 100644 subprojects/store/src/main/java/tools/refinery/store/query/view/AbstractFilteredRelationView.java diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/ViatraQueryableModelStore.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/ViatraQueryableModelStore.java index 5a02ca08..a63abc3a 100644 --- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/ViatraQueryableModelStore.java +++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/ViatraQueryableModelStore.java @@ -8,10 +8,9 @@ import tools.refinery.store.model.representation.DataRepresentation; import tools.refinery.store.query.QueryableModel; import tools.refinery.store.query.QueryableModelStore; import tools.refinery.store.query.building.*; +import tools.refinery.store.query.viatra.internal.RawPatternMatcher; import tools.refinery.store.query.viatra.internal.ViatraQueryableModel; import tools.refinery.store.query.viatra.internal.pquery.DNF2PQuery; -import tools.refinery.store.query.viatra.internal.RawPatternMatcher; -import tools.refinery.store.query.viatra.internal.pquery.SimplePQuery; import tools.refinery.store.query.view.RelationView; import java.util.Collections; @@ -21,7 +20,9 @@ import java.util.Set; public class ViatraQueryableModelStore implements QueryableModelStore { protected final ModelStore store; + protected final Set> relationViews; + protected final Map> predicates; public ViatraQueryableModelStore(ModelStore store, Set> relationViews, @@ -41,9 +42,9 @@ public class ViatraQueryableModelStore implements QueryableModelStore { private void validateViews(Set> dataRepresentations, Set> relationViews) { for (RelationView relationView : relationViews) { if (!dataRepresentations.contains(relationView.getRepresentation())) { - throw new IllegalArgumentException( - DataRepresentation.class.getSimpleName() + " " + relationView.getStringID() + " added to " - + QueryableModelStore.class.getSimpleName() + " without a referred representation."); + throw new IllegalArgumentException("%s %s added to %s without a referred representation.".formatted( + DataRepresentation.class.getSimpleName(), relationView.getName(), + QueryableModelStore.class.getSimpleName())); } } } @@ -65,10 +66,10 @@ public class ViatraQueryableModelStore implements QueryableModelStore { private void validateRelationAtom(Set> relationViews, DNFPredicate dnfPredicate, RelationAtom relationAtom) { if (!relationViews.contains(relationAtom.view())) { - throw new IllegalArgumentException(DNFPredicate.class.getSimpleName() + " " - + dnfPredicate.getUniqueName() + " contains reference to a view of " - + relationAtom.view().getRepresentation().getName() - + " that is not in the model."); + throw new IllegalArgumentException( + "%s %s contains reference to a view %s that is not in the model.".formatted( + DNFPredicate.class.getSimpleName(), dnfPredicate.getUniqueName(), + relationAtom.view().getName())); } } @@ -76,19 +77,17 @@ public class ViatraQueryableModelStore implements QueryableModelStore { PredicateAtom predicateAtom) { if (!predicates.contains(predicateAtom.getReferred())) { throw new IllegalArgumentException( - DNFPredicate.class.getSimpleName() + " " + dnfPredicate.getUniqueName() - + " contains reference to a predicate " - + predicateAtom.getReferred().getName() - + "that is not in the model."); + "%s %s contains reference to a predicate %s that is not in the model.".formatted( + DNFPredicate.class.getSimpleName(), dnfPredicate.getUniqueName(), + predicateAtom.getReferred().getName())); } } private Map> initPredicates(Set predicates) { Map> result = new HashMap<>(); - Map dnf2PQueryMap = new HashMap<>(); + var dnf2PQuery = new DNF2PQuery(); for (DNFPredicate dnfPredicate : predicates) { - GenericQuerySpecification query = - DNF2PQuery.translate(dnfPredicate, dnf2PQueryMap).build(); + GenericQuerySpecification query = dnf2PQuery.translate(dnfPredicate).build(); result.put(dnfPredicate, query); } diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/context/RelationalEngineContext.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/context/RelationalEngineContext.java index 882734cb..d32d49ba 100644 --- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/context/RelationalEngineContext.java +++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/context/RelationalEngineContext.java @@ -29,5 +29,4 @@ public class RelationalEngineContext implements IEngineContext { public IQueryRuntimeContext getQueryRuntimeContext() { return runtimeContext; } - } diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/context/RelationalQueryMetaContext.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/context/RelationalQueryMetaContext.java index 64c23c61..eb3c6fbd 100644 --- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/context/RelationalQueryMetaContext.java +++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/context/RelationalQueryMetaContext.java @@ -3,9 +3,11 @@ package tools.refinery.store.query.viatra.internal.context; import org.eclipse.viatra.query.runtime.matchers.context.AbstractQueryMetaContext; import org.eclipse.viatra.query.runtime.matchers.context.IInputKey; import org.eclipse.viatra.query.runtime.matchers.context.InputKeyImplication; -import tools.refinery.store.query.view.RelationView; +import tools.refinery.store.query.viatra.internal.pquery.RelationViewWrapper; -import java.util.*; +import java.util.Collection; +import java.util.Map; +import java.util.Set; /** * The meta context information for String scopes. @@ -36,9 +38,8 @@ public class RelationalQueryMetaContext extends AbstractQueryMetaContext { } public void ensureValidKey(IInputKey key) { - if (key instanceof RelationView) { - return; + if (!(key instanceof RelationViewWrapper)) { + throw new IllegalArgumentException("The input key %s is not a valid input key.".formatted(key)); } - throw new IllegalArgumentException("The input key %s is not a valid input key.".formatted(key)); } } diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/context/RelationalRuntimeContext.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/context/RelationalRuntimeContext.java index 0bd1b807..c007d630 100644 --- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/context/RelationalRuntimeContext.java +++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/context/RelationalRuntimeContext.java @@ -7,6 +7,7 @@ import org.eclipse.viatra.query.runtime.matchers.tuple.TupleMask; import org.eclipse.viatra.query.runtime.matchers.tuple.Tuples; import org.eclipse.viatra.query.runtime.matchers.util.Accuracy; import tools.refinery.store.model.Model; +import tools.refinery.store.query.viatra.internal.pquery.RelationViewWrapper; import tools.refinery.store.query.viatra.internal.viewupdate.ModelUpdateListener; import tools.refinery.store.query.view.RelationView; @@ -67,7 +68,8 @@ public class RelationalRuntimeContext implements IQueryRuntimeContext { @SuppressWarnings("squid:S1452") RelationView checkKey(IInputKey key) { - if (key instanceof RelationView relationViewKey) { + if (key instanceof RelationViewWrapper wrappedKey) { + var relationViewKey = wrappedKey.getWrappedKey(); if (modelUpdateListener.containsRelationalView(relationViewKey)) { return relationViewKey; } else { @@ -117,7 +119,7 @@ public class RelationalRuntimeContext implements IQueryRuntimeContext { } @Override - public Iterable enumerateValues(IInputKey key, TupleMask seedMask, ITuple seed) { + public Iterable enumerateValues(IInputKey key, TupleMask seedMask, ITuple seed) { return enumerateTuples(key, seedMask, seed); } @@ -130,14 +132,14 @@ public class RelationalRuntimeContext implements IQueryRuntimeContext { @Override public void addUpdateListener(IInputKey key, Tuple seed, IQueryRuntimeContextListener listener) { RelationView relationalKey = checkKey(key); - this.modelUpdateListener.addListener(relationalKey, seed, listener); + this.modelUpdateListener.addListener(key, relationalKey, seed, listener); } @Override public void removeUpdateListener(IInputKey key, Tuple seed, IQueryRuntimeContextListener listener) { RelationView relationalKey = checkKey(key); - this.modelUpdateListener.removeListener(relationalKey, seed, listener); + this.modelUpdateListener.removeListener(key, relationalKey, seed, listener); } @Override diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/DNF2PQuery.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/DNF2PQuery.java index c093be47..b6468e76 100644 --- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/DNF2PQuery.java +++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/DNF2PQuery.java @@ -12,28 +12,53 @@ import org.eclipse.viatra.query.runtime.matchers.psystem.basicenumerables.TypeCo import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PParameter; import org.eclipse.viatra.query.runtime.matchers.tuple.Tuples; import tools.refinery.store.query.building.*; +import tools.refinery.store.query.view.RelationView; import java.util.*; +import java.util.stream.Collectors; public class DNF2PQuery { - private DNF2PQuery() { - throw new IllegalStateException("This is a static utility class and should not be instantiated directly"); - } + private final Set translating = new LinkedHashSet<>(); + + private final Map dnf2PQueryMap = new HashMap<>(); - public static SimplePQuery translate(DNFPredicate predicate, Map dnf2PQueryMap) { - SimplePQuery query = dnf2PQueryMap.get(predicate); - if (query != null) { - return query; + private final Map, RelationViewWrapper> view2WrapperMap = new HashMap<>(); + + public SimplePQuery translate(DNFPredicate predicate) { + if (translating.contains(predicate)) { + var path = translating.stream().map(DNFPredicate::getName).collect(Collectors.joining(" -> ")); + throw new IllegalStateException("Circular reference %s -> %s detected".formatted(path, + predicate.getName())); } - query = new SimplePQuery(predicate.getName()); + // We can't use computeIfAbsent here, because translating referenced queries calls this method in a reentrant + // way, which would cause a ConcurrentModificationException with computeIfAbsent. + var pQuery = dnf2PQueryMap.get(predicate); + if (pQuery == null) { + translating.add(predicate); + try { + pQuery = doTranslate(predicate); + dnf2PQueryMap.put(predicate, pQuery); + } finally { + translating.remove(predicate); + } + } + return pQuery; + } + + private SimplePQuery doTranslate(DNFPredicate predicate) { + var query = new SimplePQuery(predicate.getName()); + Map parameters = new HashMap<>(); + for (Variable variable : predicate.getVariables()) { + parameters.put(variable, new PParameter(variable.getName())); + } - predicate.getVariables().forEach(variable -> parameters.put(variable, new PParameter(variable.getName()))); List parameterList = new ArrayList<>(); for (var param : predicate.getVariables()) { parameterList.add(parameters.get(param)); } query.setParameters(parameterList); + for (DNFAnd clause : predicate.getClauses()) { PBody body = new PBody(query); List symbolicParameters = new ArrayList<>(); @@ -44,15 +69,14 @@ public class DNF2PQuery { body.setSymbolicParameters(symbolicParameters); query.addBody(body); for (DNFAtom constraint : clause.getConstraints()) { - translateDNFAtom(constraint, body, dnf2PQueryMap); + translateDNFAtom(constraint, body); } } - dnf2PQueryMap.put(predicate, query); + return query; } - private static void translateDNFAtom(DNFAtom constraint, PBody body, - Map dnf2PQueryMap) { + private void translateDNFAtom(DNFAtom constraint, PBody body) { if (constraint instanceof EquivalenceAtom equivalence) { translateEquivalenceAtom(equivalence, body); } @@ -60,11 +84,11 @@ public class DNF2PQuery { translateRelationAtom(relation, body); } if (constraint instanceof PredicateAtom predicate) { - translatePredicateAtom(predicate, body, dnf2PQueryMap); + translatePredicateAtom(predicate, body); } } - private static void translateEquivalenceAtom(EquivalenceAtom equivalence, PBody body) { + private void translateEquivalenceAtom(EquivalenceAtom equivalence, PBody body) { PVariable varSource = body.getOrCreateVariableByName(equivalence.getLeft().getName()); PVariable varTarget = body.getOrCreateVariableByName(equivalence.getRight().getName()); if (equivalence.isPositive()) @@ -73,7 +97,7 @@ public class DNF2PQuery { new Inequality(body, varSource, varTarget); } - private static void translateRelationAtom(RelationAtom relation, PBody body) { + private void translateRelationAtom(RelationAtom relation, PBody body) { if (relation.substitution().size() != relation.view().getArity()) { throw new IllegalArgumentException("Arity (%d) does not match parameter numbers (%d)".formatted( relation.view().getArity(), relation.substitution().size())); @@ -82,32 +106,34 @@ public class DNF2PQuery { for (int i = 0; i < relation.substitution().size(); i++) { variables[i] = body.getOrCreateVariableByName(relation.substitution().get(i).getName()); } - new TypeConstraint(body, Tuples.flatTupleOf(variables), relation.view()); + new TypeConstraint(body, Tuples.flatTupleOf(variables), wrapView(relation.view())); + } + + private RelationViewWrapper wrapView(RelationView relationView) { + return view2WrapperMap.computeIfAbsent(relationView, RelationViewWrapper::new); } - private static void translatePredicateAtom(PredicateAtom predicate, PBody body, - Map dnf2PQueryMap) { + private void translatePredicateAtom(PredicateAtom predicate, PBody body) { Object[] variables = new Object[predicate.getSubstitution().size()]; for (int i = 0; i < predicate.getSubstitution().size(); i++) { variables[i] = body.getOrCreateVariableByName(predicate.getSubstitution().get(i).getName()); } + var variablesTuple = Tuples.flatTupleOf(variables); + var translatedReferred = translate(predicate.getReferred()); if (predicate.isPositive()) { if (predicate.isTransitive()) { if (predicate.getSubstitution().size() != 2) { throw new IllegalArgumentException("Transitive Predicate Atoms must be binary."); } - new BinaryTransitiveClosure(body, Tuples.flatTupleOf(variables), - DNF2PQuery.translate(predicate.getReferred(), dnf2PQueryMap)); + new BinaryTransitiveClosure(body, variablesTuple, translatedReferred); } else { - new PositivePatternCall(body, Tuples.flatTupleOf(variables), - DNF2PQuery.translate(predicate.getReferred(), dnf2PQueryMap)); + new PositivePatternCall(body, variablesTuple, translatedReferred); } } else { if (predicate.isTransitive()) { - throw new InputMismatchException("Transitive Predicate Atoms cannot be negative."); + throw new IllegalArgumentException("Transitive Predicate Atoms cannot be negative."); } else { - new NegativePatternCall(body, Tuples.flatTupleOf(variables), - DNF2PQuery.translate(predicate.getReferred(), dnf2PQueryMap)); + new NegativePatternCall(body, variablesTuple, translatedReferred); } } } diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/RelationViewWrapper.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/RelationViewWrapper.java new file mode 100644 index 00000000..2a4148dc --- /dev/null +++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/RelationViewWrapper.java @@ -0,0 +1,30 @@ +package tools.refinery.store.query.viatra.internal.pquery; + +import org.eclipse.viatra.query.runtime.matchers.context.common.BaseInputKeyWrapper; +import tools.refinery.store.query.view.RelationView; + +public class RelationViewWrapper extends BaseInputKeyWrapper> { + public RelationViewWrapper(RelationView wrappedKey) { + super(wrappedKey); + } + + @Override + public String getPrettyPrintableName() { + return wrappedKey.getName(); + } + + @Override + public String getStringID() { + return getPrettyPrintableName(); + } + + @Override + public int getArity() { + return wrappedKey.getArity(); + } + + @Override + public boolean isEnumerable() { + return true; + } +} diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/viewupdate/ModelUpdateListener.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/viewupdate/ModelUpdateListener.java index 25919888..5a0da315 100644 --- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/viewupdate/ModelUpdateListener.java +++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/viewupdate/ModelUpdateListener.java @@ -1,5 +1,6 @@ package tools.refinery.store.query.viatra.internal.viewupdate; +import org.eclipse.viatra.query.runtime.matchers.context.IInputKey; import org.eclipse.viatra.query.runtime.matchers.context.IQueryRuntimeContextListener; import org.eclipse.viatra.query.runtime.matchers.tuple.ITuple; import tools.refinery.store.model.Tuple; @@ -46,20 +47,23 @@ public class ModelUpdateListener { return view2Buffers.containsKey(relationalKey); } - public void addListener(RelationView relationView, ITuple seed, IQueryRuntimeContextListener listener) { + public void addListener(IInputKey key, RelationView relationView, ITuple seed, + IQueryRuntimeContextListener listener) { if (view2Buffers.containsKey(relationView)) { - ViewUpdateTranslator updateListener = new ViewUpdateTranslator<>(relationView, seed, listener); + ViewUpdateTranslator updateListener = new ViewUpdateTranslator<>(key, relationView, seed, listener); ViewUpdateBuffer updateBuffer = new ViewUpdateBuffer<>(updateListener); view2Buffers.get(relationView).add(updateBuffer); - } else + } else { throw new IllegalArgumentException(); + } } - public void removeListener(RelationView relationView, ITuple seed, IQueryRuntimeContextListener listener) { + public void removeListener(IInputKey key, RelationView relationView, ITuple seed, + IQueryRuntimeContextListener listener) { if (view2Buffers.containsKey(relationView)) { Set> buffers = this.view2Buffers.get(relationView); for (var buffer : buffers) { - if (buffer.getUpdateListener().equals(relationView, seed, listener)) { + if (buffer.getUpdateListener().equals(key, relationView, seed, listener)) { // remove buffer and terminate immediately, or it will break iterator. buffers.remove(buffer); return; diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/viewupdate/ViewUpdate.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/viewupdate/ViewUpdate.java index c727f046..b9406018 100644 --- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/viewupdate/ViewUpdate.java +++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/viewupdate/ViewUpdate.java @@ -3,8 +3,7 @@ package tools.refinery.store.query.viatra.internal.viewupdate; import java.util.Arrays; import java.util.Objects; -record ViewUpdate (Object[] tuple, boolean isInsertion) { - +record ViewUpdate(Object[] tuple, boolean isInsertion) { @Override public int hashCode() { final int prime = 31; @@ -28,7 +27,6 @@ record ViewUpdate (Object[] tuple, boolean isInsertion) { @Override public String toString() { - return "ViewUpdate [" + Arrays.toString(tuple) + "insertion= "+this.isInsertion+"]"; + return "ViewUpdate [" + Arrays.toString(tuple) + "insertion= " + this.isInsertion + "]"; } - } diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/viewupdate/ViewUpdateBuffer.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/viewupdate/ViewUpdateBuffer.java index 5a4243f2..e13a9cb8 100644 --- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/viewupdate/ViewUpdateBuffer.java +++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/viewupdate/ViewUpdateBuffer.java @@ -8,6 +8,7 @@ import java.util.List; public class ViewUpdateBuffer { protected final ViewUpdateTranslator updateListener; + protected final List buffer = new ArrayList<>(); public ViewUpdateBuffer(ViewUpdateTranslator updateListener) { diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/viewupdate/ViewUpdateTranslator.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/viewupdate/ViewUpdateTranslator.java index 2f7f9a9c..62a10e45 100644 --- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/viewupdate/ViewUpdateTranslator.java +++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/viewupdate/ViewUpdateTranslator.java @@ -1,5 +1,6 @@ package tools.refinery.store.query.viatra.internal.viewupdate; +import org.eclipse.viatra.query.runtime.matchers.context.IInputKey; import org.eclipse.viatra.query.runtime.matchers.context.IQueryRuntimeContextListener; import org.eclipse.viatra.query.runtime.matchers.tuple.ITuple; import org.eclipse.viatra.query.runtime.matchers.tuple.Tuples; @@ -9,29 +10,38 @@ import tools.refinery.store.query.view.RelationView; import java.util.Objects; public class ViewUpdateTranslator { + private final IInputKey wrappedKey; + private final RelationView key; private final ITuple filter; private final IQueryRuntimeContextListener listener; - public ViewUpdateTranslator(RelationView key, ITuple filter, IQueryRuntimeContextListener listener) { + public ViewUpdateTranslator(IInputKey wrappedKey, RelationView key, ITuple filter, + IQueryRuntimeContextListener listener) { super(); + this.wrappedKey = wrappedKey; this.key = key; this.filter = filter; this.listener = listener; } - public boolean equals(RelationView relationView, ITuple seed, IQueryRuntimeContextListener listener) { - return key == relationView && filter.equals(seed) && this.listener == listener; + public boolean equals(IInputKey wrappedKey, RelationView relationView, ITuple seed, + IQueryRuntimeContextListener listener) { + return this.wrappedKey == wrappedKey && key == relationView && filter.equals(seed) && this.listener == listener; } public void processChange(ViewUpdate change) { - listener.update(key, Tuples.flatTupleOf(change.tuple()), change.isInsertion()); + listener.update(wrappedKey, Tuples.flatTupleOf(change.tuple()), change.isInsertion()); } + @SuppressWarnings("squid:S1168") public Object[] isMatching(Tuple tuple, D value) { - return isMatching(key.getWrappedKey().transform(tuple, value), filter); + if (!key.filter(tuple, value)) { + return null; + } + return isMatching(key.forwardMap(tuple, value), filter); } @SuppressWarnings("squid:S1168") diff --git a/subprojects/store/build.gradle b/subprojects/store/build.gradle index 8d091a81..370d094b 100644 --- a/subprojects/store/build.gradle +++ b/subprojects/store/build.gradle @@ -2,8 +2,3 @@ plugins { id 'refinery-java-library' id 'refinery-jmh' } - -dependencies { - implementation libs.ecore - implementation libs.viatra -} diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/view/AbstractFilteredRelationView.java b/subprojects/store/src/main/java/tools/refinery/store/query/view/AbstractFilteredRelationView.java new file mode 100644 index 00000000..a21a38ba --- /dev/null +++ b/subprojects/store/src/main/java/tools/refinery/store/query/view/AbstractFilteredRelationView.java @@ -0,0 +1,44 @@ +package tools.refinery.store.query.view; + +import tools.refinery.store.model.Model; +import tools.refinery.store.model.Tuple; +import tools.refinery.store.model.Tuple.Tuple1; +import tools.refinery.store.model.representation.Relation; + +public abstract class AbstractFilteredRelationView extends RelationView { + protected AbstractFilteredRelationView(Relation representation, String name) { + super(representation, name); + } + + protected AbstractFilteredRelationView(Relation representation) { + super(representation); + } + + @Override + public Object[] forwardMap(Tuple key, D value) { + return toTuple1Array(key); + } + + @Override + public boolean get(Model model, Object[] tuple) { + int[] content = new int[tuple.length]; + for (int i = 0; i < tuple.length; i++) { + content[i] = ((Tuple1) tuple[i]).get(0); + } + Tuple key = Tuple.of(content); + D value = model.get(getRepresentation(), key); + return filter(key, value); + } + + public int getArity() { + return this.getRepresentation().getArity(); + } + + private static Object[] toTuple1Array(Tuple t) { + Object[] result = new Object[t.getSize()]; + for (int i = 0; i < t.getSize(); i++) { + result[i] = Tuple.of(t.get(i)); + } + return result; + } +} diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/view/FilteredRelationView.java b/subprojects/store/src/main/java/tools/refinery/store/query/view/FilteredRelationView.java index 3531195a..bb5d0237 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/query/view/FilteredRelationView.java +++ b/subprojects/store/src/main/java/tools/refinery/store/query/view/FilteredRelationView.java @@ -1,48 +1,34 @@ package tools.refinery.store.query.view; -import java.util.function.BiPredicate; - -import tools.refinery.store.model.Model; import tools.refinery.store.model.Tuple; -import tools.refinery.store.model.Tuple.Tuple1; import tools.refinery.store.model.representation.Relation; -public class FilteredRelationView extends RelationView{ - private final BiPredicate predicate; +import java.util.function.BiPredicate; +import java.util.function.Predicate; - public FilteredRelationView(Relation representation, BiPredicate predicate) { - super(representation); +public class FilteredRelationView extends AbstractFilteredRelationView { + private final BiPredicate predicate; + + public FilteredRelationView(Relation representation, String name, BiPredicate predicate) { + super(representation, name); this.predicate = predicate; } - @Override - protected Object[] forwardMap(Tuple key, D value) { - return toTuple1Array(key); - } - @Override - public boolean get(Model model, Object[] tuple) { - int[] content = new int[tuple.length]; - for(int i = 0; i representation, BiPredicate predicate) { + super(representation); + this.predicate = predicate; } - - public static Object[] toTuple1Array(Tuple t) { - Object[] result = new Object[t.getSize()]; - for(int i = 0; i representation, String name, Predicate predicate) { + this(representation, name, (k, v) -> predicate.test(v)); } - - @Override - public int getArity() { - return this.representation.getArity(); + + public FilteredRelationView(Relation representation, Predicate predicate) { + this(representation, (k, v) -> predicate.test(v)); } + @Override - protected boolean filter(Tuple key, D value) { + public boolean filter(Tuple key, D value) { return this.predicate.test(key, value); } } diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/view/FunctionalRelationView.java b/subprojects/store/src/main/java/tools/refinery/store/query/view/FunctionalRelationView.java index db9ba4b8..54baa050 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/query/view/FunctionalRelationView.java +++ b/subprojects/store/src/main/java/tools/refinery/store/query/view/FunctionalRelationView.java @@ -6,45 +6,48 @@ import tools.refinery.store.model.Tuple.Tuple1; import tools.refinery.store.model.representation.Relation; public class FunctionalRelationView extends RelationView { + public FunctionalRelationView(Relation representation, String name) { + super(representation, name); + } public FunctionalRelationView(Relation representation) { super(representation); } @Override - protected boolean filter(Tuple key, D value) { + public boolean filter(Tuple key, D value) { return true; } @Override - protected Object[] forwardMap(Tuple key, D value) { + public Object[] forwardMap(Tuple key, D value) { return toTuple1ArrayPlusValue(key, value); } @Override public boolean get(Model model, Object[] tuple) { - int[] content = new int[tuple.length-1]; - for(int i = 0; i Object[] toTuple1ArrayPlusValue(Tuple t, D value) { - Object[] result = new Object[t.getSize()+1]; - for(int i = 0; i Object[] toTuple1ArrayPlusValue(Tuple t, D value) { + Object[] result = new Object[t.getSize() + 1]; + for (int i = 0; i < t.getSize(); i++) { result[i] = Tuple.of(t.get(i)); } result[t.getSize()] = value; return result; } - - @Override - public int getArity() { - return this.representation.getArity()+1; - } } diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/view/KeyOnlyRelationView.java b/subprojects/store/src/main/java/tools/refinery/store/query/view/KeyOnlyRelationView.java index 6fa387a1..b9a9ed9f 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/query/view/KeyOnlyRelationView.java +++ b/subprojects/store/src/main/java/tools/refinery/store/query/view/KeyOnlyRelationView.java @@ -3,14 +3,18 @@ package tools.refinery.store.query.view; import tools.refinery.store.model.Tuple; import tools.refinery.store.model.representation.Relation; -public class KeyOnlyRelationView extends FilteredRelationView{ +public class KeyOnlyRelationView extends AbstractFilteredRelationView { + public static final String VIEW_NAME = "key"; + + private final Boolean defaultValue; public KeyOnlyRelationView(Relation representation) { - super(representation, (k,v)->true); + super(representation, VIEW_NAME); + defaultValue = representation.getDefaultValue(); } + @Override - protected boolean filter(Tuple key, Boolean value) { - return !value.equals(representation.getDefaultValue()); + public boolean filter(Tuple key, Boolean value) { + return !value.equals(defaultValue); } - } diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/view/RelationView.java b/subprojects/store/src/main/java/tools/refinery/store/query/view/RelationView.java index fd55eed4..b8a54046 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/query/view/RelationView.java +++ b/subprojects/store/src/main/java/tools/refinery/store/query/view/RelationView.java @@ -1,66 +1,51 @@ package tools.refinery.store.query.view; -import java.util.Objects; - -import org.eclipse.viatra.query.runtime.matchers.context.common.BaseInputKeyWrapper; - import tools.refinery.store.map.CursorAsIterator; import tools.refinery.store.model.Model; import tools.refinery.store.model.Tuple; import tools.refinery.store.model.representation.Relation; +import java.util.Objects; +import java.util.UUID; + /** * Represents a view of a {@link Relation} that can be queried. - * - * @author Oszkar Semerath * * @param + * @author Oszkar Semerath */ -public abstract class RelationView extends BaseInputKeyWrapper> { - protected final Relation representation; +public abstract class RelationView { + private final Relation representation; - protected RelationView(Relation representation) { - super(null); - this.wrappedKey = this; + private final String name; + + protected RelationView(Relation representation, String name) { this.representation = representation; + this.name = name; } - @Override - public String getPrettyPrintableName() { - return representation.getName(); + protected RelationView(Relation representation) { + this(representation, UUID.randomUUID().toString()); } - @Override - public String getStringID() { - return representation.getName() + this.getClass().getName(); - } + public abstract int getArity(); public Relation getRepresentation() { return representation; } - @Override - public boolean isEnumerable() { - return true; + public String getName() { + return representation.getName() + "#" + name; } - protected abstract boolean filter(Tuple key, D value); + public abstract boolean filter(Tuple key, D value); - protected abstract Object[] forwardMap(Tuple key, D value); + public abstract Object[] forwardMap(Tuple key, D value); public abstract boolean get(Model model, Object[] tuple); - - @SuppressWarnings("squid:S1168") - public Object[] transform(Tuple tuple, D value) { - if (filter(tuple, value)) { - return forwardMap(tuple, value); - } else - return null; - } public Iterable getAll(Model model) { - return (() -> new CursorAsIterator<>(model.getAll(representation), (k, v) -> forwardMap(k, v), - (k, v) -> filter(k, v))); + return (() -> new CursorAsIterator<>(model.getAll(representation), this::forwardMap, this::filter)); } @Override @@ -81,5 +66,4 @@ public abstract class RelationView extends BaseInputKeyWrapper other = ((RelationView) obj); return Objects.equals(representation, other.representation); } - } -- cgit v1.2.3-70-g09d2