From 6ccc179ea305fc27ae121253b1d1f172bad676fd Mon Sep 17 00:00:00 2001 From: Kristóf Marussy Date: Tue, 13 Dec 2022 03:21:58 +0100 Subject: refactor(store): simplify return types Prefers sealed non-generic interfaces over wildcard types to avoid confusion about method return types, especially in collections (see SonarQube rule java:S1452). --- .../model/internal/DecisionTreeCursor.java | 14 +-- .../query/viatra/ViatraQueryableModelStore.java | 28 +++--- .../query/viatra/internal/RelationalScope.java | 7 +- .../viatra/internal/ViatraQueryableModel.java | 8 +- .../internal/context/RelationalRuntimeContext.java | 28 +++--- .../query/viatra/internal/pquery/DNF2PQuery.java | 15 ++- .../internal/pquery/RelationViewWrapper.java | 6 +- .../internal/viewupdate/ModelUpdateListener.java | 21 +++-- .../internal/viewupdate/ViewUpdateTranslator.java | 5 +- .../tools/refinery/store/map/AnyVersionedMap.java | 5 + .../main/java/tools/refinery/store/map/Cursor.java | 29 +++--- .../tools/refinery/store/map/VersionedMap.java | 20 ++-- .../store/map/VersionedMapStoreConfiguration.java | 20 ++-- .../refinery/store/map/VersionedMapStoreImpl.java | 22 ++--- .../refinery/store/map/internal/MapCursor.java | 88 ++++++++++-------- .../refinery/store/map/internal/MapDiffCursor.java | 23 +++-- .../store/map/internal/VersionedMapImpl.java | 103 ++++++++------------- .../java/tools/refinery/store/model/Model.java | 28 +++--- .../refinery/store/model/ModelDiffCursor.java | 21 +++-- .../tools/refinery/store/model/ModelStore.java | 15 +-- .../tools/refinery/store/model/ModelStoreImpl.java | 41 ++++---- .../refinery/store/model/internal/ModelImpl.java | 41 ++++---- .../internal/SimilarRelationEquivalenceClass.java | 12 ++- .../model/representation/AnyAuxiliaryData.java | 4 + .../representation/AnyDataRepresentation.java | 9 ++ .../store/model/representation/AnyRelation.java | 9 ++ .../store/model/representation/AuxiliaryData.java | 2 +- .../model/representation/DataRepresentation.java | 5 +- .../store/model/representation/Relation.java | 3 +- .../refinery/store/query/QueryableModelStore.java | 10 +- .../tools/refinery/store/query/atom/Modality.java | 8 ++ .../store/query/atom/RelationViewAtom.java | 8 +- .../refinery/store/query/view/AnyRelationView.java | 13 +++ .../store/query/view/FilteredRelationView.java | 15 +++ .../store/query/view/KeyOnlyRelationView.java | 16 ++++ .../refinery/store/query/view/RelationView.java | 29 +++--- .../map/tests/fuzz/ContentEqualsFuzzTest.java | 52 ++++------- .../store/map/tests/utils/MapTestEnvironment.java | 38 +++----- 38 files changed, 437 insertions(+), 384 deletions(-) create mode 100644 subprojects/store/src/main/java/tools/refinery/store/map/AnyVersionedMap.java create mode 100644 subprojects/store/src/main/java/tools/refinery/store/model/representation/AnyAuxiliaryData.java create mode 100644 subprojects/store/src/main/java/tools/refinery/store/model/representation/AnyDataRepresentation.java create mode 100644 subprojects/store/src/main/java/tools/refinery/store/model/representation/AnyRelation.java create mode 100644 subprojects/store/src/main/java/tools/refinery/store/query/view/AnyRelationView.java diff --git a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/DecisionTreeCursor.java b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/DecisionTreeCursor.java index 727a9528..a1fdc73d 100644 --- a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/DecisionTreeCursor.java +++ b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/DecisionTreeCursor.java @@ -1,13 +1,11 @@ package tools.refinery.language.semantics.model.internal; import tools.refinery.store.map.Cursor; -import tools.refinery.store.map.VersionedMap; -import tools.refinery.store.tuple.Tuple; import tools.refinery.store.model.representation.TruthValue; +import tools.refinery.store.tuple.Tuple; import java.util.ArrayDeque; import java.util.Deque; -import java.util.List; class DecisionTreeCursor implements Cursor { static final int STATE_FINISH = Integer.MAX_VALUE; @@ -81,14 +79,4 @@ class DecisionTreeCursor implements Cursor { key = Tuple.of(rawTuple); return true; } - - @Override - public boolean isDirty() { - return false; - } - - @Override - public List> getDependingMaps() { - return List.of(); - } } 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 37cd91a6..94d2db4f 100644 --- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/ViatraQueryableModelStore.java +++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/ViatraQueryableModelStore.java @@ -5,13 +5,17 @@ import tools.refinery.store.model.ModelDiffCursor; import tools.refinery.store.model.ModelStore; import tools.refinery.store.model.ModelStoreImpl; import tools.refinery.store.model.RelationLike; +import tools.refinery.store.model.representation.AnyDataRepresentation; import tools.refinery.store.model.representation.DataRepresentation; -import tools.refinery.store.query.*; +import tools.refinery.store.query.DNF; +import tools.refinery.store.query.DNFAnd; +import tools.refinery.store.query.QueryableModel; +import tools.refinery.store.query.QueryableModelStore; import tools.refinery.store.query.atom.*; 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.view.RelationView; +import tools.refinery.store.query.view.AnyRelationView; import java.util.Collections; import java.util.HashMap; @@ -21,11 +25,11 @@ import java.util.Set; public class ViatraQueryableModelStore implements QueryableModelStore { protected final ModelStore store; - protected final Set> relationViews; + protected final Set relationViews; protected final Map> predicates; - public ViatraQueryableModelStore(ModelStore store, Set> relationViews, + public ViatraQueryableModelStore(ModelStore store, Set relationViews, Set predicates) { this.store = store; validateViews(store.getDataRepresentations(), relationViews); @@ -34,13 +38,13 @@ public class ViatraQueryableModelStore implements QueryableModelStore { this.predicates = initPredicates(predicates); } - public ViatraQueryableModelStore(Set> dataRepresentations, - Set> relationViews, Set predicates) { + public ViatraQueryableModelStore(Set dataRepresentations, + Set relationViews, Set predicates) { this(new ModelStoreImpl(dataRepresentations), relationViews, predicates); } - private void validateViews(Set> dataRepresentations, Set> relationViews) { - for (RelationView relationView : relationViews) { + private void validateViews(Set dataRepresentations, Set relationViews) { + for (var relationView : relationViews) { if (!dataRepresentations.contains(relationView.getRepresentation())) { throw new IllegalArgumentException("%s %s added to %s without a referred representation.".formatted( DataRepresentation.class.getSimpleName(), relationView.getName(), @@ -49,7 +53,7 @@ public class ViatraQueryableModelStore implements QueryableModelStore { } } - private void validatePredicates(Set> relationViews, Set predicates) { + private void validatePredicates(Set relationViews, Set predicates) { for (DNF dnfPredicate : predicates) { for (DNFAnd clause : dnfPredicate.getClauses()) { for (DNFAtom atom : clause.constraints()) { @@ -65,7 +69,7 @@ public class ViatraQueryableModelStore implements QueryableModelStore { } } - private void validateRelationAtom(Set> relationViews, DNF dnfPredicate, + private void validateRelationAtom(Set relationViews, DNF dnfPredicate, RelationViewAtom relationViewAtom) { if (!relationViews.contains(relationViewAtom.getTarget())) { throw new IllegalArgumentException( @@ -100,12 +104,12 @@ public class ViatraQueryableModelStore implements QueryableModelStore { } @Override - public Set> getDataRepresentations() { + public Set getDataRepresentations() { return store.getDataRepresentations(); } @Override - public Set> getViews() { + public Set getViews() { return this.relationViews; } 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 5ddad67d..133c4c72 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,19 +6,20 @@ import org.eclipse.viatra.query.runtime.api.scope.IEngineContext; import org.eclipse.viatra.query.runtime.api.scope.IIndexingErrorListener; import org.eclipse.viatra.query.runtime.api.scope.QueryScope; import tools.refinery.store.model.Model; -import tools.refinery.store.tuple.Tuple; import tools.refinery.store.model.representation.Relation; import tools.refinery.store.query.viatra.internal.context.RelationalEngineContext; import tools.refinery.store.query.viatra.internal.viewupdate.ModelUpdateListener; -import tools.refinery.store.query.view.RelationView; +import tools.refinery.store.query.view.AnyRelationView; +import tools.refinery.store.tuple.Tuple; import java.util.Set; public class RelationalScope extends QueryScope { private final Model model; + private final ModelUpdateListener updateListener; - public RelationalScope(Model model, Set> relationViews) { + public RelationalScope(Model model, Set relationViews) { this.model = model; this.updateListener = new ModelUpdateListener(relationViews); } diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/ViatraQueryableModel.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/ViatraQueryableModel.java index cd9fb180..5b06e266 100644 --- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/ViatraQueryableModel.java +++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/ViatraQueryableModel.java @@ -8,6 +8,7 @@ import tools.refinery.store.map.Cursor; import tools.refinery.store.map.DiffCursor; import tools.refinery.store.model.Model; import tools.refinery.store.model.ModelDiffCursor; +import tools.refinery.store.model.representation.AnyDataRepresentation; import tools.refinery.store.model.representation.DataRepresentation; import tools.refinery.store.model.representation.Relation; import tools.refinery.store.query.QueryableModel; @@ -66,7 +67,7 @@ public class ViatraQueryableModel implements QueryableModel { } @Override - public Set> getDataRepresentations() { + public Set getDataRepresentations() { return model.getDataRepresentations(); } @@ -113,7 +114,7 @@ public class ViatraQueryableModel implements QueryableModel { } @Override - public long getSize(DataRepresentation representation) { + public long getSize(AnyDataRepresentation representation) { return model.getSize(representation); } @@ -207,7 +208,8 @@ public class ViatraQueryableModel implements QueryableModel { private void restoreWithDiffReplay(long state) { var modelDiffCursor = getDiffCursor(state); - for (DataRepresentation dataRepresentation : this.getDataRepresentations()) { + for (AnyDataRepresentation anyDataRepresentation : this.getDataRepresentations()) { + var dataRepresentation = (DataRepresentation) anyDataRepresentation; restoreRepresentationWithDiffReplay(modelDiffCursor, dataRepresentation); } } 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 c007d630..e01525e0 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 @@ -9,6 +9,7 @@ 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.AnyRelationView; import tools.refinery.store.query.view.RelationView; import java.lang.reflect.InvocationTargetException; @@ -53,7 +54,7 @@ public class RelationalRuntimeContext implements IQueryRuntimeContext { @Override public boolean isIndexed(IInputKey key, IndexingService service) { if (key instanceof RelationView relationalKey) { - return this.modelUpdateListener.containsRelationalView(relationalKey); + return this.modelUpdateListener.containsRelationView(relationalKey); } else { return false; } @@ -66,11 +67,10 @@ public class RelationalRuntimeContext implements IQueryRuntimeContext { } } - @SuppressWarnings("squid:S1452") - RelationView checkKey(IInputKey key) { + AnyRelationView checkKey(IInputKey key) { if (key instanceof RelationViewWrapper wrappedKey) { var relationViewKey = wrappedKey.getWrappedKey(); - if (modelUpdateListener.containsRelationalView(relationViewKey)) { + if (modelUpdateListener.containsRelationView(relationViewKey)) { return relationViewKey; } else { throw new IllegalStateException("Query is asking for non-indexed key"); @@ -82,8 +82,8 @@ public class RelationalRuntimeContext implements IQueryRuntimeContext { @Override public int countTuples(IInputKey key, TupleMask seedMask, ITuple seed) { - RelationView relationalViewKey = checkKey(key); - Iterable allObjects = relationalViewKey.getAll(model); + var relationViewKey = checkKey(key); + Iterable allObjects = relationViewKey.getAll(model); Iterable filteredBySeed = filter(allObjects, objectArray -> isMatching(objectArray, seedMask, seed)); Iterator iterator = filteredBySeed.iterator(); int result = 0; @@ -101,8 +101,8 @@ public class RelationalRuntimeContext implements IQueryRuntimeContext { @Override public Iterable enumerateTuples(IInputKey key, TupleMask seedMask, ITuple seed) { - RelationView relationalViewKey = checkKey(key); - Iterable allObjects = relationalViewKey.getAll(model); + var relationViewKey = checkKey(key); + Iterable allObjects = relationViewKey.getAll(model); Iterable filteredBySeed = filter(allObjects, objectArray -> isMatching(objectArray, seedMask, seed)); return map(filteredBySeed, Tuples::flatTupleOf); } @@ -125,21 +125,21 @@ public class RelationalRuntimeContext implements IQueryRuntimeContext { @Override public boolean containsTuple(IInputKey key, ITuple seed) { - RelationView relationalViewKey = checkKey(key); - return relationalViewKey.get(model, seed.getElements()); + var relationViewKey = checkKey(key); + return relationViewKey.get(model, seed.getElements()); } @Override public void addUpdateListener(IInputKey key, Tuple seed, IQueryRuntimeContextListener listener) { - RelationView relationalKey = checkKey(key); - this.modelUpdateListener.addListener(key, relationalKey, seed, listener); + var relationViewKey = (RelationView) checkKey(key); + this.modelUpdateListener.addListener(key, relationViewKey, seed, listener); } @Override public void removeUpdateListener(IInputKey key, Tuple seed, IQueryRuntimeContextListener listener) { - RelationView relationalKey = checkKey(key); - this.modelUpdateListener.removeListener(key, relationalKey, seed, listener); + var relationViewKey = checkKey(key); + this.modelUpdateListener.removeListener(key, relationViewKey, 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 98054161..aa3fba6e 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 @@ -2,7 +2,10 @@ package tools.refinery.store.query.viatra.internal.pquery; import org.eclipse.viatra.query.runtime.matchers.psystem.PBody; import org.eclipse.viatra.query.runtime.matchers.psystem.PVariable; -import org.eclipse.viatra.query.runtime.matchers.psystem.basicdeferred.*; +import org.eclipse.viatra.query.runtime.matchers.psystem.basicdeferred.Equality; +import org.eclipse.viatra.query.runtime.matchers.psystem.basicdeferred.ExportedParameter; +import org.eclipse.viatra.query.runtime.matchers.psystem.basicdeferred.Inequality; +import org.eclipse.viatra.query.runtime.matchers.psystem.basicdeferred.NegativePatternCall; import org.eclipse.viatra.query.runtime.matchers.psystem.basicenumerables.BinaryTransitiveClosure; import org.eclipse.viatra.query.runtime.matchers.psystem.basicenumerables.ConstantValue; import org.eclipse.viatra.query.runtime.matchers.psystem.basicenumerables.PositivePatternCall; @@ -10,9 +13,11 @@ 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.Tuple; import org.eclipse.viatra.query.runtime.matchers.tuple.Tuples; -import tools.refinery.store.query.*; +import tools.refinery.store.query.DNF; +import tools.refinery.store.query.DNFAnd; +import tools.refinery.store.query.Variable; import tools.refinery.store.query.atom.*; -import tools.refinery.store.query.view.RelationView; +import tools.refinery.store.query.view.AnyRelationView; import java.util.*; import java.util.stream.Collectors; @@ -22,7 +27,7 @@ public class DNF2PQuery { private final Map dnf2PQueryMap = new HashMap<>(); - private final Map, RelationViewWrapper> view2WrapperMap = new HashMap<>(); + private final Map view2WrapperMap = new HashMap<>(); public SimplePQuery translate(DNF dnfQuery) { if (translating.contains(dnfQuery)) { @@ -115,7 +120,7 @@ public class DNF2PQuery { return Tuples.flatTupleOf(variables); } - private RelationViewWrapper wrapView(RelationView relationView) { + private RelationViewWrapper wrapView(AnyRelationView relationView) { return view2WrapperMap.computeIfAbsent(relationView, RelationViewWrapper::new); } 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 2a4148dc..e48648bf 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 @@ -1,10 +1,10 @@ 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; +import tools.refinery.store.query.view.AnyRelationView; -public class RelationViewWrapper extends BaseInputKeyWrapper> { - public RelationViewWrapper(RelationView wrappedKey) { +public class RelationViewWrapper extends BaseInputKeyWrapper { + public RelationViewWrapper(AnyRelationView wrappedKey) { super(wrappedKey); } 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 1a2fcee7..6a1d06a9 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 @@ -3,6 +3,8 @@ 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.representation.AnyRelation; +import tools.refinery.store.query.view.AnyRelationView; import tools.refinery.store.tuple.Tuple; import tools.refinery.store.model.representation.Relation; import tools.refinery.store.query.view.RelationView; @@ -16,24 +18,24 @@ public class ModelUpdateListener { /** * Collections of Relations and their Views. */ - private final Map, Set>> relation2View; + private final Map> relation2View; /** * Collection of Views and their buffers. */ - private final Map, Set>> view2Buffers; + private final Map>> view2Buffers; - public ModelUpdateListener(Set> relationViews) { + public ModelUpdateListener(Set relationViews) { this.relation2View = new HashMap<>(); this.view2Buffers = new HashMap<>(); - for (RelationView relationView : relationViews) { + for (var relationView : relationViews) { registerView(relationView); } } - private void registerView(RelationView view) { - Relation relation = view.getRepresentation(); + private void registerView(AnyRelationView view) { + AnyRelation relation = view.getRepresentation(); // 1. register views to relations, if necessary var views = relation2View.computeIfAbsent(relation, x -> new HashSet<>()); @@ -43,7 +45,7 @@ public class ModelUpdateListener { view2Buffers.computeIfAbsent(view, x -> new HashSet<>()); } - public boolean containsRelationalView(RelationView relationalKey) { + public boolean containsRelationView(AnyRelationView relationalKey) { return view2Buffers.containsKey(relationalKey); } @@ -58,7 +60,7 @@ public class ModelUpdateListener { } } - public void removeListener(IInputKey key, RelationView relationView, ITuple seed, + public void removeListener(IInputKey key, AnyRelationView relationView, ITuple seed, IQueryRuntimeContextListener listener) { if (view2Buffers.containsKey(relationView)) { Set> buffers = this.view2Buffers.get(relationView); @@ -92,8 +94,9 @@ public class ModelUpdateListener { public boolean hasChanges() { for (var bufferCollection : this.view2Buffers.values()) { for (ViewUpdateBuffer buffer : bufferCollection) { - if (buffer.hasChanges()) + if (buffer.hasChanges()) { return true; + } } } return false; 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 74d0b366..c324c84a 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 @@ -4,8 +4,9 @@ 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; -import tools.refinery.store.tuple.Tuple; +import tools.refinery.store.query.view.AnyRelationView; import tools.refinery.store.query.view.RelationView; +import tools.refinery.store.tuple.Tuple; import java.util.Objects; @@ -27,7 +28,7 @@ public class ViewUpdateTranslator { this.listener = listener; } - public boolean equals(IInputKey wrappedKey, RelationView relationView, ITuple seed, + public boolean equals(IInputKey wrappedKey, AnyRelationView relationView, ITuple seed, IQueryRuntimeContextListener listener) { return this.wrappedKey == wrappedKey && key == relationView && filter.equals(seed) && this.listener == listener; } diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/AnyVersionedMap.java b/subprojects/store/src/main/java/tools/refinery/store/map/AnyVersionedMap.java new file mode 100644 index 00000000..b94b9f38 --- /dev/null +++ b/subprojects/store/src/main/java/tools/refinery/store/map/AnyVersionedMap.java @@ -0,0 +1,5 @@ +package tools.refinery.store.map; + +public sealed interface AnyVersionedMap extends Versioned permits VersionedMap { + long getSize(); +} diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/Cursor.java b/subprojects/store/src/main/java/tools/refinery/store/map/Cursor.java index 9c465ddc..b420585c 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/map/Cursor.java +++ b/subprojects/store/src/main/java/tools/refinery/store/map/Cursor.java @@ -1,14 +1,21 @@ package tools.refinery.store.map; -import java.util.List; - -public interface Cursor { - public K getKey(); - public V getValue(); - public boolean isTerminated(); - public boolean move(); - public boolean isDirty(); - - @SuppressWarnings("squid:S1452") - public List> getDependingMaps(); +import java.util.Set; + +public interface Cursor { + K getKey(); + + V getValue(); + + boolean isTerminated(); + + boolean move(); + + default boolean isDirty() { + return false; + } + + default Set getDependingMaps() { + return Set.of(); + } } diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/VersionedMap.java b/subprojects/store/src/main/java/tools/refinery/store/map/VersionedMap.java index a8a64d08..31985e94 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/map/VersionedMap.java +++ b/subprojects/store/src/main/java/tools/refinery/store/map/VersionedMap.java @@ -1,13 +1,13 @@ package tools.refinery.store.map; -public interface VersionedMap extends Versioned{ - public V get(K key); - public Cursor getAll(); - - public V put(K key, V value); - public void putAll(Cursor cursor); - - public long getSize(); - - public DiffCursor getDiffCursor(long state); +public non-sealed interface VersionedMap extends AnyVersionedMap { + V get(K key); + + Cursor getAll(); + + V put(K key, V value); + + void putAll(Cursor cursor); + + DiffCursor getDiffCursor(long state); } diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/VersionedMapStoreConfiguration.java b/subprojects/store/src/main/java/tools/refinery/store/map/VersionedMapStoreConfiguration.java index 723e5ec4..3856460d 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/map/VersionedMapStoreConfiguration.java +++ b/subprojects/store/src/main/java/tools/refinery/store/map/VersionedMapStoreConfiguration.java @@ -1,14 +1,14 @@ package tools.refinery.store.map; public class VersionedMapStoreConfiguration { - + public VersionedMapStoreConfiguration() { - + } - public VersionedMapStoreConfiguration(boolean immutableWhenCommiting, boolean sharedNodeCacheInStore, + public VersionedMapStoreConfiguration(boolean immutableWhenCommitting, boolean sharedNodeCacheInStore, boolean sharedNodeCacheInStoreGroups) { super(); - this.immutableWhenCommiting = immutableWhenCommiting; + this.immutableWhenCommitting = immutableWhenCommitting; this.sharedNodeCacheInStore = sharedNodeCacheInStore; this.sharedNodeCacheInStoreGroups = sharedNodeCacheInStoreGroups; } @@ -18,13 +18,13 @@ public class VersionedMapStoreConfiguration { * by releasing immutable nodes, but it may decrease performance by recreating * immutable nodes upon changes (some evidence). */ - private boolean immutableWhenCommiting = true; - public boolean isImmutableWhenCommiting() { - return immutableWhenCommiting; + private boolean immutableWhenCommitting = true; + public boolean isImmutableWhenCommitting() { + return immutableWhenCommitting; } /** - * If true, all subnodes are cached within a {@link VersionedMapStore}. It + * If true, all sub-nodes are cached within a {@link VersionedMapStore}. It * decreases the memory requirements. It may increase performance by discovering * existing immutable copy of a node (some evidence). Additional overhead may * decrease performance (no example found). The option permits the efficient @@ -34,9 +34,9 @@ public class VersionedMapStoreConfiguration { public boolean isSharedNodeCacheInStore() { return sharedNodeCacheInStore; } - + /** - * If true, all subnodes are cached within a group of + * If true, all sub-nodes are cached within a group of * {@link VersionedMapStoreImpl#createSharedVersionedMapStores(int, ContinousHashProvider, Object, VersionedMapStoreConfiguration)}. * If {@link VersionedMapStoreConfiguration#sharedNodeCacheInStore} is * false, then it has currently no impact. diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/VersionedMapStoreImpl.java b/subprojects/store/src/main/java/tools/refinery/store/map/VersionedMapStoreImpl.java index a626a5e8..113874e7 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/map/VersionedMapStoreImpl.java +++ b/subprojects/store/src/main/java/tools/refinery/store/map/VersionedMapStoreImpl.java @@ -1,22 +1,15 @@ package tools.refinery.store.map; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - import tools.refinery.store.map.internal.ImmutableNode; import tools.refinery.store.map.internal.MapDiffCursor; import tools.refinery.store.map.internal.Node; import tools.refinery.store.map.internal.VersionedMapImpl; +import java.util.*; + public class VersionedMapStoreImpl implements VersionedMapStore { // Configuration - private final boolean immutableWhenCommiting; + private final boolean immutableWhenCommitting; // Static data protected final ContinousHashProvider hashProvider; @@ -29,7 +22,7 @@ public class VersionedMapStoreImpl implements VersionedMapStore { public VersionedMapStoreImpl(ContinousHashProvider hashProvider, V defaultValue, VersionedMapStoreConfiguration config) { - this.immutableWhenCommiting = config.isImmutableWhenCommiting(); + this.immutableWhenCommitting = config.isImmutableWhenCommitting(); this.hashProvider = hashProvider; this.defaultValue = defaultValue; if (config.isSharedNodeCacheInStore()) { @@ -41,7 +34,7 @@ public class VersionedMapStoreImpl implements VersionedMapStore { private VersionedMapStoreImpl(ContinousHashProvider hashProvider, V defaultValue, Map, ImmutableNode> nodeCache, VersionedMapStoreConfiguration config) { - this.immutableWhenCommiting = config.isImmutableWhenCommiting(); + this.immutableWhenCommitting = config.isImmutableWhenCommitting(); this.hashProvider = hashProvider; this.defaultValue = defaultValue; this.nodeCache = nodeCache; @@ -77,7 +70,7 @@ public class VersionedMapStoreImpl implements VersionedMapStore { ContinousHashProvider hashProvider, V defaultValue) { return createSharedVersionedMapStores(amount, hashProvider, defaultValue, new VersionedMapStoreConfiguration()); } - + @Override public synchronized Set getStates() { return new HashSet<>(states.keySet()); @@ -93,7 +86,6 @@ public class VersionedMapStoreImpl implements VersionedMapStore { ImmutableNode data = revert(state); return new VersionedMapImpl<>(this, hashProvider, defaultValue, data); } - public synchronized ImmutableNode revert(long state) { if (states.containsKey(state)) { @@ -118,7 +110,7 @@ public class VersionedMapStoreImpl implements VersionedMapStore { throw new IllegalStateException("Map store run out of Id-s"); long id = nextID++; this.states.put(id, immutable); - if (this.immutableWhenCommiting) { + if (this.immutableWhenCommitting) { mapToUpdateRoot.setRoot(immutable); } return id; diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/internal/MapCursor.java b/subprojects/store/src/main/java/tools/refinery/store/map/internal/MapCursor.java index b90f5b71..1698830f 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/map/internal/MapCursor.java +++ b/subprojects/store/src/main/java/tools/refinery/store/map/internal/MapCursor.java @@ -1,128 +1,136 @@ package tools.refinery.store.map.internal; +import tools.refinery.store.map.AnyVersionedMap; +import tools.refinery.store.map.Cursor; +import tools.refinery.store.map.VersionedMap; + import java.util.ArrayDeque; import java.util.ConcurrentModificationException; import java.util.Iterator; -import java.util.List; - -import tools.refinery.store.map.Cursor; -import tools.refinery.store.map.VersionedMap; +import java.util.Set; -public class MapCursor implements Cursor { +public class MapCursor implements Cursor { // Constants static final int INDEX_START = -1; static final int INDEX_FINISH = -2; - + // Tree stack - ArrayDeque> nodeStack; + ArrayDeque> nodeStack; ArrayDeque nodeIndexStack; int dataIndex; - + // Values K key; V value; - + // Hash code for checking concurrent modifications - final VersionedMap map; - final int creationHash; - - public MapCursor(Node root, VersionedMap map) { + final VersionedMap map; + final int creationHash; + + public MapCursor(Node root, VersionedMap map) { // Initializing tree stack super(); this.nodeStack = new ArrayDeque<>(); this.nodeIndexStack = new ArrayDeque<>(); - if(root != null) { + if (root != null) { this.nodeStack.add(root); this.nodeIndexStack.push(INDEX_START); } - + this.dataIndex = INDEX_START; - + // Initializing cache this.key = null; this.value = null; - + // Initializing state - this.map=map; + this.map = map; this.creationHash = map.hashCode(); } - + public K getKey() { return key; } - + public V getValue() { return value; } - + public boolean isTerminated() { return this.nodeStack.isEmpty(); } - + public boolean move() { - if(isDirty()) { + if (isDirty()) { throw new ConcurrentModificationException(); } - if(!isTerminated()) { - boolean result = this.nodeStack.peek().moveToNext(this); - if(this.nodeIndexStack.size() != this.nodeStack.size()) { + if (!isTerminated()) { + var node = this.nodeStack.peek(); + if (node == null) { + throw new IllegalStateException("Cursor is not terminated but the current node is missing"); + } + boolean result = node.moveToNext(this); + if (this.nodeIndexStack.size() != this.nodeStack.size()) { throw new IllegalArgumentException("Node stack is corrupted by illegal moves!"); } return result; } return false; } + public boolean skipCurrentNode() { nodeStack.pop(); nodeIndexStack.pop(); dataIndex = INDEX_FINISH; return move(); } + @Override public boolean isDirty() { return this.map.hashCode() != this.creationHash; } + @Override - public List> getDependingMaps() { - return List.of(this.map); + public Set getDependingMaps() { + return Set.of(this.map); } - - public static boolean sameSubnode(MapCursor cursor1, MapCursor cursor2) { + + public static boolean sameSubnode(MapCursor cursor1, MapCursor cursor2) { Node nodeOfCursor1 = cursor1.nodeStack.peek(); Node nodeOfCursor2 = cursor2.nodeStack.peek(); - if(nodeOfCursor1 != null && nodeOfCursor2 != null) { + if (nodeOfCursor1 != null && nodeOfCursor2 != null) { return nodeOfCursor1.equals(nodeOfCursor2); } else { return false; } } - + /** - * * @param * @param * @param cursor1 * @param cursor2 - * @return Positive number if cursor 1 is behind, negative number if cursor 2 is behind, and 0 if they are at the same position. + * @return Positive number if cursor 1 is behind, negative number if cursor 2 is behind, and 0 if they are at the + * same position. */ - public static int compare(MapCursor cursor1, MapCursor cursor2) { + public static int compare(MapCursor cursor1, MapCursor cursor2) { // two cursors are equally deep Iterator stack1 = cursor1.nodeIndexStack.descendingIterator(); Iterator stack2 = cursor2.nodeIndexStack.descendingIterator(); - if(stack1.hasNext()) { - if(!stack2.hasNext()) { + if (stack1.hasNext()) { + if (!stack2.hasNext()) { // stack 2 has no more element, thus stack 1 is deeper return 1; } int val1 = stack1.next(); int val2 = stack2.next(); - if(val1 < val2) { + if (val1 < val2) { return -1; - } else if(val2 < val1) { + } else if (val2 < val1) { return 1; } } - if(stack2.hasNext()) { + if (stack2.hasNext()) { // stack 2 has more element, thus stack 2 is deeper return 1; } diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/internal/MapDiffCursor.java b/subprojects/store/src/main/java/tools/refinery/store/map/internal/MapDiffCursor.java index a4ca813c..9cd78113 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/map/internal/MapDiffCursor.java +++ b/subprojects/store/src/main/java/tools/refinery/store/map/internal/MapDiffCursor.java @@ -1,12 +1,13 @@ package tools.refinery.store.map.internal; -import java.util.List; -import java.util.stream.Stream; - +import tools.refinery.store.map.AnyVersionedMap; import tools.refinery.store.map.ContinousHashProvider; import tools.refinery.store.map.Cursor; import tools.refinery.store.map.DiffCursor; -import tools.refinery.store.map.VersionedMap; + +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; /** * A cursor representing the difference between two states of a map. @@ -18,10 +19,10 @@ public class MapDiffCursor implements DiffCursor, Cursor { /** * Default nodeId representing missing elements. */ - private V defaultValue; - private MapCursor cursor1; - private MapCursor cursor2; - private ContinousHashProvider hashProvider; + private final V defaultValue; + private final MapCursor cursor1; + private final MapCursor cursor2; + private final ContinousHashProvider hashProvider; // Values private K key; @@ -75,8 +76,10 @@ public class MapDiffCursor implements DiffCursor, Cursor { } @Override - public List> getDependingMaps() { - return Stream.concat(cursor1.getDependingMaps().stream(), cursor2.getDependingMaps().stream()).toList(); + public Set getDependingMaps() { + return Stream.concat(cursor1.getDependingMaps().stream(), cursor2.getDependingMaps().stream()) + .map(AnyVersionedMap.class::cast) + .collect(Collectors.toUnmodifiableSet()); } protected void updateState() { diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/internal/VersionedMapImpl.java b/subprojects/store/src/main/java/tools/refinery/store/map/internal/VersionedMapImpl.java index 346fe596..866e7b33 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/map/internal/VersionedMapImpl.java +++ b/subprojects/store/src/main/java/tools/refinery/store/map/internal/VersionedMapImpl.java @@ -1,61 +1,59 @@ package tools.refinery.store.map.internal; +import tools.refinery.store.map.*; + import java.util.Iterator; import java.util.LinkedList; import java.util.List; -import tools.refinery.store.map.ContinousHashProvider; -import tools.refinery.store.map.Cursor; -import tools.refinery.store.map.DiffCursor; -import tools.refinery.store.map.VersionedMap; -import tools.refinery.store.map.VersionedMapStoreImpl; - /** * Not threadSafe in itself - * @author Oszkar Semerath * * @param * @param + * @author Oszkar Semerath */ -public class VersionedMapImpl implements VersionedMap{ - protected final VersionedMapStoreImpl store; - +public class VersionedMapImpl implements VersionedMap { + protected final VersionedMapStoreImpl store; + protected final ContinousHashProvider hashProvider; + protected final V defaultValue; - protected Node root; - - private OldValueBox oldValueBox = new OldValueBox<>(); - + protected Node root; + + private final OldValueBox oldValueBox = new OldValueBox<>(); + public VersionedMapImpl( - VersionedMapStoreImpl store, + VersionedMapStoreImpl store, ContinousHashProvider hashProvider, - V defaultValue) - { + V defaultValue) { this.store = store; this.hashProvider = hashProvider; this.defaultValue = defaultValue; this.root = null; } + public VersionedMapImpl( - VersionedMapStoreImpl store, + VersionedMapStoreImpl store, ContinousHashProvider hashProvider, - V defaultValue, Node data) - { + V defaultValue, Node data) { this.store = store; this.hashProvider = hashProvider; this.defaultValue = defaultValue; this.root = data; } - + public V getDefaultValue() { return defaultValue; } + public ContinousHashProvider getHashProvider() { return hashProvider; } + @Override public V put(K key, V value) { - if(root!=null) { + if (root != null) { root = root.putValue(key, value, oldValueBox, hashProvider, defaultValue, hashProvider.getHash(key, 0), 0); return oldValueBox.getOldValue(); } else { @@ -63,39 +61,40 @@ public class VersionedMapImpl implements VersionedMap{ return defaultValue; } } - + @Override public void putAll(Cursor cursor) { - if(cursor.getDependingMaps().contains(this)) { + if (cursor.getDependingMaps().contains(this)) { List keys = new LinkedList<>(); List values = new LinkedList<>(); - while(cursor.move()) { + while (cursor.move()) { keys.add(cursor.getKey()); values.add(cursor.getValue()); } Iterator keyIterator = keys.iterator(); Iterator valueIterator = values.iterator(); - while(keyIterator.hasNext()) { + while (keyIterator.hasNext()) { this.put(keyIterator.next(), valueIterator.next()); } } else { - while(cursor.move()) { + while (cursor.move()) { this.put(cursor.getKey(), cursor.getValue()); } } } - + @Override public V get(K key) { - if(root!=null) { + if (root != null) { return root.getValue(key, hashProvider, defaultValue, hashProvider.getHash(key, 0), 0); } else { return defaultValue; } } + @Override public long getSize() { - if(root == null) { + if (root == null) { return 0; } else { return root.getSize(); @@ -104,22 +103,24 @@ public class VersionedMapImpl implements VersionedMap{ @Override public Cursor getAll() { - return new MapCursor<>(this.root,this); + return new MapCursor<>(this.root, this); } + @Override public DiffCursor getDiffCursor(long toVersion) { Cursor fromCursor = this.getAll(); VersionedMap toMap = this.store.createMap(toVersion); Cursor toCursor = toMap.getAll(); - return new MapDiffCursor<>(this.hashProvider,this.defaultValue, fromCursor, toCursor); - + return new MapDiffCursor<>(this.hashProvider, this.defaultValue, fromCursor, toCursor); + } - + @Override public long commit() { - return this.store.commit(root,this); + return this.store.commit(root, this); } + public void setRoot(Node root) { this.root = root; } @@ -128,44 +129,20 @@ public class VersionedMapImpl implements VersionedMap{ public void restore(long state) { root = this.store.revert(state); } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((root == null) ? 0 : root.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - VersionedMapImpl other = (VersionedMapImpl) obj; - if (root == null) { - if (other.root != null) - return false; - } else if (!root.equals(other.root)) - return false; - return true; - } + public void prettyPrint() { StringBuilder s = new StringBuilder(); - if(this.root != null) { + if (this.root != null) { this.root.prettyPrint(s, 0, -1); System.out.println(s.toString()); } else { System.out.println("empty tree"); } } + public void checkIntegrity() { - if(this.root != null) { + if (this.root != null) { this.root.checkIntegrity(hashProvider, defaultValue, 0); } } - } diff --git a/subprojects/store/src/main/java/tools/refinery/store/model/Model.java b/subprojects/store/src/main/java/tools/refinery/store/model/Model.java index a42d711a..69f57389 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/model/Model.java +++ b/subprojects/store/src/main/java/tools/refinery/store/model/Model.java @@ -1,20 +1,24 @@ package tools.refinery.store.model; -import java.util.Set; - import tools.refinery.store.map.Cursor; import tools.refinery.store.map.Versioned; +import tools.refinery.store.model.representation.AnyDataRepresentation; import tools.refinery.store.model.representation.DataRepresentation; -public interface Model extends Versioned{ - @SuppressWarnings("squid:S1452") - Set> getDataRepresentations(); - - V get(DataRepresentation representation, K key); - Cursor getAll(DataRepresentation representation); - V put(DataRepresentation representation, K key, V value); - void putAll(DataRepresentation representation, Cursor cursor); - long getSize(DataRepresentation representation); - +import java.util.Set; + +public interface Model extends Versioned { + Set getDataRepresentations(); + + V get(DataRepresentation representation, K key); + + Cursor getAll(DataRepresentation representation); + + V put(DataRepresentation representation, K key, V value); + + void putAll(DataRepresentation representation, Cursor cursor); + + long getSize(AnyDataRepresentation representation); + ModelDiffCursor getDiffCursor(long to); } diff --git a/subprojects/store/src/main/java/tools/refinery/store/model/ModelDiffCursor.java b/subprojects/store/src/main/java/tools/refinery/store/model/ModelDiffCursor.java index 91990fa6..d5bb541b 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/model/ModelDiffCursor.java +++ b/subprojects/store/src/main/java/tools/refinery/store/model/ModelDiffCursor.java @@ -1,26 +1,27 @@ package tools.refinery.store.model; -import java.util.Map; - import tools.refinery.store.map.Cursor; import tools.refinery.store.map.DiffCursor; +import tools.refinery.store.model.representation.AnyDataRepresentation; import tools.refinery.store.model.representation.DataRepresentation; +import java.util.Map; + public class ModelDiffCursor { - final Map,DiffCursor> diffcursors; + final Map> diffCursors; - public ModelDiffCursor(Map, DiffCursor> diffcursors) { + public ModelDiffCursor(Map> diffCursors) { super(); - this.diffcursors = diffcursors; + this.diffCursors = diffCursors; } - + @SuppressWarnings("unchecked") - public DiffCursor getCursor(DataRepresentation representation) { - Cursor cursor = diffcursors.get(representation); - if(cursor != null) { + public DiffCursor getCursor(DataRepresentation representation) { + Cursor cursor = diffCursors.get(representation); + if (cursor != null) { return (DiffCursor) cursor; } else { - throw new IllegalArgumentException("ModelCursor does not contain cursor for representation "+representation); + throw new IllegalArgumentException("ModelCursor does not contain cursor for representation " + representation); } } } diff --git a/subprojects/store/src/main/java/tools/refinery/store/model/ModelStore.java b/subprojects/store/src/main/java/tools/refinery/store/model/ModelStore.java index 682a0e78..84b67765 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/model/ModelStore.java +++ b/subprojects/store/src/main/java/tools/refinery/store/model/ModelStore.java @@ -1,16 +1,17 @@ package tools.refinery.store.model; -import java.util.Set; +import tools.refinery.store.model.representation.AnyDataRepresentation; -import tools.refinery.store.model.representation.DataRepresentation; +import java.util.Set; public interface ModelStore { - @SuppressWarnings("squid:S1452") - Set> getDataRepresentations(); - + Set getDataRepresentations(); + Model createModel(); + Model createModel(long state); - + Set getStates(); + ModelDiffCursor getDiffCursor(long from, long to); -} \ No newline at end of file +} diff --git a/subprojects/store/src/main/java/tools/refinery/store/model/ModelStoreImpl.java b/subprojects/store/src/main/java/tools/refinery/store/model/ModelStoreImpl.java index d08cf0f8..2f73a0e5 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/model/ModelStoreImpl.java +++ b/subprojects/store/src/main/java/tools/refinery/store/model/ModelStoreImpl.java @@ -3,6 +3,7 @@ package tools.refinery.store.model; import tools.refinery.store.map.*; import tools.refinery.store.model.internal.ModelImpl; import tools.refinery.store.model.internal.SimilarRelationEquivalenceClass; +import tools.refinery.store.model.representation.AnyDataRepresentation; import tools.refinery.store.model.representation.AuxiliaryData; import tools.refinery.store.model.representation.DataRepresentation; import tools.refinery.store.model.representation.Relation; @@ -13,26 +14,26 @@ import java.util.Map.Entry; public class ModelStoreImpl implements ModelStore { - private final Map, VersionedMapStore> stores; + private final Map> stores; - public ModelStoreImpl(Set> dataRepresentations) { + public ModelStoreImpl(Set dataRepresentations) { stores = initStores(dataRepresentations); } - private Map, VersionedMapStore> initStores( - Set> dataRepresentations) { - Map, VersionedMapStore> result = new HashMap<>(); + private Map> initStores( + Set dataRepresentations) { + Map> result = new HashMap<>(); Map>> symbolRepresentationsPerHashPerArity = new HashMap<>(); - for (DataRepresentation dataRepresentation : dataRepresentations) { + for (AnyDataRepresentation dataRepresentation : dataRepresentations) { if (dataRepresentation instanceof Relation symbolRepresentation) { addOrCreate(symbolRepresentationsPerHashPerArity, new SimilarRelationEquivalenceClass(symbolRepresentation), symbolRepresentation); - } else if (dataRepresentation instanceof AuxiliaryData) { - VersionedMapStoreImpl store = new VersionedMapStoreImpl<>(dataRepresentation.getHashProvider(), - dataRepresentation.getDefaultValue()); - result.put(dataRepresentation, store); + } else if (dataRepresentation instanceof AuxiliaryData auxiliaryData) { + VersionedMapStoreImpl store = new VersionedMapStoreImpl<>(auxiliaryData.getHashProvider(), + auxiliaryData.getDefaultValue()); + result.put(auxiliaryData, store); } else { throw new UnsupportedOperationException( "Model store does not have strategy to use " + dataRepresentation.getClass() + "!"); @@ -45,7 +46,7 @@ public class ModelStoreImpl implements ModelStore { return result; } - private void initRepresentationGroup(Map, VersionedMapStore> result, + private void initRepresentationGroup(Map> result, List> symbolGroup) { final ContinousHashProvider hashProvider = symbolGroup.get(0).getHashProvider(); final Object defaultValue = symbolGroup.get(0).getDefaultValue(); @@ -70,14 +71,14 @@ public class ModelStoreImpl implements ModelStore { } @Override - public Set> getDataRepresentations() { + public Set getDataRepresentations() { return this.stores.keySet(); } @Override public ModelImpl createModel() { - Map, VersionedMap> maps = new HashMap<>(); - for (Entry, VersionedMapStore> entry : this.stores.entrySet()) { + Map> maps = new HashMap<>(); + for (var entry : this.stores.entrySet()) { maps.put(entry.getKey(), entry.getValue().createMap()); } return new ModelImpl(this, maps); @@ -85,8 +86,8 @@ public class ModelStoreImpl implements ModelStore { @Override public synchronized ModelImpl createModel(long state) { - Map, VersionedMap> maps = new HashMap<>(); - for (Entry, VersionedMapStore> entry : this.stores.entrySet()) { + Map> maps = new HashMap<>(); + for (var entry : this.stores.entrySet()) { maps.put(entry.getKey(), entry.getValue().createMap(state)); } return new ModelImpl(this, maps); @@ -103,10 +104,10 @@ public class ModelStoreImpl implements ModelStore { @Override public synchronized ModelDiffCursor getDiffCursor(long from, long to) { - Map, DiffCursor> diffcursors = new HashMap<>(); - for (Entry, VersionedMapStore> entry : stores.entrySet()) { - DataRepresentation representation = entry.getKey(); - DiffCursor diffCursor = entry.getValue().getDiffCursor(from, to); + Map> diffcursors = new HashMap<>(); + for (var entry : stores.entrySet()) { + var representation = entry.getKey(); + var diffCursor = entry.getValue().getDiffCursor(from, to); diffcursors.put(representation, diffCursor); } return new ModelDiffCursor(diffcursors); diff --git a/subprojects/store/src/main/java/tools/refinery/store/model/internal/ModelImpl.java b/subprojects/store/src/main/java/tools/refinery/store/model/internal/ModelImpl.java index 2a5f2925..795a891b 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/model/internal/ModelImpl.java +++ b/subprojects/store/src/main/java/tools/refinery/store/model/internal/ModelImpl.java @@ -1,9 +1,5 @@ package tools.refinery.store.model.internal; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; - import tools.refinery.store.map.ContinousHashProvider; import tools.refinery.store.map.Cursor; import tools.refinery.store.map.DiffCursor; @@ -12,31 +8,41 @@ import tools.refinery.store.map.internal.MapDiffCursor; import tools.refinery.store.model.Model; import tools.refinery.store.model.ModelDiffCursor; import tools.refinery.store.model.ModelStore; +import tools.refinery.store.model.representation.AnyDataRepresentation; import tools.refinery.store.model.representation.DataRepresentation; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + public class ModelImpl implements Model { private final ModelStore store; - private final Map, VersionedMap> maps; - public ModelImpl(ModelStore store, Map, VersionedMap> maps) { + private final Map> maps; + + public ModelImpl(ModelStore store, Map> maps) { this.store = store; this.maps = maps; } @Override - public Set> getDataRepresentations() { + public Set getDataRepresentations() { return maps.keySet(); } - @SuppressWarnings("unchecked") - private VersionedMap getMap(DataRepresentation representation) { + private VersionedMap getMap(AnyDataRepresentation representation) { if (maps.containsKey(representation)) { - return (VersionedMap) maps.get(representation); + return maps.get(representation); } else { throw new IllegalArgumentException("Model does have representation " + representation); } } + @SuppressWarnings("unchecked") + private VersionedMap getMap(DataRepresentation representation) { + return (VersionedMap) maps.get(representation); + } + private VersionedMap getMapValidateKey(DataRepresentation representation, K key) { if (representation.isValidKey(key)) { return getMap(representation); @@ -67,17 +73,18 @@ public class ModelImpl implements Model { } @Override - public long getSize(DataRepresentation representation) { + public long getSize(AnyDataRepresentation representation) { return getMap(representation).getSize(); } @Override public ModelDiffCursor getDiffCursor(long to) { Model toModel = store.createModel(to); - Map, DiffCursor> diffCursors = new HashMap<>(); - for (DataRepresentation representation : this.maps.keySet()) { - MapDiffCursor diffCursor = constructDiffCursor(toModel, representation); - diffCursors.put(representation, diffCursor); + Map> diffCursors = new HashMap<>(); + for (AnyDataRepresentation anyDataRepresentation : this.maps.keySet()) { + var dataRepresentation = (DataRepresentation) anyDataRepresentation; + MapDiffCursor diffCursor = constructDiffCursor(toModel, dataRepresentation); + diffCursors.put(dataRepresentation, diffCursor); } return new ModelDiffCursor(diffCursors); } @@ -113,12 +120,12 @@ public class ModelImpl implements Model { @Override public void restore(long state) { - if(store.getStates().contains(state)) { + if (store.getStates().contains(state)) { for (VersionedMap map : maps.values()) { map.restore(state); } } else { - throw new IllegalArgumentException("Map does not contain state "+state+"!"); + throw new IllegalArgumentException("Map does not contain state " + state + "!"); } } } diff --git a/subprojects/store/src/main/java/tools/refinery/store/model/internal/SimilarRelationEquivalenceClass.java b/subprojects/store/src/main/java/tools/refinery/store/model/internal/SimilarRelationEquivalenceClass.java index 9939f17e..79e4c9f9 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/model/internal/SimilarRelationEquivalenceClass.java +++ b/subprojects/store/src/main/java/tools/refinery/store/model/internal/SimilarRelationEquivalenceClass.java @@ -1,31 +1,33 @@ package tools.refinery.store.model.internal; -import java.util.Objects; - import tools.refinery.store.map.ContinousHashProvider; -import tools.refinery.store.tuple.Tuple; import tools.refinery.store.model.representation.Relation; +import tools.refinery.store.tuple.Tuple; + +import java.util.Objects; public class SimilarRelationEquivalenceClass { final ContinousHashProvider hashProvider; final Object defaultValue; final int arity; + public SimilarRelationEquivalenceClass(Relation representation) { this.hashProvider = representation.getHashProvider(); this.defaultValue = representation.getDefaultValue(); this.arity = representation.getArity(); } + @Override public int hashCode() { return Objects.hash(arity, defaultValue, hashProvider); } + @Override public boolean equals(Object obj) { if (this == obj) return true; - if (!(obj instanceof SimilarRelationEquivalenceClass)) + if (!(obj instanceof SimilarRelationEquivalenceClass other)) return false; - SimilarRelationEquivalenceClass other = (SimilarRelationEquivalenceClass) obj; return arity == other.arity && Objects.equals(defaultValue, other.defaultValue) && Objects.equals(hashProvider, other.hashProvider); } diff --git a/subprojects/store/src/main/java/tools/refinery/store/model/representation/AnyAuxiliaryData.java b/subprojects/store/src/main/java/tools/refinery/store/model/representation/AnyAuxiliaryData.java new file mode 100644 index 00000000..951952e5 --- /dev/null +++ b/subprojects/store/src/main/java/tools/refinery/store/model/representation/AnyAuxiliaryData.java @@ -0,0 +1,4 @@ +package tools.refinery.store.model.representation; + +public sealed interface AnyAuxiliaryData extends AnyDataRepresentation permits AuxiliaryData { +} diff --git a/subprojects/store/src/main/java/tools/refinery/store/model/representation/AnyDataRepresentation.java b/subprojects/store/src/main/java/tools/refinery/store/model/representation/AnyDataRepresentation.java new file mode 100644 index 00000000..ea74a625 --- /dev/null +++ b/subprojects/store/src/main/java/tools/refinery/store/model/representation/AnyDataRepresentation.java @@ -0,0 +1,9 @@ +package tools.refinery.store.model.representation; + +public sealed interface AnyDataRepresentation permits DataRepresentation, AnyRelation, AnyAuxiliaryData { + String getName(); + + Class getKeyType(); + + Class getValueType(); +} diff --git a/subprojects/store/src/main/java/tools/refinery/store/model/representation/AnyRelation.java b/subprojects/store/src/main/java/tools/refinery/store/model/representation/AnyRelation.java new file mode 100644 index 00000000..1d698c28 --- /dev/null +++ b/subprojects/store/src/main/java/tools/refinery/store/model/representation/AnyRelation.java @@ -0,0 +1,9 @@ +package tools.refinery.store.model.representation; + +import tools.refinery.store.model.RelationLike; +import tools.refinery.store.tuple.Tuple; + +public sealed interface AnyRelation extends AnyDataRepresentation, RelationLike permits Relation { + @Override + Class getKeyType(); +} diff --git a/subprojects/store/src/main/java/tools/refinery/store/model/representation/AuxiliaryData.java b/subprojects/store/src/main/java/tools/refinery/store/model/representation/AuxiliaryData.java index 18c38151..dad1ccf4 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/model/representation/AuxiliaryData.java +++ b/subprojects/store/src/main/java/tools/refinery/store/model/representation/AuxiliaryData.java @@ -2,7 +2,7 @@ package tools.refinery.store.model.representation; import tools.refinery.store.map.ContinousHashProvider; -public final class AuxiliaryData extends DataRepresentation { +public final class AuxiliaryData extends DataRepresentation implements AnyAuxiliaryData { private final ContinousHashProvider hashProvider; public AuxiliaryData(String name, Class keyType, ContinousHashProvider hashProvider, Class valueType, diff --git a/subprojects/store/src/main/java/tools/refinery/store/model/representation/DataRepresentation.java b/subprojects/store/src/main/java/tools/refinery/store/model/representation/DataRepresentation.java index 61c6291b..2bf498b9 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/model/representation/DataRepresentation.java +++ b/subprojects/store/src/main/java/tools/refinery/store/model/representation/DataRepresentation.java @@ -2,7 +2,7 @@ package tools.refinery.store.model.representation; import tools.refinery.store.map.ContinousHashProvider; -public abstract sealed class DataRepresentation permits Relation, AuxiliaryData { +public abstract sealed class DataRepresentation implements AnyDataRepresentation permits Relation, AuxiliaryData { private final String name; private final V defaultValue; @@ -18,6 +18,7 @@ public abstract sealed class DataRepresentation permits Relation, Auxiliar this.valueType = valueType; } + @Override public String getName() { return name; } @@ -30,10 +31,12 @@ public abstract sealed class DataRepresentation permits Relation, Auxiliar return defaultValue; } + @Override public Class getKeyType() { return keyType; } + @Override public Class getValueType() { return valueType; } diff --git a/subprojects/store/src/main/java/tools/refinery/store/model/representation/Relation.java b/subprojects/store/src/main/java/tools/refinery/store/model/representation/Relation.java index cc32257c..47a07536 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/model/representation/Relation.java +++ b/subprojects/store/src/main/java/tools/refinery/store/model/representation/Relation.java @@ -1,11 +1,10 @@ package tools.refinery.store.model.representation; import tools.refinery.store.map.ContinousHashProvider; -import tools.refinery.store.model.RelationLike; import tools.refinery.store.model.TupleHashProvider; import tools.refinery.store.tuple.Tuple; -public final class Relation extends DataRepresentation implements RelationLike { +public final class Relation extends DataRepresentation implements AnyRelation { private final int arity; public Relation(String name, int arity, Class valueType, D defaultValue) { diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/QueryableModelStore.java b/subprojects/store/src/main/java/tools/refinery/store/query/QueryableModelStore.java index 41f47e64..3a69f3a4 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/query/QueryableModelStore.java +++ b/subprojects/store/src/main/java/tools/refinery/store/query/QueryableModelStore.java @@ -1,17 +1,15 @@ package tools.refinery.store.query; import tools.refinery.store.model.ModelStore; -import tools.refinery.store.model.representation.DataRepresentation; -import tools.refinery.store.query.view.RelationView; +import tools.refinery.store.model.representation.AnyDataRepresentation; +import tools.refinery.store.query.view.AnyRelationView; import java.util.Set; public interface QueryableModelStore extends ModelStore { - @SuppressWarnings("squid:S1452") - Set> getDataRepresentations(); + Set getDataRepresentations(); - @SuppressWarnings("squid:S1452") - Set> getViews(); + Set getViews(); Set getPredicates(); diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/atom/Modality.java b/subprojects/store/src/main/java/tools/refinery/store/query/atom/Modality.java index bc107b76..e389f563 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/query/atom/Modality.java +++ b/subprojects/store/src/main/java/tools/refinery/store/query/atom/Modality.java @@ -7,6 +7,14 @@ public enum Modality { MAY, CURRENT; + public Modality negate() { + return switch(this) { + case MUST -> MAY; + case MAY -> MUST; + case CURRENT -> CURRENT; + }; + } + @Override public String toString() { return name().toLowerCase(Locale.ROOT); diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/atom/RelationViewAtom.java b/subprojects/store/src/main/java/tools/refinery/store/query/atom/RelationViewAtom.java index 762a41f1..cf836541 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/query/atom/RelationViewAtom.java +++ b/subprojects/store/src/main/java/tools/refinery/store/query/atom/RelationViewAtom.java @@ -1,17 +1,17 @@ package tools.refinery.store.query.atom; import tools.refinery.store.query.Variable; -import tools.refinery.store.query.view.RelationView; +import tools.refinery.store.query.view.AnyRelationView; import java.util.List; import java.util.Objects; -public final class RelationViewAtom extends AbstractSubstitutionAtom> { - public RelationViewAtom(RelationView target, List substitution) { +public final class RelationViewAtom extends AbstractSubstitutionAtom { + public RelationViewAtom(AnyRelationView target, List substitution) { super(target, substitution); } - public RelationViewAtom(RelationView target, Variable... substitution) { + public RelationViewAtom(AnyRelationView target, Variable... substitution) { this(target, List.of(substitution)); } diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/view/AnyRelationView.java b/subprojects/store/src/main/java/tools/refinery/store/query/view/AnyRelationView.java new file mode 100644 index 00000000..df5e0d72 --- /dev/null +++ b/subprojects/store/src/main/java/tools/refinery/store/query/view/AnyRelationView.java @@ -0,0 +1,13 @@ +package tools.refinery.store.query.view; + +import tools.refinery.store.model.Model; +import tools.refinery.store.model.RelationLike; +import tools.refinery.store.model.representation.AnyRelation; + +public sealed interface AnyRelationView extends RelationLike permits RelationView { + AnyRelation getRepresentation(); + + boolean get(Model model, Object[] tuple); + + Iterable getAll(Model model); +} 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 3b639979..5b892cc6 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 @@ -3,6 +3,7 @@ package tools.refinery.store.query.view; import tools.refinery.store.tuple.Tuple; import tools.refinery.store.model.representation.Relation; +import java.util.Objects; import java.util.function.BiPredicate; import java.util.function.Predicate; @@ -31,4 +32,18 @@ public class FilteredRelationView extends AbstractFilteredRelationView { public boolean filter(Tuple key, D value) { return this.predicate.test(key, value); } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + if (!super.equals(o)) return false; + FilteredRelationView that = (FilteredRelationView) o; + return Objects.equals(predicate, that.predicate); + } + + @Override + public int hashCode() { + return Objects.hash(super.hashCode(), predicate); + } } 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 c88af5a4..f7e7d28a 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,6 +3,8 @@ package tools.refinery.store.query.view; import tools.refinery.store.tuple.Tuple; import tools.refinery.store.model.representation.Relation; +import java.util.Objects; + public class KeyOnlyRelationView extends AbstractFilteredRelationView { public static final String VIEW_NAME = "key"; @@ -17,4 +19,18 @@ public class KeyOnlyRelationView extends AbstractFilteredRelationView { public boolean filter(Tuple key, Boolean value) { return !value.equals(defaultValue); } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + if (!super.equals(o)) return false; + KeyOnlyRelationView that = (KeyOnlyRelationView) o; + return Objects.equals(defaultValue, that.defaultValue); + } + + @Override + public int hashCode() { + return Objects.hash(super.hashCode(), 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 96f8584a..1224076c 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/query/view/RelationView.java +++ b/subprojects/store/src/main/java/tools/refinery/store/query/view/RelationView.java @@ -2,9 +2,8 @@ package tools.refinery.store.query.view; import tools.refinery.store.map.CursorAsIterator; import tools.refinery.store.model.Model; -import tools.refinery.store.model.RelationLike; -import tools.refinery.store.tuple.Tuple; import tools.refinery.store.model.representation.Relation; +import tools.refinery.store.tuple.Tuple; import java.util.Objects; import java.util.UUID; @@ -15,7 +14,7 @@ import java.util.UUID; * @param * @author Oszkar Semerath */ -public abstract class RelationView implements RelationLike { +public abstract non-sealed class RelationView implements AnyRelationView { private final Relation representation; private final String name; @@ -29,6 +28,7 @@ public abstract class RelationView implements RelationLike { this(representation, UUID.randomUUID().toString()); } + @Override public Relation getRepresentation() { return representation; } @@ -42,28 +42,21 @@ public abstract class RelationView implements RelationLike { public abstract Object[] forwardMap(Tuple key, D value); - public abstract boolean get(Model model, Object[] tuple); - + @Override public Iterable getAll(Model model) { return (() -> new CursorAsIterator<>(model.getAll(representation), this::forwardMap, this::filter)); } @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + Objects.hash(representation); - return result; + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + RelationView that = (RelationView) o; + return Objects.equals(representation, that.representation) && Objects.equals(name, that.name); } @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (!(obj instanceof RelationView)) - return false; - @SuppressWarnings("unchecked") - RelationView other = ((RelationView) obj); - return Objects.equals(representation, other.representation); + public int hashCode() { + return Objects.hash(representation, name); } } diff --git a/subprojects/store/src/test/java/tools/refinery/store/map/tests/fuzz/ContentEqualsFuzzTest.java b/subprojects/store/src/test/java/tools/refinery/store/map/tests/fuzz/ContentEqualsFuzzTest.java index 263cb2cd..d7f77d1a 100644 --- a/subprojects/store/src/test/java/tools/refinery/store/map/tests/fuzz/ContentEqualsFuzzTest.java +++ b/subprojects/store/src/test/java/tools/refinery/store/map/tests/fuzz/ContentEqualsFuzzTest.java @@ -1,30 +1,25 @@ package tools.refinery.store.map.tests.fuzz; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.fail; - -import java.util.AbstractMap.SimpleEntry; -import java.util.Collections; -import java.util.LinkedList; -import java.util.List; -import java.util.Random; -import java.util.stream.Stream; - import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Timeout; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; - -import tools.refinery.store.map.ContinousHashProvider; -import tools.refinery.store.map.Cursor; -import tools.refinery.store.map.VersionedMap; -import tools.refinery.store.map.VersionedMapStore; -import tools.refinery.store.map.VersionedMapStoreImpl; +import tools.refinery.store.map.*; import tools.refinery.store.map.internal.VersionedMapImpl; import tools.refinery.store.map.tests.fuzz.utils.FuzzTestUtils; import tools.refinery.store.map.tests.utils.MapTestEnvironment; +import java.util.AbstractMap.SimpleEntry; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; +import java.util.Random; +import java.util.stream.Stream; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.fail; + class ContentEqualsFuzzTest { private void runFuzzTest(String scenario, int seed, int steps, int maxKey, int maxValue, int commitFrequency, boolean evilHash) { @@ -37,10 +32,9 @@ class ContentEqualsFuzzTest { } private void iterativeRandomPutsAndCommitsThenCompare(String scenario, ContinousHashProvider chp, int steps, int maxKey, String[] values, Random r, int commitFrequency) { - VersionedMapStore store1 = new VersionedMapStoreImpl(chp, values[0]); VersionedMap sut1 = store1.createMap(); - + // Fill one map for (int i = 0; i < steps; i++) { int index1 = i + 1; @@ -57,17 +51,17 @@ class ContentEqualsFuzzTest { sut1.commit(); } } - + // Get the content of the first map List> content = new LinkedList<>(); Cursor cursor = sut1.getAll(); while (cursor.move()) { content.add(new SimpleEntry<>(cursor.getKey(), cursor.getValue())); } - + // Randomize the order of the content Collections.shuffle(content, r); - + VersionedMapStore store2 = new VersionedMapStoreImpl(chp, values[0]); VersionedMap sut2 = store2.createMap(); int index2 = 1; @@ -76,18 +70,16 @@ class ContentEqualsFuzzTest { if(index2++%commitFrequency == 0) sut2.commit(); } - + // Check the integrity of the maps ((VersionedMapImpl) sut1).checkIntegrity(); ((VersionedMapImpl) sut2).checkIntegrity(); - + // // Compare the two maps // By size assertEquals(sut1.getSize(), content.size()); assertEquals(sut2.getSize(), content.size()); - - - + // By cursors Cursor cursor1 = sut1.getAll(); Cursor cursor2 = sut2.getAll(); @@ -99,16 +91,10 @@ class ContentEqualsFuzzTest { assertEquals(canMove1, canMove2, scenario + ":" + index3 +" Cursors stopped at different times!"); assertEquals(cursor1.getKey(), cursor2.getKey(), scenario + ":" + index3 +" Cursors have different keys!"); assertEquals(cursor1.getValue(), cursor2.getValue(), scenario + ":" + index3 +" Cursors have different values!"); - + canMove = canMove1; MapTestEnvironment.printStatus(scenario, index3++, content.size(), "Compare"); } while (canMove); - - // By hashcode - assertEquals(sut1.hashCode(), sut2.hashCode(), "Hash codes are not equal!"); - - // By equals - assertEquals(sut1, sut2, "Maps are not equals"); } @ParameterizedTest(name = "Compare {index}/{0} Steps={1} Keys={2} Values={3} commit frequency={4} seed={5} evil-hash={6}") diff --git a/subprojects/store/src/test/java/tools/refinery/store/map/tests/utils/MapTestEnvironment.java b/subprojects/store/src/test/java/tools/refinery/store/map/tests/utils/MapTestEnvironment.java index a4ba7441..b73f8b32 100644 --- a/subprojects/store/src/test/java/tools/refinery/store/map/tests/utils/MapTestEnvironment.java +++ b/subprojects/store/src/test/java/tools/refinery/store/map/tests/utils/MapTestEnvironment.java @@ -1,21 +1,14 @@ package tools.refinery.store.map.tests.utils; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.junit.jupiter.api.Assertions.fail; - -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; - import tools.refinery.store.map.ContinousHashProvider; import tools.refinery.store.map.Cursor; import tools.refinery.store.map.VersionedMap; import tools.refinery.store.map.internal.VersionedMapImpl; -import java.util.TreeMap; +import java.util.*; +import java.util.Map.Entry; + +import static org.junit.jupiter.api.Assertions.*; public class MapTestEnvironment { public static String[] prepareValues(int maxValue) { @@ -63,7 +56,6 @@ public class MapTestEnvironment { } public static void compareTwoMaps(String title, VersionedMapImpl map1, VersionedMapImpl map2, List errors) { - // 1. Comparing cursors. Cursor cursor1 = map1.getAll(); Cursor cursor2 = map2.getAll(); while (!cursor1.isTerminated()) { @@ -77,12 +69,8 @@ public class MapTestEnvironment { } if (!cursor2.isTerminated()) fail("cursor 1 terminated before cursor 2"); - - // 2.1. comparing hash codes - assertEqualsList(map1.hashCode(), map2.hashCode(), title + ": hash code check",errors); - assertEqualsList(map1, map2, title + ": 1.equals(2)",errors); - assertEqualsList(map2, map1, title + ": 2.equals(1)",errors); } + private static void assertEqualsList(Object o1, Object o2, String message, List errors) { if(errors == null) { assertEquals(o1, o2, message); @@ -112,7 +100,7 @@ public class MapTestEnvironment { oldOracleValue = oracle.remove(key); } if(oldSutValue == sut.getDefaultValue() && oldOracleValue != null) { - fail("After put, SUT old nodeId was default, but oracle old walue was " + oldOracleValue); + fail("After put, SUT old nodeId was default, but oracle old value was " + oldOracleValue); } if(oldSutValue != sut.getDefaultValue()) { assertEquals(oldOracleValue, oldSutValue); @@ -165,7 +153,7 @@ public class MapTestEnvironment { long sutSize = sut.getSize(); if (oracleSize != sutSize || oracleSize != elementsInSutEntrySet) { printComparison(); - fail(title + ": Non-eqivalent size() result: SUT.getSize()=" + sutSize + ", SUT.entryset.size=" + fail(title + ": Non-equivalent size() result: SUT.getSize()=" + sutSize + ", SUT.entryset.size=" + elementsInSutEntrySet + ", Oracle=" + oracleSize + "!"); } } @@ -192,22 +180,22 @@ public class MapTestEnvironment { } private void printEntrySet(Iterator> iterator) { - TreeMap treemap = new TreeMap<>(); + Map map = new LinkedHashMap<>(); while (iterator.hasNext()) { Entry entry = iterator.next(); - treemap.put(entry.getKey(), entry.getValue()); + map.put(entry.getKey(), entry.getValue()); } - for (Entry e : treemap.entrySet()) { + for (Entry e : map.entrySet()) { System.out.println("\t" + e.getKey() + " -> " + e.getValue()); } } private void printEntrySet(Cursor cursor) { - TreeMap treemap = new TreeMap<>(); + Map map = new LinkedHashMap<>(); while (cursor.move()) { - treemap.put(cursor.getKey(), cursor.getValue()); + map.put(cursor.getKey(), cursor.getValue()); } - for (Entry e : treemap.entrySet()) { + for (Entry e : map.entrySet()) { System.out.println("\t" + e.getKey() + " -> " + e.getValue()); } } -- cgit v1.2.3-54-g00ecf