diff options
author | 2023-07-24 14:37:16 +0200 | |
---|---|---|
committer | 2023-07-24 14:37:16 +0200 | |
commit | 8789304690384d19ad829286560aec5ed0917976 (patch) | |
tree | b157e78e8b6a3f2fb3d0eee6e1aa10d2c16e0204 /subprojects/store/src/main/java/tools | |
parent | decreasing steps in fast fuzz tests (diff) | |
parent | Merge pull request #27 from kris7t/ordered-result-set (diff) | |
download | refinery-8789304690384d19ad829286560aec5ed0917976.tar.gz refinery-8789304690384d19ad829286560aec5ed0917976.tar.zst refinery-8789304690384d19ad829286560aec5ed0917976.zip |
Merge branch 'graphs4value:main' into datastructure
Diffstat (limited to 'subprojects/store/src/main/java/tools')
104 files changed, 900 insertions, 1388 deletions
diff --git a/subprojects/store/src/main/java/tools/refinery/store/adapter/AbstractModelAdapterBuilder.java b/subprojects/store/src/main/java/tools/refinery/store/adapter/AbstractModelAdapterBuilder.java index 4c142217..8d3e998e 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/adapter/AbstractModelAdapterBuilder.java +++ b/subprojects/store/src/main/java/tools/refinery/store/adapter/AbstractModelAdapterBuilder.java | |||
@@ -1,27 +1,48 @@ | |||
1 | package tools.refinery.store.adapter; | 1 | package tools.refinery.store.adapter; |
2 | 2 | /* | |
3 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
4 | * | ||
5 | * SPDX-License-Identifier: EPL-2.0 | ||
6 | */ | ||
3 | import tools.refinery.store.model.ModelStore; | 7 | import tools.refinery.store.model.ModelStore; |
4 | import tools.refinery.store.model.ModelStoreBuilder; | 8 | import tools.refinery.store.model.ModelStoreBuilder; |
5 | 9 | ||
6 | public abstract class AbstractModelAdapterBuilder implements ModelAdapterBuilder { | 10 | public abstract class AbstractModelAdapterBuilder<T extends ModelStoreAdapter> implements ModelAdapterBuilder { |
7 | private final ModelStoreBuilder storeBuilder; | 11 | private boolean configured; |
8 | 12 | ||
9 | protected AbstractModelAdapterBuilder(ModelStoreBuilder storeBuilder) { | 13 | @Override |
10 | this.storeBuilder = storeBuilder; | 14 | public boolean isConfigured() { |
15 | return configured; | ||
11 | } | 16 | } |
12 | 17 | ||
13 | @Override | 18 | protected void checkConfigured() { |
14 | public <T extends ModelAdapterBuilder> T with(ModelAdapterBuilderFactory<?, ?, T> adapterBuilderFactory) { | 19 | if (!configured) { |
15 | return storeBuilder.with(adapterBuilderFactory); | 20 | throw new IllegalStateException("Model adapter builder was not configured"); |
21 | } | ||
22 | } | ||
23 | |||
24 | protected void checkNotConfigured() { | ||
25 | if (configured) { | ||
26 | throw new IllegalStateException("Model adapter builder was already configured"); | ||
27 | } | ||
28 | } | ||
29 | |||
30 | protected void doConfigure(ModelStoreBuilder storeBuilder) { | ||
31 | // Nothing to configure by default. | ||
16 | } | 32 | } |
17 | 33 | ||
18 | @Override | 34 | @Override |
19 | public ModelStoreBuilder getStoreBuilder() { | 35 | public final void configure(ModelStoreBuilder storeBuilder) { |
20 | return storeBuilder; | 36 | checkNotConfigured(); |
37 | doConfigure(storeBuilder); | ||
38 | configured = true; | ||
21 | } | 39 | } |
22 | 40 | ||
41 | protected abstract T doBuild(ModelStore store); | ||
42 | |||
23 | @Override | 43 | @Override |
24 | public ModelStore build() { | 44 | public final T build(ModelStore store) { |
25 | return storeBuilder.build(); | 45 | checkConfigured(); |
46 | return doBuild(store); | ||
26 | } | 47 | } |
27 | } | 48 | } |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/adapter/AdapterList.java b/subprojects/store/src/main/java/tools/refinery/store/adapter/AdapterList.java deleted file mode 100644 index 74bae6f0..00000000 --- a/subprojects/store/src/main/java/tools/refinery/store/adapter/AdapterList.java +++ /dev/null | |||
@@ -1,97 +0,0 @@ | |||
1 | package tools.refinery.store.adapter; | ||
2 | |||
3 | import org.jetbrains.annotations.NotNull; | ||
4 | |||
5 | import java.util.*; | ||
6 | import java.util.function.Consumer; | ||
7 | |||
8 | public class AdapterList<T> implements Iterable<T> { | ||
9 | private final List<AnyModelAdapterType> adapterTypes; | ||
10 | private final List<T> adapters; | ||
11 | |||
12 | public AdapterList() { | ||
13 | adapterTypes = new ArrayList<>(); | ||
14 | adapters = new ArrayList<>(); | ||
15 | } | ||
16 | |||
17 | public AdapterList(int adapterCount) { | ||
18 | adapterTypes = new ArrayList<>(adapterCount); | ||
19 | adapters = new ArrayList<>(adapterCount); | ||
20 | } | ||
21 | |||
22 | public int size() { | ||
23 | return adapters.size(); | ||
24 | } | ||
25 | |||
26 | public void add(AnyModelAdapterType adapterType, T adapter) { | ||
27 | adapterTypes.add(adapterType); | ||
28 | adapters.add(adapter); | ||
29 | } | ||
30 | |||
31 | public <U extends T> Optional<U> tryGet(AnyModelAdapterType adapterType, Class<? extends U> adapterClass) { | ||
32 | int size = size(); | ||
33 | for (int i = 0; i < size; i++) { | ||
34 | if (getType(i).supports(adapterType)) { | ||
35 | return Optional.of(adapterClass.cast(get(i))); | ||
36 | } | ||
37 | } | ||
38 | return Optional.empty(); | ||
39 | } | ||
40 | |||
41 | public <U extends T> U get(AnyModelAdapterType adapterType, Class<U> adapterClass) { | ||
42 | return tryGet(adapterType, adapterClass).orElseThrow(() -> new IllegalArgumentException( | ||
43 | "No %s was configured".formatted(adapterType))); | ||
44 | } | ||
45 | |||
46 | public AnyModelAdapterType getType(int i) { | ||
47 | return adapterTypes.get(i); | ||
48 | } | ||
49 | |||
50 | public T get(int i) { | ||
51 | return adapters.get(i); | ||
52 | } | ||
53 | |||
54 | public Collection<AnyModelAdapterType> getAdapterTypes() { | ||
55 | return Collections.unmodifiableCollection(adapterTypes); | ||
56 | } | ||
57 | |||
58 | public Iterable<Entry<T>> withAdapterTypes() { | ||
59 | return () -> new Iterator<>() { | ||
60 | private int i = 0; | ||
61 | |||
62 | @Override | ||
63 | public boolean hasNext() { | ||
64 | return i < size(); | ||
65 | } | ||
66 | |||
67 | @Override | ||
68 | public Entry<T> next() { | ||
69 | if (i >= size()) { | ||
70 | throw new NoSuchElementException(); | ||
71 | } | ||
72 | var entry = new Entry<>(getType(i), get(i)); | ||
73 | i++; | ||
74 | return entry; | ||
75 | } | ||
76 | }; | ||
77 | } | ||
78 | |||
79 | @NotNull | ||
80 | @Override | ||
81 | public Iterator<T> iterator() { | ||
82 | return adapters.iterator(); | ||
83 | } | ||
84 | |||
85 | @Override | ||
86 | public void forEach(Consumer<? super T> action) { | ||
87 | adapters.forEach(action); | ||
88 | } | ||
89 | |||
90 | @Override | ||
91 | public Spliterator<T> spliterator() { | ||
92 | return adapters.spliterator(); | ||
93 | } | ||
94 | |||
95 | public record Entry<T>(AnyModelAdapterType adapterType, T adapter) { | ||
96 | } | ||
97 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/adapter/AdapterUtils.java b/subprojects/store/src/main/java/tools/refinery/store/adapter/AdapterUtils.java new file mode 100644 index 00000000..556e99f0 --- /dev/null +++ b/subprojects/store/src/main/java/tools/refinery/store/adapter/AdapterUtils.java | |||
@@ -0,0 +1,33 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.adapter; | ||
7 | |||
8 | import java.util.Collection; | ||
9 | import java.util.Optional; | ||
10 | |||
11 | public class AdapterUtils { | ||
12 | private AdapterUtils() { | ||
13 | throw new IllegalStateException("This is a static utility class and should not be instantiated directly"); | ||
14 | } | ||
15 | |||
16 | public static <T, U extends T> Optional<U> tryGetAdapter(Collection<T> adapters, Class<? extends U> type) { | ||
17 | var iterator = adapters.stream().filter(type::isInstance).iterator(); | ||
18 | if (!iterator.hasNext()) { | ||
19 | return Optional.empty(); | ||
20 | } | ||
21 | var adapter = type.cast(iterator.next()); | ||
22 | if (iterator.hasNext()) { | ||
23 | throw new IllegalArgumentException("Ambiguous adapter: both %s and %s match %s" | ||
24 | .formatted(adapter.getClass().getName(), iterator.next().getClass().getName(), type.getName())); | ||
25 | } | ||
26 | return Optional.of(adapter); | ||
27 | } | ||
28 | |||
29 | public static <T> T getAdapter(Collection<? super T> adapters, Class<T> type) { | ||
30 | return tryGetAdapter(adapters, type).orElseThrow(() -> new IllegalArgumentException( | ||
31 | "No %s adapter was configured".formatted(type.getName()))); | ||
32 | } | ||
33 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/adapter/AnyModelAdapterType.java b/subprojects/store/src/main/java/tools/refinery/store/adapter/AnyModelAdapterType.java deleted file mode 100644 index 37a247fe..00000000 --- a/subprojects/store/src/main/java/tools/refinery/store/adapter/AnyModelAdapterType.java +++ /dev/null | |||
@@ -1,19 +0,0 @@ | |||
1 | package tools.refinery.store.adapter; | ||
2 | |||
3 | import java.util.Collection; | ||
4 | |||
5 | public sealed interface AnyModelAdapterType permits ModelAdapterType { | ||
6 | Class<? extends ModelAdapter> getModelAdapterClass(); | ||
7 | |||
8 | Class<? extends ModelStoreAdapter> getModelStoreAdapterClass(); | ||
9 | |||
10 | Class<? extends ModelAdapterBuilder> getModelAdapterBuilderClass(); | ||
11 | |||
12 | Collection<AnyModelAdapterType> getSupportedAdapterTypes(); | ||
13 | |||
14 | default boolean supports(AnyModelAdapterType targetAdapter) { | ||
15 | return getSupportedAdapterTypes().contains(targetAdapter); | ||
16 | } | ||
17 | |||
18 | String getName(); | ||
19 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/adapter/ModelAdapter.java b/subprojects/store/src/main/java/tools/refinery/store/adapter/ModelAdapter.java index aa079e01..672007aa 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/adapter/ModelAdapter.java +++ b/subprojects/store/src/main/java/tools/refinery/store/adapter/ModelAdapter.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.adapter; | 6 | package tools.refinery.store.adapter; |
2 | 7 | ||
3 | import tools.refinery.store.model.Model; | 8 | import tools.refinery.store.model.Model; |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/adapter/ModelAdapterBuilder.java b/subprojects/store/src/main/java/tools/refinery/store/adapter/ModelAdapterBuilder.java index 64b3e59f..75e5e07d 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/adapter/ModelAdapterBuilder.java +++ b/subprojects/store/src/main/java/tools/refinery/store/adapter/ModelAdapterBuilder.java | |||
@@ -1,17 +1,17 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.adapter; | 6 | package tools.refinery.store.adapter; |
2 | 7 | ||
3 | import tools.refinery.store.model.ModelStore; | 8 | import tools.refinery.store.model.ModelStore; |
4 | import tools.refinery.store.model.ModelStoreBuilder; | 9 | import tools.refinery.store.model.ModelStoreBuilder; |
5 | 10 | ||
6 | public interface ModelAdapterBuilder { | 11 | public interface ModelAdapterBuilder { |
7 | ModelStoreAdapter createStoreAdapter(ModelStore store); | 12 | boolean isConfigured(); |
8 | 13 | ||
9 | <T extends ModelAdapterBuilder> T with(ModelAdapterBuilderFactory<?, ?, T> adapterBuilderFactory); | 14 | void configure(ModelStoreBuilder storeBuilder); |
10 | 15 | ||
11 | ModelStoreBuilder getStoreBuilder(); | 16 | ModelStoreAdapter build(ModelStore store); |
12 | |||
13 | default void configure() { | ||
14 | } | ||
15 | |||
16 | ModelStore build(); | ||
17 | } | 17 | } |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/adapter/ModelAdapterBuilderFactory.java b/subprojects/store/src/main/java/tools/refinery/store/adapter/ModelAdapterBuilderFactory.java deleted file mode 100644 index 7c9b01bc..00000000 --- a/subprojects/store/src/main/java/tools/refinery/store/adapter/ModelAdapterBuilderFactory.java +++ /dev/null | |||
@@ -1,14 +0,0 @@ | |||
1 | package tools.refinery.store.adapter; | ||
2 | |||
3 | import tools.refinery.store.model.ModelStoreBuilder; | ||
4 | |||
5 | public abstract class ModelAdapterBuilderFactory<T1 extends ModelAdapter, T2 extends ModelStoreAdapter, | ||
6 | T3 extends ModelAdapterBuilder> extends ModelAdapterType<T1, T2, T3> { | ||
7 | |||
8 | protected ModelAdapterBuilderFactory(Class<T1> modelAdapterClass, Class<T2> modelStoreAdapterClass, | ||
9 | Class<T3> modelAdapterBuilderClass) { | ||
10 | super(modelAdapterClass, modelStoreAdapterClass, modelAdapterBuilderClass); | ||
11 | } | ||
12 | |||
13 | public abstract T3 createBuilder(ModelStoreBuilder storeBuilder); | ||
14 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/adapter/ModelAdapterType.java b/subprojects/store/src/main/java/tools/refinery/store/adapter/ModelAdapterType.java deleted file mode 100644 index 82ddeb12..00000000 --- a/subprojects/store/src/main/java/tools/refinery/store/adapter/ModelAdapterType.java +++ /dev/null | |||
@@ -1,79 +0,0 @@ | |||
1 | package tools.refinery.store.adapter; | ||
2 | |||
3 | import tools.refinery.store.model.Model; | ||
4 | import tools.refinery.store.model.ModelStore; | ||
5 | |||
6 | import java.lang.reflect.Method; | ||
7 | import java.util.Collection; | ||
8 | import java.util.Collections; | ||
9 | import java.util.HashSet; | ||
10 | import java.util.Set; | ||
11 | |||
12 | public abstract non-sealed class ModelAdapterType<T1 extends ModelAdapter, T2 extends ModelStoreAdapter, | ||
13 | T3 extends ModelAdapterBuilder> implements AnyModelAdapterType { | ||
14 | private final Class<? extends T1> modelAdapterClass; | ||
15 | private final Class<? extends T2> modelStoreAdapterClass; | ||
16 | private final Class<? extends T3> modelAdapterBuilderClass; | ||
17 | private final Set<AnyModelAdapterType> supportedAdapters = new HashSet<>(); | ||
18 | |||
19 | protected ModelAdapterType(Class<T1> modelAdapterClass, Class<T2> modelStoreAdapterClass, | ||
20 | Class<T3> modelAdapterBuilderClass) { | ||
21 | checkReturnType(modelAdapterClass, modelStoreAdapterClass, "createModelAdapter", Model.class); | ||
22 | checkReturnType(modelStoreAdapterClass, modelAdapterBuilderClass, "createStoreAdapter", ModelStore.class); | ||
23 | this.modelAdapterClass = modelAdapterClass; | ||
24 | this.modelStoreAdapterClass = modelStoreAdapterClass; | ||
25 | this.modelAdapterBuilderClass = modelAdapterBuilderClass; | ||
26 | supportedAdapters.add(this); | ||
27 | } | ||
28 | |||
29 | private void checkReturnType(Class<?> expectedReturnType, Class<?> ownerClass, String methodName, | ||
30 | Class<?>... argumentTypes) { | ||
31 | Method method; | ||
32 | try { | ||
33 | method = ownerClass.getMethod(methodName, argumentTypes); | ||
34 | } catch (NoSuchMethodException e) { | ||
35 | throw new IllegalStateException("Invalid %s: %s#%s method is required" | ||
36 | .formatted(this, ownerClass.getName(), methodName), e); | ||
37 | } | ||
38 | var returnType = method.getReturnType(); | ||
39 | if (!expectedReturnType.isAssignableFrom(returnType)) { | ||
40 | throw new IllegalStateException("Invalid %s: %s is not assignable from the return type %s of %s#%s" | ||
41 | .formatted(this, expectedReturnType.getName(), returnType.getCanonicalName(), | ||
42 | ownerClass.getName(), methodName)); | ||
43 | } | ||
44 | } | ||
45 | |||
46 | protected void extendsAdapter(ModelAdapterType<? super T1, ? super T2, ? super T3> superAdapter) { | ||
47 | supportedAdapters.addAll(superAdapter.supportedAdapters); | ||
48 | } | ||
49 | |||
50 | @Override | ||
51 | public final Class<? extends T1> getModelAdapterClass() { | ||
52 | return modelAdapterClass; | ||
53 | } | ||
54 | |||
55 | @Override | ||
56 | public final Class<? extends T2> getModelStoreAdapterClass() { | ||
57 | return modelStoreAdapterClass; | ||
58 | } | ||
59 | |||
60 | @Override | ||
61 | public final Class<? extends T3> getModelAdapterBuilderClass() { | ||
62 | return modelAdapterBuilderClass; | ||
63 | } | ||
64 | |||
65 | @Override | ||
66 | public Collection<AnyModelAdapterType> getSupportedAdapterTypes() { | ||
67 | return Collections.unmodifiableCollection(supportedAdapters); | ||
68 | } | ||
69 | |||
70 | @Override | ||
71 | public String getName() { | ||
72 | return "%s.ADAPTER".formatted(this.getClass().getName()); | ||
73 | } | ||
74 | |||
75 | @Override | ||
76 | public String toString() { | ||
77 | return getName(); | ||
78 | } | ||
79 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/adapter/ModelStoreAdapter.java b/subprojects/store/src/main/java/tools/refinery/store/adapter/ModelStoreAdapter.java index 1eb40ada..bc5f7b6b 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/adapter/ModelStoreAdapter.java +++ b/subprojects/store/src/main/java/tools/refinery/store/adapter/ModelStoreAdapter.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.adapter; | 6 | package tools.refinery.store.adapter; |
2 | 7 | ||
3 | import tools.refinery.store.model.Model; | 8 | import tools.refinery.store.model.Model; |
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 index ead79878..01099eb0 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/map/AnyVersionedMap.java +++ b/subprojects/store/src/main/java/tools/refinery/store/map/AnyVersionedMap.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.map; | 6 | package tools.refinery.store.map; |
2 | 7 | ||
3 | public sealed interface AnyVersionedMap extends Versioned permits VersionedMap { | 8 | public sealed interface AnyVersionedMap extends Versioned permits VersionedMap { |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/ContentHashCode.java b/subprojects/store/src/main/java/tools/refinery/store/map/ContentHashCode.java index 8deeab23..cbea05e1 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/map/ContentHashCode.java +++ b/subprojects/store/src/main/java/tools/refinery/store/map/ContentHashCode.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.map; | 6 | package tools.refinery.store.map; |
2 | 7 | ||
3 | public enum ContentHashCode { | 8 | public enum ContentHashCode { |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/ContinousHashProvider.java b/subprojects/store/src/main/java/tools/refinery/store/map/ContinousHashProvider.java index 75f1e2ab..8e451230 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/map/ContinousHashProvider.java +++ b/subprojects/store/src/main/java/tools/refinery/store/map/ContinousHashProvider.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.map; | 6 | package tools.refinery.store.map; |
2 | 7 | ||
3 | import tools.refinery.store.map.internal.Node; | 8 | import tools.refinery.store.map.internal.Node; |
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 b420585c..3bdca104 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,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.map; | 6 | package tools.refinery.store.map; |
2 | 7 | ||
3 | import java.util.Set; | 8 | import java.util.Set; |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/CursorAsIterator.java b/subprojects/store/src/main/java/tools/refinery/store/map/CursorAsIterator.java index 65ae6648..c7e4d279 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/map/CursorAsIterator.java +++ b/subprojects/store/src/main/java/tools/refinery/store/map/CursorAsIterator.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.map; | 6 | package tools.refinery.store.map; |
2 | 7 | ||
3 | import java.util.Iterator; | 8 | import java.util.Iterator; |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/Cursors.java b/subprojects/store/src/main/java/tools/refinery/store/map/Cursors.java new file mode 100644 index 00000000..0a94d449 --- /dev/null +++ b/subprojects/store/src/main/java/tools/refinery/store/map/Cursors.java | |||
@@ -0,0 +1,41 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.map; | ||
7 | |||
8 | public final class Cursors { | ||
9 | private Cursors() { | ||
10 | throw new IllegalStateException("This is a static utility class and should not be instantiated directly"); | ||
11 | } | ||
12 | |||
13 | public static <K, V> Cursor<K, V> empty() { | ||
14 | return new Empty<>(); | ||
15 | } | ||
16 | |||
17 | private static class Empty<K, V> implements Cursor<K, V> { | ||
18 | private boolean terminated = false; | ||
19 | |||
20 | @Override | ||
21 | public K getKey() { | ||
22 | return null; | ||
23 | } | ||
24 | |||
25 | @Override | ||
26 | public V getValue() { | ||
27 | return null; | ||
28 | } | ||
29 | |||
30 | @Override | ||
31 | public boolean isTerminated() { | ||
32 | return terminated; | ||
33 | } | ||
34 | |||
35 | @Override | ||
36 | public boolean move() { | ||
37 | terminated = true; | ||
38 | return false; | ||
39 | } | ||
40 | } | ||
41 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/DiffCursor.java b/subprojects/store/src/main/java/tools/refinery/store/map/DiffCursor.java index 701f3ec8..4322e041 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/map/DiffCursor.java +++ b/subprojects/store/src/main/java/tools/refinery/store/map/DiffCursor.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.map; | 6 | package tools.refinery.store.map; |
2 | 7 | ||
3 | public interface DiffCursor<K, V> extends Cursor<K,V> { | 8 | public interface DiffCursor<K, V> extends Cursor<K,V> { |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/MapAsIterable.java b/subprojects/store/src/main/java/tools/refinery/store/map/MapAsIterable.java index 6b986732..199b548f 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/map/MapAsIterable.java +++ b/subprojects/store/src/main/java/tools/refinery/store/map/MapAsIterable.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.map; | 6 | package tools.refinery.store.map; |
2 | 7 | ||
3 | import java.util.Iterator; | 8 | import java.util.Iterator; |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/Versioned.java b/subprojects/store/src/main/java/tools/refinery/store/map/Versioned.java index 6a23e9d5..55720db3 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/map/Versioned.java +++ b/subprojects/store/src/main/java/tools/refinery/store/map/Versioned.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.map; | 6 | package tools.refinery.store.map; |
2 | 7 | ||
3 | public interface Versioned { | 8 | public interface Versioned { |
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 08ce1dbd..c8226c3e 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,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.map; | 6 | package tools.refinery.store.map; |
2 | 7 | ||
3 | public non-sealed interface VersionedMap<K, V> extends AnyVersionedMap { | 8 | public non-sealed interface VersionedMap<K, V> extends AnyVersionedMap { |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/VersionedMapStore.java b/subprojects/store/src/main/java/tools/refinery/store/map/VersionedMapStore.java index 7768287a..b24c404c 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/map/VersionedMapStore.java +++ b/subprojects/store/src/main/java/tools/refinery/store/map/VersionedMapStore.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.map; | 6 | package tools.refinery.store.map; |
2 | 7 | ||
3 | import tools.refinery.store.map.internal.VersionedMapStoreFactoryBuilderImpl; | 8 | import tools.refinery.store.map.internal.VersionedMapStoreFactoryBuilderImpl; |
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 3856460d..b00cd961 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,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.map; | 6 | package tools.refinery.store.map; |
2 | 7 | ||
3 | public class VersionedMapStoreConfiguration { | 8 | public class VersionedMapStoreConfiguration { |
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 beeed110..a934d59e 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,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.map; | 6 | package tools.refinery.store.map; |
2 | 7 | ||
3 | import tools.refinery.store.map.internal.*; | 8 | import tools.refinery.store.map.internal.*; |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/internal/HashClash.java b/subprojects/store/src/main/java/tools/refinery/store/map/internal/HashClash.java index 0806c486..a357fbce 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/map/internal/HashClash.java +++ b/subprojects/store/src/main/java/tools/refinery/store/map/internal/HashClash.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.map.internal; | 6 | package tools.refinery.store.map.internal; |
2 | 7 | ||
3 | enum HashClash { | 8 | enum HashClash { |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/internal/ImmutableNode.java b/subprojects/store/src/main/java/tools/refinery/store/map/internal/ImmutableNode.java index 92446711..d052318f 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/map/internal/ImmutableNode.java +++ b/subprojects/store/src/main/java/tools/refinery/store/map/internal/ImmutableNode.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.map.internal; | 6 | package tools.refinery.store.map.internal; |
2 | 7 | ||
3 | import java.util.Arrays; | 8 | import java.util.Arrays; |
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 7e4f82e8..d42519b2 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,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.map.internal; | 6 | package tools.refinery.store.map.internal; |
2 | 7 | ||
3 | import tools.refinery.store.map.AnyVersionedMap; | 8 | import tools.refinery.store.map.AnyVersionedMap; |
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 59e8d738..fb1d5d2b 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,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.map.internal; | 6 | package tools.refinery.store.map.internal; |
2 | 7 | ||
3 | import tools.refinery.store.map.AnyVersionedMap; | 8 | import tools.refinery.store.map.AnyVersionedMap; |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/internal/MutableNode.java b/subprojects/store/src/main/java/tools/refinery/store/map/internal/MutableNode.java index 81bf6188..bb85deb9 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/map/internal/MutableNode.java +++ b/subprojects/store/src/main/java/tools/refinery/store/map/internal/MutableNode.java | |||
@@ -1,10 +1,15 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.map.internal; | 6 | package tools.refinery.store.map.internal; |
2 | 7 | ||
8 | import tools.refinery.store.map.ContinousHashProvider; | ||
9 | |||
3 | import java.util.Arrays; | 10 | import java.util.Arrays; |
4 | import java.util.Map; | 11 | import java.util.Map; |
5 | 12 | ||
6 | import tools.refinery.store.map.ContinousHashProvider; | ||
7 | |||
8 | public class MutableNode<K, V> extends Node<K, V> { | 13 | public class MutableNode<K, V> extends Node<K, V> { |
9 | int cachedHash; | 14 | int cachedHash; |
10 | protected boolean cachedHashValid; | 15 | protected boolean cachedHashValid; |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/internal/Node.java b/subprojects/store/src/main/java/tools/refinery/store/map/internal/Node.java index 3dd332da..4b44f760 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/map/internal/Node.java +++ b/subprojects/store/src/main/java/tools/refinery/store/map/internal/Node.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.map.internal; | 6 | package tools.refinery.store.map.internal; |
2 | 7 | ||
3 | import java.util.Map; | 8 | import java.util.Map; |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/internal/OldValueBox.java b/subprojects/store/src/main/java/tools/refinery/store/map/internal/OldValueBox.java index 5534c703..354af51d 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/map/internal/OldValueBox.java +++ b/subprojects/store/src/main/java/tools/refinery/store/map/internal/OldValueBox.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.map.internal; | 6 | package tools.refinery.store.map.internal; |
2 | 7 | ||
3 | public class OldValueBox<V>{ | 8 | public class OldValueBox<V>{ |
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 2ceca463..c107f7e0 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,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.map.internal; | 6 | package tools.refinery.store.map.internal; |
2 | 7 | ||
3 | import tools.refinery.store.map.*; | 8 | import tools.refinery.store.map.*; |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/model/AnyInterpretation.java b/subprojects/store/src/main/java/tools/refinery/store/model/AnyInterpretation.java index d18ba71d..f906b48a 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/model/AnyInterpretation.java +++ b/subprojects/store/src/main/java/tools/refinery/store/model/AnyInterpretation.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.model; | 6 | package tools.refinery.store.model; |
2 | 7 | ||
3 | import tools.refinery.store.representation.AnySymbol; | 8 | import tools.refinery.store.representation.AnySymbol; |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/model/Interpretation.java b/subprojects/store/src/main/java/tools/refinery/store/model/Interpretation.java index 55949d0c..26ad9a69 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/model/Interpretation.java +++ b/subprojects/store/src/main/java/tools/refinery/store/model/Interpretation.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.model; | 6 | package tools.refinery.store.model; |
2 | 7 | ||
3 | import tools.refinery.store.map.Cursor; | 8 | import tools.refinery.store.map.Cursor; |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/model/InterpretationListener.java b/subprojects/store/src/main/java/tools/refinery/store/model/InterpretationListener.java index 73950779..6f7b24c1 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/model/InterpretationListener.java +++ b/subprojects/store/src/main/java/tools/refinery/store/model/InterpretationListener.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.model; | 6 | package tools.refinery.store.model; |
2 | 7 | ||
3 | import tools.refinery.store.tuple.Tuple; | 8 | import tools.refinery.store.tuple.Tuple; |
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 6ca1ac7b..d58d91c3 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,7 +1,11 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.model; | 6 | package tools.refinery.store.model; |
2 | 7 | ||
3 | import tools.refinery.store.adapter.ModelAdapter; | 8 | import tools.refinery.store.adapter.ModelAdapter; |
4 | import tools.refinery.store.adapter.ModelAdapterType; | ||
5 | import tools.refinery.store.map.Versioned; | 9 | import tools.refinery.store.map.Versioned; |
6 | import tools.refinery.store.representation.AnySymbol; | 10 | import tools.refinery.store.representation.AnySymbol; |
7 | import tools.refinery.store.representation.Symbol; | 11 | import tools.refinery.store.representation.Symbol; |
@@ -25,9 +29,9 @@ public interface Model extends Versioned { | |||
25 | 29 | ||
26 | ModelDiffCursor getDiffCursor(long to); | 30 | ModelDiffCursor getDiffCursor(long to); |
27 | 31 | ||
28 | <T extends ModelAdapter> Optional<T> tryGetAdapter(ModelAdapterType<? extends T, ?, ?> adapterType); | 32 | <T extends ModelAdapter> Optional<T> tryGetAdapter(Class<? extends T> adapterType); |
29 | 33 | ||
30 | <T extends ModelAdapter> T getAdapter(ModelAdapterType<T, ?, ?> adapterType); | 34 | <T extends ModelAdapter> T getAdapter(Class<T> adapterType); |
31 | 35 | ||
32 | void addListener(ModelListener listener); | 36 | void addListener(ModelListener listener); |
33 | 37 | ||
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 97bf2039..7b236891 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,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.model; | 6 | package tools.refinery.store.model; |
2 | 7 | ||
3 | import tools.refinery.store.map.DiffCursor; | 8 | import tools.refinery.store.map.DiffCursor; |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/model/ModelListener.java b/subprojects/store/src/main/java/tools/refinery/store/model/ModelListener.java index f67540bb..a9ad8cfd 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/model/ModelListener.java +++ b/subprojects/store/src/main/java/tools/refinery/store/model/ModelListener.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.model; | 6 | package tools.refinery.store.model; |
2 | 7 | ||
3 | public interface ModelListener { | 8 | public interface ModelListener { |
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 2e7e62c3..b10eb8a4 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,6 +1,10 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.model; | 6 | package tools.refinery.store.model; |
2 | 7 | ||
3 | import tools.refinery.store.adapter.ModelAdapterType; | ||
4 | import tools.refinery.store.adapter.ModelStoreAdapter; | 8 | import tools.refinery.store.adapter.ModelStoreAdapter; |
5 | import tools.refinery.store.model.internal.ModelStoreBuilderImpl; | 9 | import tools.refinery.store.model.internal.ModelStoreBuilderImpl; |
6 | import tools.refinery.store.representation.AnySymbol; | 10 | import tools.refinery.store.representation.AnySymbol; |
@@ -20,9 +24,9 @@ public interface ModelStore { | |||
20 | 24 | ||
21 | ModelDiffCursor getDiffCursor(long from, long to); | 25 | ModelDiffCursor getDiffCursor(long from, long to); |
22 | 26 | ||
23 | <T extends ModelStoreAdapter> Optional<T> tryGetAdapter(ModelAdapterType<?, ? extends T, ?> adapterType); | 27 | <T extends ModelStoreAdapter> Optional<T> tryGetAdapter(Class<? extends T> adapterType); |
24 | 28 | ||
25 | <T extends ModelStoreAdapter> T getAdapter(ModelAdapterType<?, T, ?> adapterType); | 29 | <T extends ModelStoreAdapter> T getAdapter(Class<T> adapterType); |
26 | 30 | ||
27 | static ModelStoreBuilder builder() { | 31 | static ModelStoreBuilder builder() { |
28 | return new ModelStoreBuilderImpl(); | 32 | return new ModelStoreBuilderImpl(); |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/model/ModelStoreBuilder.java b/subprojects/store/src/main/java/tools/refinery/store/model/ModelStoreBuilder.java index 289099da..3a4024b5 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/model/ModelStoreBuilder.java +++ b/subprojects/store/src/main/java/tools/refinery/store/model/ModelStoreBuilder.java | |||
@@ -1,8 +1,11 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.model; | 6 | package tools.refinery.store.model; |
2 | 7 | ||
3 | import tools.refinery.store.adapter.ModelAdapterBuilder; | 8 | import tools.refinery.store.adapter.ModelAdapterBuilder; |
4 | import tools.refinery.store.adapter.ModelAdapterBuilderFactory; | ||
5 | import tools.refinery.store.adapter.ModelAdapterType; | ||
6 | import tools.refinery.store.representation.AnySymbol; | 9 | import tools.refinery.store.representation.AnySymbol; |
7 | import tools.refinery.store.representation.Symbol; | 10 | import tools.refinery.store.representation.Symbol; |
8 | 11 | ||
@@ -26,11 +29,11 @@ public interface ModelStoreBuilder { | |||
26 | 29 | ||
27 | <T> ModelStoreBuilder symbol(Symbol<T> symbol); | 30 | <T> ModelStoreBuilder symbol(Symbol<T> symbol); |
28 | 31 | ||
29 | <T extends ModelAdapterBuilder> T with(ModelAdapterBuilderFactory<?, ?, T> adapterBuilderFactory); | 32 | <T extends ModelAdapterBuilder> ModelStoreBuilder with(T adapterBuilder); |
30 | 33 | ||
31 | <T extends ModelAdapterBuilder> Optional<T> tryGetAdapter(ModelAdapterType<?, ?, ? extends T> adapterType); | 34 | <T extends ModelAdapterBuilder> Optional<T> tryGetAdapter(Class<? extends T> adapterType); |
32 | 35 | ||
33 | <T extends ModelAdapterBuilder> T getAdapter(ModelAdapterType<?, ?, T> adapterType); | 36 | <T extends ModelAdapterBuilder> T getAdapter(Class<T> adapterType); |
34 | 37 | ||
35 | ModelStore build(); | 38 | ModelStore build(); |
36 | } | 39 | } |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/model/TupleHashProvider.java b/subprojects/store/src/main/java/tools/refinery/store/model/TupleHashProvider.java index 1183b8f2..fdd4425e 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/model/TupleHashProvider.java +++ b/subprojects/store/src/main/java/tools/refinery/store/model/TupleHashProvider.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.model; | 6 | package tools.refinery.store.model; |
2 | 7 | ||
3 | import tools.refinery.store.map.ContinousHashProvider; | 8 | import tools.refinery.store.map.ContinousHashProvider; |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/model/TupleHashProviderBitMagic.java b/subprojects/store/src/main/java/tools/refinery/store/model/TupleHashProviderBitMagic.java index 33059a1b..14116a90 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/model/TupleHashProviderBitMagic.java +++ b/subprojects/store/src/main/java/tools/refinery/store/model/TupleHashProviderBitMagic.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.model; | 6 | package tools.refinery.store.model; |
2 | 7 | ||
3 | import tools.refinery.store.map.ContinousHashProvider; | 8 | import tools.refinery.store.map.ContinousHashProvider; |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/model/internal/ModelAction.java b/subprojects/store/src/main/java/tools/refinery/store/model/internal/ModelAction.java index f68859db..dbd95d80 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/model/internal/ModelAction.java +++ b/subprojects/store/src/main/java/tools/refinery/store/model/internal/ModelAction.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.model.internal; | 6 | package tools.refinery.store.model.internal; |
2 | 7 | ||
3 | public enum ModelAction { | 8 | public enum ModelAction { |
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 9eb438c4..c5475a1a 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,12 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.model.internal; | 6 | package tools.refinery.store.model.internal; |
2 | 7 | ||
3 | import tools.refinery.store.adapter.AdapterList; | 8 | import tools.refinery.store.adapter.AdapterUtils; |
4 | import tools.refinery.store.adapter.AnyModelAdapterType; | ||
5 | import tools.refinery.store.adapter.ModelAdapter; | 9 | import tools.refinery.store.adapter.ModelAdapter; |
6 | import tools.refinery.store.adapter.ModelAdapterType; | ||
7 | import tools.refinery.store.map.DiffCursor; | 10 | import tools.refinery.store.map.DiffCursor; |
8 | import tools.refinery.store.model.*; | 11 | import tools.refinery.store.model.*; |
9 | import tools.refinery.store.representation.AnySymbol; | 12 | import tools.refinery.store.representation.AnySymbol; |
@@ -16,7 +19,7 @@ public class ModelImpl implements Model { | |||
16 | private final ModelStore store; | 19 | private final ModelStore store; |
17 | private long state; | 20 | private long state; |
18 | private Map<? extends AnySymbol, ? extends VersionedInterpretation<?>> interpretations; | 21 | private Map<? extends AnySymbol, ? extends VersionedInterpretation<?>> interpretations; |
19 | private final AdapterList<ModelAdapter> adapters; | 22 | private final List<ModelAdapter> adapters; |
20 | private final List<ModelListener> listeners = new ArrayList<>(); | 23 | private final List<ModelListener> listeners = new ArrayList<>(); |
21 | private boolean uncommittedChanges; | 24 | private boolean uncommittedChanges; |
22 | private ModelAction pendingAction = ModelAction.NONE; | 25 | private ModelAction pendingAction = ModelAction.NONE; |
@@ -25,7 +28,7 @@ public class ModelImpl implements Model { | |||
25 | ModelImpl(ModelStore store, long state, int adapterCount) { | 28 | ModelImpl(ModelStore store, long state, int adapterCount) { |
26 | this.store = store; | 29 | this.store = store; |
27 | this.state = state; | 30 | this.state = state; |
28 | adapters = new AdapterList<>(adapterCount); | 31 | adapters = new ArrayList<>(adapterCount); |
29 | } | 32 | } |
30 | 33 | ||
31 | void setInterpretations(Map<? extends AnySymbol, ? extends VersionedInterpretation<?>> interpretations) { | 34 | void setInterpretations(Map<? extends AnySymbol, ? extends VersionedInterpretation<?>> interpretations) { |
@@ -162,17 +165,17 @@ public class ModelImpl implements Model { | |||
162 | } | 165 | } |
163 | 166 | ||
164 | @Override | 167 | @Override |
165 | public <T extends ModelAdapter> Optional<T> tryGetAdapter(ModelAdapterType<? extends T, ?, ?> adapterType) { | 168 | public <T extends ModelAdapter> Optional<T> tryGetAdapter(Class<? extends T> adapterType) { |
166 | return adapters.tryGet(adapterType, adapterType.getModelAdapterClass()); | 169 | return AdapterUtils.tryGetAdapter(adapters, adapterType); |
167 | } | 170 | } |
168 | 171 | ||
169 | @Override | 172 | @Override |
170 | public <T extends ModelAdapter> T getAdapter(ModelAdapterType<T, ?, ?> adapterType) { | 173 | public <T extends ModelAdapter> T getAdapter(Class<T> adapterType) { |
171 | return adapters.get(adapterType, adapterType.getModelAdapterClass()); | 174 | return AdapterUtils.getAdapter(adapters, adapterType); |
172 | } | 175 | } |
173 | 176 | ||
174 | void addAdapter(AnyModelAdapterType adapterType, ModelAdapter adapter) { | 177 | void addAdapter(ModelAdapter adapter) { |
175 | adapters.add(adapterType, adapter); | 178 | adapters.add(adapter); |
176 | } | 179 | } |
177 | 180 | ||
178 | @Override | 181 | @Override |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/model/internal/ModelStoreBuilderImpl.java b/subprojects/store/src/main/java/tools/refinery/store/model/internal/ModelStoreBuilderImpl.java index 79f7195d..aafbe130 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/model/internal/ModelStoreBuilderImpl.java +++ b/subprojects/store/src/main/java/tools/refinery/store/model/internal/ModelStoreBuilderImpl.java | |||
@@ -1,9 +1,12 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.model.internal; | 6 | package tools.refinery.store.model.internal; |
2 | 7 | ||
3 | import tools.refinery.store.adapter.AdapterList; | 8 | import tools.refinery.store.adapter.AdapterUtils; |
4 | import tools.refinery.store.adapter.ModelAdapterBuilder; | 9 | import tools.refinery.store.adapter.ModelAdapterBuilder; |
5 | import tools.refinery.store.adapter.ModelAdapterBuilderFactory; | ||
6 | import tools.refinery.store.adapter.ModelAdapterType; | ||
7 | import tools.refinery.store.map.VersionedMapStore; | 10 | import tools.refinery.store.map.VersionedMapStore; |
8 | import tools.refinery.store.map.VersionedMapStoreImpl; | 11 | import tools.refinery.store.map.VersionedMapStoreImpl; |
9 | import tools.refinery.store.model.ModelStore; | 12 | import tools.refinery.store.model.ModelStore; |
@@ -18,7 +21,7 @@ import java.util.*; | |||
18 | public class ModelStoreBuilderImpl implements ModelStoreBuilder { | 21 | public class ModelStoreBuilderImpl implements ModelStoreBuilder { |
19 | private final Set<AnySymbol> allSymbols = new HashSet<>(); | 22 | private final Set<AnySymbol> allSymbols = new HashSet<>(); |
20 | private final Map<SymbolEquivalenceClass<?>, List<AnySymbol>> equivalenceClasses = new HashMap<>(); | 23 | private final Map<SymbolEquivalenceClass<?>, List<AnySymbol>> equivalenceClasses = new HashMap<>(); |
21 | private final AdapterList<ModelAdapterBuilder> adapters = new AdapterList<>(); | 24 | private final List<ModelAdapterBuilder> adapters = new ArrayList<>(); |
22 | 25 | ||
23 | @Override | 26 | @Override |
24 | public <T> ModelStoreBuilder symbol(Symbol<T> symbol) { | 27 | public <T> ModelStoreBuilder symbol(Symbol<T> symbol) { |
@@ -33,46 +36,25 @@ public class ModelStoreBuilderImpl implements ModelStoreBuilder { | |||
33 | } | 36 | } |
34 | 37 | ||
35 | @Override | 38 | @Override |
36 | public <T extends ModelAdapterBuilder> T with(ModelAdapterBuilderFactory<?, ?, T> adapterBuilderFactory) { | 39 | public <T extends ModelAdapterBuilder> ModelStoreBuilder with(T adapterBuilder) { |
37 | return adapters.<T>tryGet(adapterBuilderFactory, adapterBuilderFactory.getModelAdapterBuilderClass()) | 40 | for (var existingAdapter : adapters) { |
38 | .orElseGet(() -> addAdapter(adapterBuilderFactory)); | 41 | if (existingAdapter.getClass().equals(adapterBuilder.getClass())) { |
39 | } | 42 | throw new IllegalArgumentException("%s adapter was already configured for store builder" |
40 | 43 | .formatted(adapterBuilder.getClass().getName())); | |
41 | private <T extends ModelAdapterBuilder> T addAdapter(ModelAdapterBuilderFactory<?, ?, T> adapterBuilderFactory) { | ||
42 | for (var configuredAdapterType : adapters.getAdapterTypes()) { | ||
43 | var intersection = new HashSet<>(adapterBuilderFactory.getSupportedAdapterTypes()); | ||
44 | intersection.retainAll(configuredAdapterType.getSupportedAdapterTypes()); | ||
45 | if (!intersection.isEmpty()) { | ||
46 | if (configuredAdapterType.supports(adapterBuilderFactory)) { | ||
47 | // Impossible to end up here from <code>#with</code>, because we should have returned | ||
48 | // the existing adapter there instead of adding a new one. | ||
49 | throw new IllegalArgumentException( | ||
50 | "Cannot add %s, because it is already provided by configured adapter %s" | ||
51 | .formatted(adapterBuilderFactory, configuredAdapterType)); | ||
52 | } else if (adapterBuilderFactory.supports(configuredAdapterType)) { | ||
53 | throw new IllegalArgumentException( | ||
54 | "Cannot add %s, because it provides already configured adapter %s" | ||
55 | .formatted(adapterBuilderFactory, configuredAdapterType)); | ||
56 | } else { | ||
57 | throw new IllegalArgumentException( | ||
58 | "Cannot add %s, because configured adapter %s already provides %s" | ||
59 | .formatted(adapterBuilderFactory, configuredAdapterType, intersection)); | ||
60 | } | ||
61 | } | 44 | } |
62 | } | 45 | } |
63 | var newAdapter = adapterBuilderFactory.createBuilder(this); | 46 | adapters.add(adapterBuilder); |
64 | adapters.add(adapterBuilderFactory, newAdapter); | 47 | return this; |
65 | return newAdapter; | ||
66 | } | 48 | } |
67 | 49 | ||
68 | @Override | 50 | @Override |
69 | public <T extends ModelAdapterBuilder> Optional<T> tryGetAdapter(ModelAdapterType<?, ?, ? extends T> adapterType) { | 51 | public <T extends ModelAdapterBuilder> Optional<T> tryGetAdapter(Class<? extends T> adapterType) { |
70 | return adapters.tryGet(adapterType, adapterType.getModelAdapterBuilderClass()); | 52 | return AdapterUtils.tryGetAdapter(adapters, adapterType); |
71 | } | 53 | } |
72 | 54 | ||
73 | @Override | 55 | @Override |
74 | public <T extends ModelAdapterBuilder> T getAdapter(ModelAdapterType<?, ?, T> adapterType) { | 56 | public <T extends ModelAdapterBuilder> T getAdapter(Class<T> adapterType) { |
75 | return adapters.get(adapterType, adapterType.getModelAdapterBuilderClass()); | 57 | return AdapterUtils.getAdapter(adapters, adapterType); |
76 | } | 58 | } |
77 | 59 | ||
78 | @Override | 60 | @Override |
@@ -81,13 +63,13 @@ public class ModelStoreBuilderImpl implements ModelStoreBuilder { | |||
81 | for (var entry : equivalenceClasses.entrySet()) { | 63 | for (var entry : equivalenceClasses.entrySet()) { |
82 | createStores(stores, entry.getKey(), entry.getValue()); | 64 | createStores(stores, entry.getKey(), entry.getValue()); |
83 | } | 65 | } |
84 | var modelStore = new ModelStoreImpl(stores, adapters.size()); | ||
85 | for (int i = adapters.size() - 1; i >= 0; i--) { | 66 | for (int i = adapters.size() - 1; i >= 0; i--) { |
86 | adapters.get(i).configure(); | 67 | adapters.get(i).configure(this); |
87 | } | 68 | } |
88 | for (var entry : adapters.withAdapterTypes()) { | 69 | var modelStore = new ModelStoreImpl(stores, adapters.size()); |
89 | var adapter = entry.adapter().createStoreAdapter(modelStore); | 70 | for (var adapterBuilder : adapters) { |
90 | modelStore.addAdapter(entry.adapterType(), adapter); | 71 | var storeAdapter = adapterBuilder.build(modelStore); |
72 | modelStore.addAdapter(storeAdapter); | ||
91 | } | 73 | } |
92 | return modelStore; | 74 | return modelStore; |
93 | } | 75 | } |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/model/internal/ModelStoreImpl.java b/subprojects/store/src/main/java/tools/refinery/store/model/internal/ModelStoreImpl.java index e8c205e4..60b735e6 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/model/internal/ModelStoreImpl.java +++ b/subprojects/store/src/main/java/tools/refinery/store/model/internal/ModelStoreImpl.java | |||
@@ -1,8 +1,11 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.model.internal; | 6 | package tools.refinery.store.model.internal; |
2 | 7 | ||
3 | import tools.refinery.store.adapter.AdapterList; | 8 | import tools.refinery.store.adapter.AdapterUtils; |
4 | import tools.refinery.store.adapter.AnyModelAdapterType; | ||
5 | import tools.refinery.store.adapter.ModelAdapterType; | ||
6 | import tools.refinery.store.adapter.ModelStoreAdapter; | 9 | import tools.refinery.store.adapter.ModelStoreAdapter; |
7 | import tools.refinery.store.map.DiffCursor; | 10 | import tools.refinery.store.map.DiffCursor; |
8 | import tools.refinery.store.map.VersionedMapStore; | 11 | import tools.refinery.store.map.VersionedMapStore; |
@@ -16,11 +19,11 @@ import java.util.*; | |||
16 | 19 | ||
17 | public class ModelStoreImpl implements ModelStore { | 20 | public class ModelStoreImpl implements ModelStore { |
18 | private final Map<? extends AnySymbol, ? extends VersionedMapStore<Tuple, ?>> stores; | 21 | private final Map<? extends AnySymbol, ? extends VersionedMapStore<Tuple, ?>> stores; |
19 | private final AdapterList<ModelStoreAdapter> adapters; | 22 | private final List<ModelStoreAdapter> adapters; |
20 | 23 | ||
21 | ModelStoreImpl(Map<? extends AnySymbol, ? extends VersionedMapStore<Tuple, ?>> stores, int adapterCount) { | 24 | ModelStoreImpl(Map<? extends AnySymbol, ? extends VersionedMapStore<Tuple, ?>> stores, int adapterCount) { |
22 | this.stores = stores; | 25 | this.stores = stores; |
23 | adapters = new AdapterList<>(adapterCount); | 26 | adapters = new ArrayList<>(adapterCount); |
24 | } | 27 | } |
25 | 28 | ||
26 | @Override | 29 | @Override |
@@ -59,9 +62,9 @@ public class ModelStoreImpl implements ModelStore { | |||
59 | } | 62 | } |
60 | 63 | ||
61 | private void adaptModel(ModelImpl model) { | 64 | private void adaptModel(ModelImpl model) { |
62 | for (var entry : adapters.withAdapterTypes()) { | 65 | for (var storeAdapter : adapters) { |
63 | var adapter = entry.adapter().createModelAdapter(model); | 66 | var adapter = storeAdapter.createModelAdapter(model); |
64 | model.addAdapter(entry.adapterType(), adapter); | 67 | model.addAdapter(adapter); |
65 | } | 68 | } |
66 | } | 69 | } |
67 | 70 | ||
@@ -86,16 +89,16 @@ public class ModelStoreImpl implements ModelStore { | |||
86 | } | 89 | } |
87 | 90 | ||
88 | @Override | 91 | @Override |
89 | public <T extends ModelStoreAdapter> Optional<T> tryGetAdapter(ModelAdapterType<?, ? extends T, ?> adapterType) { | 92 | public <T extends ModelStoreAdapter> Optional<T> tryGetAdapter(Class<? extends T> adapterType) { |
90 | return adapters.tryGet(adapterType, adapterType.getModelStoreAdapterClass()); | 93 | return AdapterUtils.tryGetAdapter(adapters, adapterType); |
91 | } | 94 | } |
92 | 95 | ||
93 | @Override | 96 | @Override |
94 | public <T extends ModelStoreAdapter> T getAdapter(ModelAdapterType<?, T, ?> adapterType) { | 97 | public <T extends ModelStoreAdapter> T getAdapter(Class<T> adapterType) { |
95 | return adapters.get(adapterType, adapterType.getModelStoreAdapterClass()); | 98 | return AdapterUtils.getAdapter(adapters, adapterType); |
96 | } | 99 | } |
97 | 100 | ||
98 | void addAdapter(AnyModelAdapterType adapterType, ModelStoreAdapter adapter) { | 101 | void addAdapter(ModelStoreAdapter adapter) { |
99 | adapters.add(adapterType, adapter); | 102 | adapters.add(adapter); |
100 | } | 103 | } |
101 | } | 104 | } |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/model/internal/SymbolEquivalenceClass.java b/subprojects/store/src/main/java/tools/refinery/store/model/internal/SymbolEquivalenceClass.java index 5bf1b90d..136f2976 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/model/internal/SymbolEquivalenceClass.java +++ b/subprojects/store/src/main/java/tools/refinery/store/model/internal/SymbolEquivalenceClass.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.model.internal; | 6 | package tools.refinery.store.model.internal; |
2 | 7 | ||
3 | import tools.refinery.store.representation.Symbol; | 8 | import tools.refinery.store.representation.Symbol; |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/model/internal/VersionedInterpretation.java b/subprojects/store/src/main/java/tools/refinery/store/model/internal/VersionedInterpretation.java index c850d334..404be65f 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/model/internal/VersionedInterpretation.java +++ b/subprojects/store/src/main/java/tools/refinery/store/model/internal/VersionedInterpretation.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.model.internal; | 6 | package tools.refinery.store.model.internal; |
2 | 7 | ||
3 | import tools.refinery.store.map.Cursor; | 8 | import tools.refinery.store.map.Cursor; |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/partial/PartialInterpretation.java b/subprojects/store/src/main/java/tools/refinery/store/partial/PartialInterpretation.java deleted file mode 100644 index 331fa294..00000000 --- a/subprojects/store/src/main/java/tools/refinery/store/partial/PartialInterpretation.java +++ /dev/null | |||
@@ -1,19 +0,0 @@ | |||
1 | package tools.refinery.store.partial; | ||
2 | |||
3 | import tools.refinery.store.adapter.ModelAdapterBuilderFactory; | ||
4 | import tools.refinery.store.model.ModelStoreBuilder; | ||
5 | import tools.refinery.store.partial.internal.PartialInterpretationBuilderImpl; | ||
6 | |||
7 | public final class PartialInterpretation extends ModelAdapterBuilderFactory<PartialInterpretationAdapter, | ||
8 | PartialInterpretationStoreAdapter, PartialInterpretationBuilder> { | ||
9 | public static final PartialInterpretation ADAPTER = new PartialInterpretation(); | ||
10 | |||
11 | private PartialInterpretation() { | ||
12 | super(PartialInterpretationAdapter.class, PartialInterpretationStoreAdapter.class, PartialInterpretationBuilder.class); | ||
13 | } | ||
14 | |||
15 | @Override | ||
16 | public PartialInterpretationBuilder createBuilder(ModelStoreBuilder storeBuilder) { | ||
17 | return new PartialInterpretationBuilderImpl(storeBuilder); | ||
18 | } | ||
19 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/partial/PartialInterpretationAdapter.java b/subprojects/store/src/main/java/tools/refinery/store/partial/PartialInterpretationAdapter.java deleted file mode 100644 index 2c83a200..00000000 --- a/subprojects/store/src/main/java/tools/refinery/store/partial/PartialInterpretationAdapter.java +++ /dev/null | |||
@@ -1,9 +0,0 @@ | |||
1 | package tools.refinery.store.partial; | ||
2 | |||
3 | import tools.refinery.store.adapter.ModelAdapter; | ||
4 | |||
5 | public interface PartialInterpretationAdapter extends ModelAdapter { | ||
6 | @Override | ||
7 | PartialInterpretationStoreAdapter getStoreAdapter(); | ||
8 | } | ||
9 | |||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/partial/PartialInterpretationBuilder.java b/subprojects/store/src/main/java/tools/refinery/store/partial/PartialInterpretationBuilder.java deleted file mode 100644 index 0ec13836..00000000 --- a/subprojects/store/src/main/java/tools/refinery/store/partial/PartialInterpretationBuilder.java +++ /dev/null | |||
@@ -1,9 +0,0 @@ | |||
1 | package tools.refinery.store.partial; | ||
2 | |||
3 | import tools.refinery.store.adapter.ModelAdapterBuilder; | ||
4 | import tools.refinery.store.model.ModelStore; | ||
5 | |||
6 | public interface PartialInterpretationBuilder extends ModelAdapterBuilder { | ||
7 | @Override | ||
8 | PartialInterpretationStoreAdapter createStoreAdapter(ModelStore store); | ||
9 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/partial/PartialInterpretationStoreAdapter.java b/subprojects/store/src/main/java/tools/refinery/store/partial/PartialInterpretationStoreAdapter.java deleted file mode 100644 index d4eb770d..00000000 --- a/subprojects/store/src/main/java/tools/refinery/store/partial/PartialInterpretationStoreAdapter.java +++ /dev/null | |||
@@ -1,9 +0,0 @@ | |||
1 | package tools.refinery.store.partial; | ||
2 | |||
3 | import tools.refinery.store.adapter.ModelStoreAdapter; | ||
4 | import tools.refinery.store.model.Model; | ||
5 | |||
6 | public interface PartialInterpretationStoreAdapter extends ModelStoreAdapter { | ||
7 | @Override | ||
8 | PartialInterpretationAdapter createModelAdapter(Model model); | ||
9 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/partial/internal/PartialInterpretationAdapterImpl.java b/subprojects/store/src/main/java/tools/refinery/store/partial/internal/PartialInterpretationAdapterImpl.java deleted file mode 100644 index 4b3977c0..00000000 --- a/subprojects/store/src/main/java/tools/refinery/store/partial/internal/PartialInterpretationAdapterImpl.java +++ /dev/null | |||
@@ -1,24 +0,0 @@ | |||
1 | package tools.refinery.store.partial.internal; | ||
2 | |||
3 | import tools.refinery.store.model.Model; | ||
4 | import tools.refinery.store.partial.PartialInterpretationAdapter; | ||
5 | |||
6 | public class PartialInterpretationAdapterImpl implements PartialInterpretationAdapter { | ||
7 | private final Model model; | ||
8 | private final PartialInterpretationStoreAdapterImpl storeAdapter; | ||
9 | |||
10 | PartialInterpretationAdapterImpl(Model model, PartialInterpretationStoreAdapterImpl storeAdapter) { | ||
11 | this.model = model; | ||
12 | this.storeAdapter = storeAdapter; | ||
13 | } | ||
14 | |||
15 | @Override | ||
16 | public Model getModel() { | ||
17 | return model; | ||
18 | } | ||
19 | |||
20 | @Override | ||
21 | public PartialInterpretationStoreAdapterImpl getStoreAdapter() { | ||
22 | return storeAdapter; | ||
23 | } | ||
24 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/partial/internal/PartialInterpretationBuilderImpl.java b/subprojects/store/src/main/java/tools/refinery/store/partial/internal/PartialInterpretationBuilderImpl.java deleted file mode 100644 index 4609dc32..00000000 --- a/subprojects/store/src/main/java/tools/refinery/store/partial/internal/PartialInterpretationBuilderImpl.java +++ /dev/null | |||
@@ -1,17 +0,0 @@ | |||
1 | package tools.refinery.store.partial.internal; | ||
2 | |||
3 | import tools.refinery.store.adapter.AbstractModelAdapterBuilder; | ||
4 | import tools.refinery.store.model.ModelStore; | ||
5 | import tools.refinery.store.model.ModelStoreBuilder; | ||
6 | import tools.refinery.store.partial.PartialInterpretationBuilder; | ||
7 | |||
8 | public class PartialInterpretationBuilderImpl extends AbstractModelAdapterBuilder implements PartialInterpretationBuilder { | ||
9 | public PartialInterpretationBuilderImpl(ModelStoreBuilder storeBuilder) { | ||
10 | super(storeBuilder); | ||
11 | } | ||
12 | |||
13 | @Override | ||
14 | public PartialInterpretationStoreAdapterImpl createStoreAdapter(ModelStore store) { | ||
15 | return null; | ||
16 | } | ||
17 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/partial/internal/PartialInterpretationStoreAdapterImpl.java b/subprojects/store/src/main/java/tools/refinery/store/partial/internal/PartialInterpretationStoreAdapterImpl.java deleted file mode 100644 index 970b802b..00000000 --- a/subprojects/store/src/main/java/tools/refinery/store/partial/internal/PartialInterpretationStoreAdapterImpl.java +++ /dev/null | |||
@@ -1,23 +0,0 @@ | |||
1 | package tools.refinery.store.partial.internal; | ||
2 | |||
3 | import tools.refinery.store.model.Model; | ||
4 | import tools.refinery.store.model.ModelStore; | ||
5 | import tools.refinery.store.partial.PartialInterpretationStoreAdapter; | ||
6 | |||
7 | public class PartialInterpretationStoreAdapterImpl implements PartialInterpretationStoreAdapter { | ||
8 | private final ModelStore store; | ||
9 | |||
10 | PartialInterpretationStoreAdapterImpl(ModelStore store) { | ||
11 | this.store = store; | ||
12 | } | ||
13 | |||
14 | @Override | ||
15 | public ModelStore getStore() { | ||
16 | return store; | ||
17 | } | ||
18 | |||
19 | @Override | ||
20 | public PartialInterpretationAdapterImpl createModelAdapter(Model model) { | ||
21 | return new PartialInterpretationAdapterImpl(model, this); | ||
22 | } | ||
23 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/DNF.java b/subprojects/store/src/main/java/tools/refinery/store/query/DNF.java deleted file mode 100644 index 95c5d787..00000000 --- a/subprojects/store/src/main/java/tools/refinery/store/query/DNF.java +++ /dev/null | |||
@@ -1,169 +0,0 @@ | |||
1 | package tools.refinery.store.query; | ||
2 | |||
3 | import tools.refinery.store.query.atom.DNFAtom; | ||
4 | |||
5 | import java.util.*; | ||
6 | |||
7 | public final class DNF implements RelationLike { | ||
8 | private final String name; | ||
9 | |||
10 | private final String uniqueName; | ||
11 | |||
12 | private final List<Variable> parameters; | ||
13 | |||
14 | private final List<FunctionalDependency<Variable>> functionalDependencies; | ||
15 | |||
16 | private final List<DNFAnd> clauses; | ||
17 | |||
18 | private DNF(String name, List<Variable> parameters, List<FunctionalDependency<Variable>> functionalDependencies, | ||
19 | List<DNFAnd> clauses) { | ||
20 | validateFunctionalDependencies(parameters, functionalDependencies); | ||
21 | this.name = name; | ||
22 | this.uniqueName = DNFUtils.generateUniqueName(name); | ||
23 | this.parameters = parameters; | ||
24 | this.functionalDependencies = functionalDependencies; | ||
25 | this.clauses = clauses; | ||
26 | } | ||
27 | |||
28 | private static void validateFunctionalDependencies( | ||
29 | Collection<Variable> parameters, Collection<FunctionalDependency<Variable>> functionalDependencies) { | ||
30 | var parameterSet = new HashSet<>(parameters); | ||
31 | for (var functionalDependency : functionalDependencies) { | ||
32 | validateParameters(parameters, parameterSet, functionalDependency.forEach(), functionalDependency); | ||
33 | validateParameters(parameters, parameterSet, functionalDependency.unique(), functionalDependency); | ||
34 | } | ||
35 | } | ||
36 | |||
37 | private static void validateParameters(Collection<Variable> parameters, Set<Variable> parameterSet, | ||
38 | Collection<Variable> toValidate, | ||
39 | FunctionalDependency<Variable> functionalDependency) { | ||
40 | for (var variable : toValidate) { | ||
41 | if (!parameterSet.contains(variable)) { | ||
42 | throw new IllegalArgumentException( | ||
43 | "Variable %s of functional dependency %s does not appear in the parameter list %s" | ||
44 | .formatted(variable, functionalDependency, parameters)); | ||
45 | } | ||
46 | } | ||
47 | } | ||
48 | |||
49 | @Override | ||
50 | public String name() { | ||
51 | return name; | ||
52 | } | ||
53 | |||
54 | public String getUniqueName() { | ||
55 | return uniqueName; | ||
56 | } | ||
57 | |||
58 | public List<Variable> getParameters() { | ||
59 | return parameters; | ||
60 | } | ||
61 | |||
62 | public List<FunctionalDependency<Variable>> getFunctionalDependencies() { | ||
63 | return functionalDependencies; | ||
64 | } | ||
65 | |||
66 | @Override | ||
67 | public int arity() { | ||
68 | return parameters.size(); | ||
69 | } | ||
70 | |||
71 | public List<DNFAnd> getClauses() { | ||
72 | return clauses; | ||
73 | } | ||
74 | |||
75 | public static Builder builder() { | ||
76 | return builder(null); | ||
77 | } | ||
78 | |||
79 | public static Builder builder(String name) { | ||
80 | return new Builder(name); | ||
81 | } | ||
82 | |||
83 | @SuppressWarnings("UnusedReturnValue") | ||
84 | public static class Builder { | ||
85 | private final String name; | ||
86 | |||
87 | private final List<Variable> parameters = new ArrayList<>(); | ||
88 | |||
89 | private final List<FunctionalDependency<Variable>> functionalDependencies = new ArrayList<>(); | ||
90 | |||
91 | private final List<List<DNFAtom>> clauses = new ArrayList<>(); | ||
92 | |||
93 | private Builder(String name) { | ||
94 | this.name = name; | ||
95 | } | ||
96 | |||
97 | public Builder parameter(Variable variable) { | ||
98 | parameters.add(variable); | ||
99 | return this; | ||
100 | } | ||
101 | |||
102 | public Builder parameters(Variable... variables) { | ||
103 | return parameters(List.of(variables)); | ||
104 | } | ||
105 | |||
106 | public Builder parameters(Collection<Variable> variables) { | ||
107 | parameters.addAll(variables); | ||
108 | return this; | ||
109 | } | ||
110 | |||
111 | public Builder functionalDependencies(Collection<FunctionalDependency<Variable>> functionalDependencies) { | ||
112 | this.functionalDependencies.addAll(functionalDependencies); | ||
113 | return this; | ||
114 | } | ||
115 | |||
116 | public Builder functionalDependency(FunctionalDependency<Variable> functionalDependency) { | ||
117 | functionalDependencies.add(functionalDependency); | ||
118 | return this; | ||
119 | } | ||
120 | |||
121 | public Builder functionalDependency(Set<Variable> forEach, Set<Variable> unique) { | ||
122 | return functionalDependency(new FunctionalDependency<>(forEach, unique)); | ||
123 | } | ||
124 | |||
125 | public Builder clause(DNFAtom... atoms) { | ||
126 | clauses.add(List.of(atoms)); | ||
127 | return this; | ||
128 | } | ||
129 | |||
130 | public Builder clause(Collection<DNFAtom> atoms) { | ||
131 | clauses.add(List.copyOf(atoms)); | ||
132 | return this; | ||
133 | } | ||
134 | |||
135 | public Builder clause(DNFAnd clause) { | ||
136 | return clause(clause.constraints()); | ||
137 | } | ||
138 | |||
139 | public Builder clauses(DNFAnd... clauses) { | ||
140 | for (var clause : clauses) { | ||
141 | this.clause(clause); | ||
142 | } | ||
143 | return this; | ||
144 | } | ||
145 | |||
146 | public Builder clauses(Collection<DNFAnd> clauses) { | ||
147 | for (var clause : clauses) { | ||
148 | this.clause(clause); | ||
149 | } | ||
150 | return this; | ||
151 | } | ||
152 | |||
153 | public DNF build() { | ||
154 | var postProcessedClauses = new ArrayList<DNFAnd>(); | ||
155 | for (var constraints : clauses) { | ||
156 | var variables = new HashSet<Variable>(); | ||
157 | for (var constraint : constraints) { | ||
158 | constraint.collectAllVariables(variables); | ||
159 | } | ||
160 | parameters.forEach(variables::remove); | ||
161 | postProcessedClauses.add(new DNFAnd(Collections.unmodifiableSet(variables), | ||
162 | Collections.unmodifiableList(constraints))); | ||
163 | } | ||
164 | return new DNF(name, Collections.unmodifiableList(parameters), | ||
165 | Collections.unmodifiableList(functionalDependencies), | ||
166 | Collections.unmodifiableList(postProcessedClauses)); | ||
167 | } | ||
168 | } | ||
169 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/DNFAnd.java b/subprojects/store/src/main/java/tools/refinery/store/query/DNFAnd.java deleted file mode 100644 index 8c3bf05d..00000000 --- a/subprojects/store/src/main/java/tools/refinery/store/query/DNFAnd.java +++ /dev/null | |||
@@ -1,9 +0,0 @@ | |||
1 | package tools.refinery.store.query; | ||
2 | |||
3 | import tools.refinery.store.query.atom.DNFAtom; | ||
4 | |||
5 | import java.util.List; | ||
6 | import java.util.Set; | ||
7 | |||
8 | public record DNFAnd(Set<Variable> quantifiedVariables, List<DNFAtom> constraints) { | ||
9 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/DNFUtils.java b/subprojects/store/src/main/java/tools/refinery/store/query/DNFUtils.java deleted file mode 100644 index 0ef77d49..00000000 --- a/subprojects/store/src/main/java/tools/refinery/store/query/DNFUtils.java +++ /dev/null | |||
@@ -1,19 +0,0 @@ | |||
1 | package tools.refinery.store.query; | ||
2 | |||
3 | import java.util.UUID; | ||
4 | |||
5 | public final class DNFUtils { | ||
6 | private DNFUtils() { | ||
7 | throw new IllegalStateException("This is a static utility class and should not be instantiated directly"); | ||
8 | } | ||
9 | |||
10 | public static String generateUniqueName(String originalName) { | ||
11 | UUID uuid = UUID.randomUUID(); | ||
12 | String uniqueString = "_" + uuid.toString().replace('-', '_'); | ||
13 | if (originalName == null) { | ||
14 | return uniqueString; | ||
15 | } else { | ||
16 | return originalName + uniqueString; | ||
17 | } | ||
18 | } | ||
19 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/FunctionalDependency.java b/subprojects/store/src/main/java/tools/refinery/store/query/FunctionalDependency.java deleted file mode 100644 index 63a81713..00000000 --- a/subprojects/store/src/main/java/tools/refinery/store/query/FunctionalDependency.java +++ /dev/null | |||
@@ -1,15 +0,0 @@ | |||
1 | package tools.refinery.store.query; | ||
2 | |||
3 | import java.util.HashSet; | ||
4 | import java.util.Set; | ||
5 | |||
6 | public record FunctionalDependency<T>(Set<T> forEach, Set<T> unique) { | ||
7 | public FunctionalDependency { | ||
8 | var uniqueForEach = new HashSet<>(unique); | ||
9 | uniqueForEach.retainAll(forEach); | ||
10 | if (!uniqueForEach.isEmpty()) { | ||
11 | throw new IllegalArgumentException("Variables %s appear on both sides of the functional dependency" | ||
12 | .formatted(uniqueForEach)); | ||
13 | } | ||
14 | } | ||
15 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/ModelQuery.java b/subprojects/store/src/main/java/tools/refinery/store/query/ModelQuery.java deleted file mode 100644 index 6a1aeabb..00000000 --- a/subprojects/store/src/main/java/tools/refinery/store/query/ModelQuery.java +++ /dev/null | |||
@@ -1,11 +0,0 @@ | |||
1 | package tools.refinery.store.query; | ||
2 | |||
3 | import tools.refinery.store.adapter.ModelAdapterType; | ||
4 | |||
5 | public final class ModelQuery extends ModelAdapterType<ModelQueryAdapter, ModelQueryStoreAdapter, ModelQueryBuilder> { | ||
6 | public static final ModelQuery ADAPTER = new ModelQuery(); | ||
7 | |||
8 | private ModelQuery() { | ||
9 | super(ModelQueryAdapter.class, ModelQueryStoreAdapter.class, ModelQueryBuilder.class); | ||
10 | } | ||
11 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/ModelQueryAdapter.java b/subprojects/store/src/main/java/tools/refinery/store/query/ModelQueryAdapter.java deleted file mode 100644 index 7449e39b..00000000 --- a/subprojects/store/src/main/java/tools/refinery/store/query/ModelQueryAdapter.java +++ /dev/null | |||
@@ -1,13 +0,0 @@ | |||
1 | package tools.refinery.store.query; | ||
2 | |||
3 | import tools.refinery.store.adapter.ModelAdapter; | ||
4 | |||
5 | public interface ModelQueryAdapter extends ModelAdapter { | ||
6 | ModelQueryStoreAdapter getStoreAdapter(); | ||
7 | |||
8 | ResultSet getResultSet(DNF query); | ||
9 | |||
10 | boolean hasPendingChanges(); | ||
11 | |||
12 | void flushChanges(); | ||
13 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/ModelQueryBuilder.java b/subprojects/store/src/main/java/tools/refinery/store/query/ModelQueryBuilder.java deleted file mode 100644 index 4364d844..00000000 --- a/subprojects/store/src/main/java/tools/refinery/store/query/ModelQueryBuilder.java +++ /dev/null | |||
@@ -1,23 +0,0 @@ | |||
1 | package tools.refinery.store.query; | ||
2 | |||
3 | import tools.refinery.store.adapter.ModelAdapterBuilder; | ||
4 | import tools.refinery.store.model.ModelStore; | ||
5 | |||
6 | import java.util.Collection; | ||
7 | import java.util.List; | ||
8 | |||
9 | public interface ModelQueryBuilder extends ModelAdapterBuilder { | ||
10 | default ModelQueryBuilder queries(DNF... queries) { | ||
11 | return queries(List.of(queries)); | ||
12 | } | ||
13 | |||
14 | default ModelQueryBuilder queries(Collection<DNF> queries) { | ||
15 | queries.forEach(this::query); | ||
16 | return this; | ||
17 | } | ||
18 | |||
19 | ModelQueryBuilder query(DNF query); | ||
20 | |||
21 | @Override | ||
22 | ModelQueryStoreAdapter createStoreAdapter(ModelStore store); | ||
23 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/ModelQueryStoreAdapter.java b/subprojects/store/src/main/java/tools/refinery/store/query/ModelQueryStoreAdapter.java deleted file mode 100644 index ef5a4587..00000000 --- a/subprojects/store/src/main/java/tools/refinery/store/query/ModelQueryStoreAdapter.java +++ /dev/null | |||
@@ -1,16 +0,0 @@ | |||
1 | package tools.refinery.store.query; | ||
2 | |||
3 | import tools.refinery.store.adapter.ModelStoreAdapter; | ||
4 | import tools.refinery.store.model.Model; | ||
5 | import tools.refinery.store.query.view.AnyRelationView; | ||
6 | |||
7 | import java.util.Collection; | ||
8 | |||
9 | public interface ModelQueryStoreAdapter extends ModelStoreAdapter { | ||
10 | Collection<AnyRelationView> getRelationViews(); | ||
11 | |||
12 | Collection<DNF> getQueries(); | ||
13 | |||
14 | @Override | ||
15 | ModelQueryAdapter createModelAdapter(Model model); | ||
16 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/RelationLike.java b/subprojects/store/src/main/java/tools/refinery/store/query/RelationLike.java deleted file mode 100644 index 8c784d8b..00000000 --- a/subprojects/store/src/main/java/tools/refinery/store/query/RelationLike.java +++ /dev/null | |||
@@ -1,11 +0,0 @@ | |||
1 | package tools.refinery.store.query; | ||
2 | |||
3 | public interface RelationLike { | ||
4 | String name(); | ||
5 | |||
6 | int arity(); | ||
7 | |||
8 | default boolean invalidIndex(int i) { | ||
9 | return i < 0 || i >= arity(); | ||
10 | } | ||
11 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/ResultSet.java b/subprojects/store/src/main/java/tools/refinery/store/query/ResultSet.java deleted file mode 100644 index 3542e252..00000000 --- a/subprojects/store/src/main/java/tools/refinery/store/query/ResultSet.java +++ /dev/null | |||
@@ -1,25 +0,0 @@ | |||
1 | package tools.refinery.store.query; | ||
2 | |||
3 | import tools.refinery.store.tuple.Tuple; | ||
4 | import tools.refinery.store.tuple.TupleLike; | ||
5 | |||
6 | import java.util.Optional; | ||
7 | import java.util.stream.Stream; | ||
8 | |||
9 | public interface ResultSet { | ||
10 | boolean hasResult(); | ||
11 | |||
12 | boolean hasResult(Tuple parameters); | ||
13 | |||
14 | Optional<TupleLike> oneResult(); | ||
15 | |||
16 | Optional<TupleLike> oneResult(Tuple parameters); | ||
17 | |||
18 | Stream<TupleLike> allResults(); | ||
19 | |||
20 | Stream<TupleLike> allResults(Tuple parameters); | ||
21 | |||
22 | int countResults(); | ||
23 | |||
24 | int countResults(Tuple parameters); | ||
25 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/Variable.java b/subprojects/store/src/main/java/tools/refinery/store/query/Variable.java deleted file mode 100644 index 3632f3c5..00000000 --- a/subprojects/store/src/main/java/tools/refinery/store/query/Variable.java +++ /dev/null | |||
@@ -1,43 +0,0 @@ | |||
1 | package tools.refinery.store.query; | ||
2 | |||
3 | import java.util.Objects; | ||
4 | |||
5 | public class Variable { | ||
6 | private final String name; | ||
7 | private final String uniqueName; | ||
8 | |||
9 | public Variable() { | ||
10 | this(null); | ||
11 | } | ||
12 | |||
13 | public Variable(String name) { | ||
14 | super(); | ||
15 | this.name = name; | ||
16 | this.uniqueName = DNFUtils.generateUniqueName(name); | ||
17 | |||
18 | } | ||
19 | public String getName() { | ||
20 | return name; | ||
21 | } | ||
22 | |||
23 | public String getUniqueName() { | ||
24 | return uniqueName; | ||
25 | } | ||
26 | |||
27 | public boolean isNamed() { | ||
28 | return name != null; | ||
29 | } | ||
30 | |||
31 | @Override | ||
32 | public boolean equals(Object o) { | ||
33 | if (this == o) return true; | ||
34 | if (o == null || getClass() != o.getClass()) return false; | ||
35 | Variable variable = (Variable) o; | ||
36 | return Objects.equals(uniqueName, variable.uniqueName); | ||
37 | } | ||
38 | |||
39 | @Override | ||
40 | public int hashCode() { | ||
41 | return Objects.hash(uniqueName); | ||
42 | } | ||
43 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/atom/CallAtom.java b/subprojects/store/src/main/java/tools/refinery/store/query/atom/CallAtom.java deleted file mode 100644 index 47121870..00000000 --- a/subprojects/store/src/main/java/tools/refinery/store/query/atom/CallAtom.java +++ /dev/null | |||
@@ -1,80 +0,0 @@ | |||
1 | package tools.refinery.store.query.atom; | ||
2 | |||
3 | import tools.refinery.store.query.Variable; | ||
4 | import tools.refinery.store.query.RelationLike; | ||
5 | |||
6 | import java.util.List; | ||
7 | import java.util.Objects; | ||
8 | import java.util.Set; | ||
9 | |||
10 | public abstract class CallAtom<T extends RelationLike> implements DNFAtom { | ||
11 | private final CallPolarity polarity; | ||
12 | private final T target; | ||
13 | private final List<Variable> substitution; | ||
14 | |||
15 | protected CallAtom(CallPolarity polarity, T target, List<Variable> substitution) { | ||
16 | if (substitution.size() != target.arity()) { | ||
17 | throw new IllegalArgumentException("%s needs %d arguments, but got %s".formatted(target.name(), | ||
18 | target.arity(), substitution.size())); | ||
19 | } | ||
20 | if (polarity.isTransitive() && target.arity() != 2) { | ||
21 | throw new IllegalArgumentException("Transitive closures can only take binary relations"); | ||
22 | } | ||
23 | this.polarity = polarity; | ||
24 | this.target = target; | ||
25 | this.substitution = substitution; | ||
26 | } | ||
27 | |||
28 | protected CallAtom(CallPolarity polarity, T target, Variable... substitution) { | ||
29 | this(polarity, target, List.of(substitution)); | ||
30 | } | ||
31 | |||
32 | protected CallAtom(boolean positive, T target, List<Variable> substitution) { | ||
33 | this(CallPolarity.fromBoolean(positive), target, substitution); | ||
34 | } | ||
35 | |||
36 | protected CallAtom(boolean positive, T target, Variable... substitution) { | ||
37 | this(positive, target, List.of(substitution)); | ||
38 | } | ||
39 | |||
40 | protected CallAtom(T target, List<Variable> substitution) { | ||
41 | this(true, target, substitution); | ||
42 | } | ||
43 | |||
44 | protected CallAtom(T target, Variable... substitution) { | ||
45 | this(target, List.of(substitution)); | ||
46 | } | ||
47 | |||
48 | public CallPolarity getPolarity() { | ||
49 | return polarity; | ||
50 | } | ||
51 | |||
52 | public T getTarget() { | ||
53 | return target; | ||
54 | } | ||
55 | |||
56 | public List<Variable> getSubstitution() { | ||
57 | return substitution; | ||
58 | } | ||
59 | |||
60 | @Override | ||
61 | public void collectAllVariables(Set<Variable> variables) { | ||
62 | if (polarity.isPositive()) { | ||
63 | variables.addAll(substitution); | ||
64 | } | ||
65 | } | ||
66 | |||
67 | @Override | ||
68 | public boolean equals(Object o) { | ||
69 | if (this == o) return true; | ||
70 | if (o == null || getClass() != o.getClass()) return false; | ||
71 | CallAtom<?> callAtom = (CallAtom<?>) o; | ||
72 | return polarity == callAtom.polarity && Objects.equals(target, callAtom.target) && Objects.equals(substitution | ||
73 | , callAtom.substitution); | ||
74 | } | ||
75 | |||
76 | @Override | ||
77 | public int hashCode() { | ||
78 | return Objects.hash(polarity, target, substitution); | ||
79 | } | ||
80 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/atom/CallPolarity.java b/subprojects/store/src/main/java/tools/refinery/store/query/atom/CallPolarity.java deleted file mode 100644 index 957e9b7b..00000000 --- a/subprojects/store/src/main/java/tools/refinery/store/query/atom/CallPolarity.java +++ /dev/null | |||
@@ -1,28 +0,0 @@ | |||
1 | package tools.refinery.store.query.atom; | ||
2 | |||
3 | public enum CallPolarity { | ||
4 | POSITIVE(true, false), | ||
5 | NEGATIVE(false, false), | ||
6 | TRANSITIVE(true, true); | ||
7 | |||
8 | private final boolean positive; | ||
9 | |||
10 | private final boolean transitive; | ||
11 | |||
12 | CallPolarity(boolean positive, boolean transitive) { | ||
13 | this.positive = positive; | ||
14 | this.transitive = transitive; | ||
15 | } | ||
16 | |||
17 | public boolean isPositive() { | ||
18 | return positive; | ||
19 | } | ||
20 | |||
21 | public boolean isTransitive() { | ||
22 | return transitive; | ||
23 | } | ||
24 | |||
25 | public static CallPolarity fromBoolean(boolean positive) { | ||
26 | return positive ? POSITIVE : NEGATIVE; | ||
27 | } | ||
28 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/atom/ConstantAtom.java b/subprojects/store/src/main/java/tools/refinery/store/query/atom/ConstantAtom.java deleted file mode 100644 index 13dae7d0..00000000 --- a/subprojects/store/src/main/java/tools/refinery/store/query/atom/ConstantAtom.java +++ /dev/null | |||
@@ -1,12 +0,0 @@ | |||
1 | package tools.refinery.store.query.atom; | ||
2 | |||
3 | import tools.refinery.store.query.Variable; | ||
4 | |||
5 | import java.util.Set; | ||
6 | |||
7 | public record ConstantAtom(Variable variable, int nodeId) implements DNFAtom { | ||
8 | @Override | ||
9 | public void collectAllVariables(Set<Variable> variables) { | ||
10 | variables.add(variable); | ||
11 | } | ||
12 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/atom/DNFAtom.java b/subprojects/store/src/main/java/tools/refinery/store/query/atom/DNFAtom.java deleted file mode 100644 index ebf71236..00000000 --- a/subprojects/store/src/main/java/tools/refinery/store/query/atom/DNFAtom.java +++ /dev/null | |||
@@ -1,9 +0,0 @@ | |||
1 | package tools.refinery.store.query.atom; | ||
2 | |||
3 | import tools.refinery.store.query.Variable; | ||
4 | |||
5 | import java.util.Set; | ||
6 | |||
7 | public interface DNFAtom { | ||
8 | void collectAllVariables(Set<Variable> variables); | ||
9 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/atom/DNFCallAtom.java b/subprojects/store/src/main/java/tools/refinery/store/query/atom/DNFCallAtom.java deleted file mode 100644 index 3b4f5cd1..00000000 --- a/subprojects/store/src/main/java/tools/refinery/store/query/atom/DNFCallAtom.java +++ /dev/null | |||
@@ -1,32 +0,0 @@ | |||
1 | package tools.refinery.store.query.atom; | ||
2 | |||
3 | import tools.refinery.store.query.DNF; | ||
4 | import tools.refinery.store.query.Variable; | ||
5 | |||
6 | import java.util.List; | ||
7 | |||
8 | public class DNFCallAtom extends CallAtom<DNF> { | ||
9 | public DNFCallAtom(CallPolarity polarity, DNF target, List<Variable> substitution) { | ||
10 | super(polarity, target, substitution); | ||
11 | } | ||
12 | |||
13 | public DNFCallAtom(CallPolarity polarity, DNF target, Variable... substitution) { | ||
14 | super(polarity, target, substitution); | ||
15 | } | ||
16 | |||
17 | public DNFCallAtom(boolean positive, DNF target, List<Variable> substitution) { | ||
18 | super(positive, target, substitution); | ||
19 | } | ||
20 | |||
21 | public DNFCallAtom(boolean positive, DNF target, Variable... substitution) { | ||
22 | super(positive, target, substitution); | ||
23 | } | ||
24 | |||
25 | public DNFCallAtom(DNF target, List<Variable> substitution) { | ||
26 | super(target, substitution); | ||
27 | } | ||
28 | |||
29 | public DNFCallAtom(DNF target, Variable... substitution) { | ||
30 | super(target, substitution); | ||
31 | } | ||
32 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/atom/EquivalenceAtom.java b/subprojects/store/src/main/java/tools/refinery/store/query/atom/EquivalenceAtom.java deleted file mode 100644 index b1b3a6f7..00000000 --- a/subprojects/store/src/main/java/tools/refinery/store/query/atom/EquivalenceAtom.java +++ /dev/null | |||
@@ -1,17 +0,0 @@ | |||
1 | package tools.refinery.store.query.atom; | ||
2 | |||
3 | import tools.refinery.store.query.Variable; | ||
4 | |||
5 | import java.util.Set; | ||
6 | |||
7 | public record EquivalenceAtom(boolean positive, Variable left, Variable right) implements DNFAtom { | ||
8 | public EquivalenceAtom(Variable left, Variable right) { | ||
9 | this(true, left, right); | ||
10 | } | ||
11 | |||
12 | @Override | ||
13 | public void collectAllVariables(Set<Variable> variables) { | ||
14 | variables.add(left); | ||
15 | variables.add(right); | ||
16 | } | ||
17 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/atom/Modality.java b/subprojects/store/src/main/java/tools/refinery/store/query/atom/Modality.java deleted file mode 100644 index e389f563..00000000 --- a/subprojects/store/src/main/java/tools/refinery/store/query/atom/Modality.java +++ /dev/null | |||
@@ -1,22 +0,0 @@ | |||
1 | package tools.refinery.store.query.atom; | ||
2 | |||
3 | import java.util.Locale; | ||
4 | |||
5 | public enum Modality { | ||
6 | MUST, | ||
7 | MAY, | ||
8 | CURRENT; | ||
9 | |||
10 | public Modality negate() { | ||
11 | return switch(this) { | ||
12 | case MUST -> MAY; | ||
13 | case MAY -> MUST; | ||
14 | case CURRENT -> CURRENT; | ||
15 | }; | ||
16 | } | ||
17 | |||
18 | @Override | ||
19 | public String toString() { | ||
20 | return name().toLowerCase(Locale.ROOT); | ||
21 | } | ||
22 | } | ||
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 deleted file mode 100644 index a2b176c4..00000000 --- a/subprojects/store/src/main/java/tools/refinery/store/query/atom/RelationViewAtom.java +++ /dev/null | |||
@@ -1,32 +0,0 @@ | |||
1 | package tools.refinery.store.query.atom; | ||
2 | |||
3 | import tools.refinery.store.query.Variable; | ||
4 | import tools.refinery.store.query.view.AnyRelationView; | ||
5 | |||
6 | import java.util.List; | ||
7 | |||
8 | public final class RelationViewAtom extends CallAtom<AnyRelationView> { | ||
9 | public RelationViewAtom(CallPolarity polarity, AnyRelationView target, List<Variable> substitution) { | ||
10 | super(polarity, target, substitution); | ||
11 | } | ||
12 | |||
13 | public RelationViewAtom(CallPolarity polarity, AnyRelationView target, Variable... substitution) { | ||
14 | super(polarity, target, substitution); | ||
15 | } | ||
16 | |||
17 | public RelationViewAtom(boolean positive, AnyRelationView target, List<Variable> substitution) { | ||
18 | super(positive, target, substitution); | ||
19 | } | ||
20 | |||
21 | public RelationViewAtom(boolean positive, AnyRelationView target, Variable... substitution) { | ||
22 | super(positive, target, substitution); | ||
23 | } | ||
24 | |||
25 | public RelationViewAtom(AnyRelationView target, List<Variable> substitution) { | ||
26 | super(target, substitution); | ||
27 | } | ||
28 | |||
29 | public RelationViewAtom(AnyRelationView target, Variable... substitution) { | ||
30 | super(target, substitution); | ||
31 | } | ||
32 | } | ||
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 deleted file mode 100644 index 328cde3a..00000000 --- a/subprojects/store/src/main/java/tools/refinery/store/query/view/AnyRelationView.java +++ /dev/null | |||
@@ -1,24 +0,0 @@ | |||
1 | package tools.refinery.store.query.view; | ||
2 | |||
3 | import tools.refinery.store.model.Model; | ||
4 | import tools.refinery.store.query.FunctionalDependency; | ||
5 | import tools.refinery.store.representation.AnySymbol; | ||
6 | import tools.refinery.store.query.RelationLike; | ||
7 | |||
8 | import java.util.Set; | ||
9 | |||
10 | public sealed interface AnyRelationView extends RelationLike permits RelationView { | ||
11 | AnySymbol getSymbol(); | ||
12 | |||
13 | default Set<FunctionalDependency<Integer>> getFunctionalDependencies() { | ||
14 | return Set.of(); | ||
15 | } | ||
16 | |||
17 | default Set<RelationViewImplication> getImpliedRelationViews() { | ||
18 | return Set.of(); | ||
19 | } | ||
20 | |||
21 | boolean get(Model model, Object[] tuple); | ||
22 | |||
23 | Iterable<Object[]> getAll(Model model); | ||
24 | } | ||
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 deleted file mode 100644 index 64c601bb..00000000 --- a/subprojects/store/src/main/java/tools/refinery/store/query/view/FilteredRelationView.java +++ /dev/null | |||
@@ -1,49 +0,0 @@ | |||
1 | package tools.refinery.store.query.view; | ||
2 | |||
3 | import tools.refinery.store.tuple.Tuple; | ||
4 | import tools.refinery.store.representation.Symbol; | ||
5 | |||
6 | import java.util.Objects; | ||
7 | import java.util.function.BiPredicate; | ||
8 | import java.util.function.Predicate; | ||
9 | |||
10 | public class FilteredRelationView<T> extends TuplePreservingRelationView<T> { | ||
11 | private final BiPredicate<Tuple, T> predicate; | ||
12 | |||
13 | public FilteredRelationView(Symbol<T> symbol, String name, BiPredicate<Tuple, T> predicate) { | ||
14 | super(symbol, name); | ||
15 | this.predicate = predicate; | ||
16 | } | ||
17 | |||
18 | public FilteredRelationView(Symbol<T> symbol, BiPredicate<Tuple, T> predicate) { | ||
19 | super(symbol); | ||
20 | this.predicate = predicate; | ||
21 | } | ||
22 | |||
23 | public FilteredRelationView(Symbol<T> symbol, String name, Predicate<T> predicate) { | ||
24 | this(symbol, name, (k, v) -> predicate.test(v)); | ||
25 | } | ||
26 | |||
27 | public FilteredRelationView(Symbol<T> symbol, Predicate<T> predicate) { | ||
28 | this(symbol, (k, v) -> predicate.test(v)); | ||
29 | } | ||
30 | |||
31 | @Override | ||
32 | public boolean filter(Tuple key, T value) { | ||
33 | return this.predicate.test(key, value); | ||
34 | } | ||
35 | |||
36 | @Override | ||
37 | public boolean equals(Object o) { | ||
38 | if (this == o) return true; | ||
39 | if (o == null || getClass() != o.getClass()) return false; | ||
40 | if (!super.equals(o)) return false; | ||
41 | FilteredRelationView<?> that = (FilteredRelationView<?>) o; | ||
42 | return Objects.equals(predicate, that.predicate); | ||
43 | } | ||
44 | |||
45 | @Override | ||
46 | public int hashCode() { | ||
47 | return Objects.hash(super.hashCode(), predicate); | ||
48 | } | ||
49 | } | ||
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 deleted file mode 100644 index 3d278a8b..00000000 --- a/subprojects/store/src/main/java/tools/refinery/store/query/view/FunctionalRelationView.java +++ /dev/null | |||
@@ -1,71 +0,0 @@ | |||
1 | package tools.refinery.store.query.view; | ||
2 | |||
3 | import tools.refinery.store.model.Model; | ||
4 | import tools.refinery.store.query.FunctionalDependency; | ||
5 | import tools.refinery.store.representation.Symbol; | ||
6 | import tools.refinery.store.tuple.Tuple; | ||
7 | import tools.refinery.store.tuple.Tuple1; | ||
8 | |||
9 | import java.util.Set; | ||
10 | import java.util.stream.Collectors; | ||
11 | import java.util.stream.IntStream; | ||
12 | |||
13 | public final class FunctionalRelationView<T> extends RelationView<T> { | ||
14 | public FunctionalRelationView(Symbol<T> symbol, String name) { | ||
15 | super(symbol, name); | ||
16 | } | ||
17 | |||
18 | public FunctionalRelationView(Symbol<T> symbol) { | ||
19 | super(symbol); | ||
20 | } | ||
21 | |||
22 | @Override | ||
23 | public Set<FunctionalDependency<Integer>> getFunctionalDependencies() { | ||
24 | var arity = getSymbol().arity(); | ||
25 | var forEach = IntStream.range(0, arity).boxed().collect(Collectors.toUnmodifiableSet()); | ||
26 | var unique = Set.of(arity); | ||
27 | return Set.of(new FunctionalDependency<>(forEach, unique)); | ||
28 | } | ||
29 | |||
30 | @Override | ||
31 | public Set<RelationViewImplication> getImpliedRelationViews() { | ||
32 | var symbol = getSymbol(); | ||
33 | var impliedIndices = IntStream.range(0, symbol.arity()).boxed().toList(); | ||
34 | var keyOnlyRelationView = new KeyOnlyRelationView<>(symbol); | ||
35 | return Set.of(new RelationViewImplication(this, keyOnlyRelationView, impliedIndices)); | ||
36 | } | ||
37 | |||
38 | @Override | ||
39 | public boolean filter(Tuple key, T value) { | ||
40 | return true; | ||
41 | } | ||
42 | |||
43 | @Override | ||
44 | public Object[] forwardMap(Tuple key, T value) { | ||
45 | int size = key.getSize(); | ||
46 | Object[] result = new Object[size + 1]; | ||
47 | for (int i = 0; i < size; i++) { | ||
48 | result[i] = Tuple.of(key.get(i)); | ||
49 | } | ||
50 | result[key.getSize()] = value; | ||
51 | return result; | ||
52 | } | ||
53 | |||
54 | @Override | ||
55 | public boolean get(Model model, Object[] tuple) { | ||
56 | int[] content = new int[tuple.length - 1]; | ||
57 | for (int i = 0; i < tuple.length - 1; i++) { | ||
58 | content[i] = ((Tuple1) tuple[i]).value0(); | ||
59 | } | ||
60 | Tuple key = Tuple.of(content); | ||
61 | @SuppressWarnings("unchecked") | ||
62 | T valueInTuple = (T) tuple[tuple.length - 1]; | ||
63 | T valueInMap = model.getInterpretation(getSymbol()).get(key); | ||
64 | return valueInTuple.equals(valueInMap); | ||
65 | } | ||
66 | |||
67 | @Override | ||
68 | public int arity() { | ||
69 | return getSymbol().arity() + 1; | ||
70 | } | ||
71 | } | ||
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 deleted file mode 100644 index e1b2e45b..00000000 --- a/subprojects/store/src/main/java/tools/refinery/store/query/view/KeyOnlyRelationView.java +++ /dev/null | |||
@@ -1,36 +0,0 @@ | |||
1 | package tools.refinery.store.query.view; | ||
2 | |||
3 | import tools.refinery.store.representation.Symbol; | ||
4 | import tools.refinery.store.tuple.Tuple; | ||
5 | |||
6 | import java.util.Objects; | ||
7 | |||
8 | public final class KeyOnlyRelationView<T> extends TuplePreservingRelationView<T> { | ||
9 | public static final String VIEW_NAME = "key"; | ||
10 | |||
11 | private final T defaultValue; | ||
12 | |||
13 | public KeyOnlyRelationView(Symbol<T> symbol) { | ||
14 | super(symbol, VIEW_NAME); | ||
15 | defaultValue = symbol.defaultValue(); | ||
16 | } | ||
17 | |||
18 | @Override | ||
19 | public boolean filter(Tuple key, T value) { | ||
20 | return !Objects.equals(value, defaultValue); | ||
21 | } | ||
22 | |||
23 | @Override | ||
24 | public boolean equals(Object o) { | ||
25 | if (this == o) return true; | ||
26 | if (o == null || getClass() != o.getClass()) return false; | ||
27 | if (!super.equals(o)) return false; | ||
28 | KeyOnlyRelationView<?> that = (KeyOnlyRelationView<?>) o; | ||
29 | return Objects.equals(defaultValue, that.defaultValue); | ||
30 | } | ||
31 | |||
32 | @Override | ||
33 | public int hashCode() { | ||
34 | return Objects.hash(super.hashCode(), defaultValue); | ||
35 | } | ||
36 | } | ||
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 deleted file mode 100644 index bbec1e73..00000000 --- a/subprojects/store/src/main/java/tools/refinery/store/query/view/RelationView.java +++ /dev/null | |||
@@ -1,62 +0,0 @@ | |||
1 | package tools.refinery.store.query.view; | ||
2 | |||
3 | import tools.refinery.store.map.CursorAsIterator; | ||
4 | import tools.refinery.store.model.Model; | ||
5 | import tools.refinery.store.representation.Symbol; | ||
6 | import tools.refinery.store.tuple.Tuple; | ||
7 | |||
8 | import java.util.Objects; | ||
9 | import java.util.UUID; | ||
10 | |||
11 | /** | ||
12 | * Represents a view of a {@link Symbol} that can be queried. | ||
13 | * | ||
14 | * @param <T> | ||
15 | * @author Oszkar Semerath | ||
16 | */ | ||
17 | public abstract non-sealed class RelationView<T> implements AnyRelationView { | ||
18 | private final Symbol<T> symbol; | ||
19 | |||
20 | private final String name; | ||
21 | |||
22 | protected RelationView(Symbol<T> symbol, String name) { | ||
23 | this.symbol = symbol; | ||
24 | this.name = name; | ||
25 | } | ||
26 | |||
27 | protected RelationView(Symbol<T> representation) { | ||
28 | this(representation, UUID.randomUUID().toString()); | ||
29 | } | ||
30 | |||
31 | @Override | ||
32 | public Symbol<T> getSymbol() { | ||
33 | return symbol; | ||
34 | } | ||
35 | |||
36 | @Override | ||
37 | public String name() { | ||
38 | return symbol.name() + "#" + name; | ||
39 | } | ||
40 | |||
41 | public abstract boolean filter(Tuple key, T value); | ||
42 | |||
43 | public abstract Object[] forwardMap(Tuple key, T value); | ||
44 | |||
45 | @Override | ||
46 | public Iterable<Object[]> getAll(Model model) { | ||
47 | return (() -> new CursorAsIterator<>(model.getInterpretation(symbol).getAll(), this::forwardMap, this::filter)); | ||
48 | } | ||
49 | |||
50 | @Override | ||
51 | public boolean equals(Object o) { | ||
52 | if (this == o) return true; | ||
53 | if (o == null || getClass() != o.getClass()) return false; | ||
54 | RelationView<?> that = (RelationView<?>) o; | ||
55 | return Objects.equals(symbol, that.symbol) && Objects.equals(name, that.name); | ||
56 | } | ||
57 | |||
58 | @Override | ||
59 | public int hashCode() { | ||
60 | return Objects.hash(symbol, name); | ||
61 | } | ||
62 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/view/RelationViewImplication.java b/subprojects/store/src/main/java/tools/refinery/store/query/view/RelationViewImplication.java deleted file mode 100644 index 2ba1fcc4..00000000 --- a/subprojects/store/src/main/java/tools/refinery/store/query/view/RelationViewImplication.java +++ /dev/null | |||
@@ -1,19 +0,0 @@ | |||
1 | package tools.refinery.store.query.view; | ||
2 | |||
3 | import java.util.List; | ||
4 | |||
5 | public record RelationViewImplication(AnyRelationView implyingRelationView, AnyRelationView impliedRelationView, | ||
6 | List<Integer> impliedIndices) { | ||
7 | public RelationViewImplication { | ||
8 | if (impliedIndices.size() != impliedRelationView.arity()) { | ||
9 | throw new IllegalArgumentException("Expected %d implied indices for %s, but %d are provided" | ||
10 | .formatted(impliedRelationView.arity(), impliedRelationView, impliedIndices.size())); | ||
11 | } | ||
12 | for (var index : impliedIndices) { | ||
13 | if (impliedRelationView.invalidIndex(index)) { | ||
14 | throw new IllegalArgumentException("%d is not a valid index for %s".formatted(index, | ||
15 | implyingRelationView)); | ||
16 | } | ||
17 | } | ||
18 | } | ||
19 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/view/TuplePreservingRelationView.java b/subprojects/store/src/main/java/tools/refinery/store/query/view/TuplePreservingRelationView.java deleted file mode 100644 index 8cc4986e..00000000 --- a/subprojects/store/src/main/java/tools/refinery/store/query/view/TuplePreservingRelationView.java +++ /dev/null | |||
@@ -1,44 +0,0 @@ | |||
1 | package tools.refinery.store.query.view; | ||
2 | |||
3 | import tools.refinery.store.model.Model; | ||
4 | import tools.refinery.store.tuple.Tuple; | ||
5 | import tools.refinery.store.tuple.Tuple1; | ||
6 | import tools.refinery.store.representation.Symbol; | ||
7 | |||
8 | public abstract class TuplePreservingRelationView<T> extends RelationView<T> { | ||
9 | protected TuplePreservingRelationView(Symbol<T> symbol, String name) { | ||
10 | super(symbol, name); | ||
11 | } | ||
12 | |||
13 | protected TuplePreservingRelationView(Symbol<T> symbol) { | ||
14 | super(symbol); | ||
15 | } | ||
16 | |||
17 | public Object[] forwardMap(Tuple key) { | ||
18 | Object[] result = new Object[key.getSize()]; | ||
19 | for (int i = 0; i < key.getSize(); i++) { | ||
20 | result[i] = Tuple.of(key.get(i)); | ||
21 | } | ||
22 | return result; | ||
23 | } | ||
24 | |||
25 | @Override | ||
26 | public Object[] forwardMap(Tuple key, T value) { | ||
27 | return forwardMap(key); | ||
28 | } | ||
29 | |||
30 | @Override | ||
31 | public boolean get(Model model, Object[] tuple) { | ||
32 | int[] content = new int[tuple.length]; | ||
33 | for (int i = 0; i < tuple.length; i++) { | ||
34 | content[i] = ((Tuple1) tuple[i]).value0(); | ||
35 | } | ||
36 | Tuple key = Tuple.of(content); | ||
37 | T value = model.getInterpretation(getSymbol()).get(key); | ||
38 | return filter(key, value); | ||
39 | } | ||
40 | |||
41 | public int arity() { | ||
42 | return this.getSymbol().arity(); | ||
43 | } | ||
44 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/representation/AbstractDomain.java b/subprojects/store/src/main/java/tools/refinery/store/representation/AbstractDomain.java new file mode 100644 index 00000000..52c740e8 --- /dev/null +++ b/subprojects/store/src/main/java/tools/refinery/store/representation/AbstractDomain.java | |||
@@ -0,0 +1,34 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.representation; | ||
7 | |||
8 | import java.util.Optional; | ||
9 | |||
10 | public non-sealed interface AbstractDomain<A, C> extends AnyAbstractDomain { | ||
11 | @Override | ||
12 | Class<A> abstractType(); | ||
13 | |||
14 | @Override | ||
15 | Class<C> concreteType(); | ||
16 | |||
17 | A toAbstract(C concreteValue); | ||
18 | |||
19 | Optional<C> toConcrete(A abstractValue); | ||
20 | |||
21 | default boolean isConcrete(A abstractValue) { | ||
22 | return toConcrete(abstractValue).isPresent(); | ||
23 | } | ||
24 | |||
25 | boolean isRefinement(A originalValue, A refinedValue); | ||
26 | |||
27 | A commonRefinement(A leftValue, A rightValue); | ||
28 | |||
29 | A commonAncestor(A leftValue, A rightValue); | ||
30 | |||
31 | A unknown(); | ||
32 | |||
33 | boolean isError(A abstractValue); | ||
34 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/representation/AnyAbstractDomain.java b/subprojects/store/src/main/java/tools/refinery/store/representation/AnyAbstractDomain.java new file mode 100644 index 00000000..c354fab7 --- /dev/null +++ b/subprojects/store/src/main/java/tools/refinery/store/representation/AnyAbstractDomain.java | |||
@@ -0,0 +1,12 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.representation; | ||
7 | |||
8 | public sealed interface AnyAbstractDomain permits AbstractDomain { | ||
9 | Class<?> abstractType(); | ||
10 | |||
11 | Class<?> concreteType(); | ||
12 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/representation/AnySymbol.java b/subprojects/store/src/main/java/tools/refinery/store/representation/AnySymbol.java index 20b9eead..b2377905 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/representation/AnySymbol.java +++ b/subprojects/store/src/main/java/tools/refinery/store/representation/AnySymbol.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.representation; | 6 | package tools.refinery.store.representation; |
2 | 7 | ||
3 | public sealed interface AnySymbol permits Symbol { | 8 | public sealed interface AnySymbol permits Symbol { |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/representation/Symbol.java b/subprojects/store/src/main/java/tools/refinery/store/representation/Symbol.java index 85ea15f4..cc748180 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/representation/Symbol.java +++ b/subprojects/store/src/main/java/tools/refinery/store/representation/Symbol.java | |||
@@ -1,25 +1,25 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.representation; | 6 | package tools.refinery.store.representation; |
2 | 7 | ||
3 | import java.util.Objects; | ||
4 | |||
5 | public record Symbol<T>(String name, int arity, Class<T> valueType, T defaultValue) implements AnySymbol { | 8 | public record Symbol<T>(String name, int arity, Class<T> valueType, T defaultValue) implements AnySymbol { |
6 | public boolean isDefaultValue(T value) { | 9 | @Override |
7 | return Objects.equals(defaultValue, value); | 10 | public String toString() { |
11 | return "%s/%d".formatted(name, arity); | ||
8 | } | 12 | } |
9 | 13 | ||
10 | @Override | 14 | public static Symbol<Boolean> of(String name, int arity) { |
11 | public boolean equals(Object o) { | 15 | return of(name, arity, Boolean.class, false); |
12 | return this == o; | ||
13 | } | 16 | } |
14 | 17 | ||
15 | @Override | 18 | public static <T> Symbol<T> of(String name, int arity, Class<T> valueType) { |
16 | public int hashCode() { | 19 | return of(name, arity, valueType, null); |
17 | // Compare by identity to make hash table lookups more efficient. | ||
18 | return System.identityHashCode(this); | ||
19 | } | 20 | } |
20 | 21 | ||
21 | @Override | 22 | public static <T> Symbol<T> of(String name, int arity, Class<T> valueType, T defaultValue) { |
22 | public String toString() { | 23 | return new Symbol<>(name, arity, valueType, defaultValue); |
23 | return "%s/%d".formatted(name, arity); | ||
24 | } | 24 | } |
25 | } | 25 | } |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/representation/TruthValue.java b/subprojects/store/src/main/java/tools/refinery/store/representation/TruthValue.java index b7893fd3..40baf9a5 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/representation/TruthValue.java +++ b/subprojects/store/src/main/java/tools/refinery/store/representation/TruthValue.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.representation; | 6 | package tools.refinery.store.representation; |
2 | 7 | ||
3 | public enum TruthValue { | 8 | public enum TruthValue { |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/representation/TruthValueDomain.java b/subprojects/store/src/main/java/tools/refinery/store/representation/TruthValueDomain.java new file mode 100644 index 00000000..89f8dd19 --- /dev/null +++ b/subprojects/store/src/main/java/tools/refinery/store/representation/TruthValueDomain.java | |||
@@ -0,0 +1,65 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.representation; | ||
7 | |||
8 | import java.util.Optional; | ||
9 | |||
10 | public final class TruthValueDomain implements AbstractDomain<TruthValue, Boolean> { | ||
11 | public static final TruthValueDomain INSTANCE = new TruthValueDomain(); | ||
12 | |||
13 | private TruthValueDomain() { | ||
14 | } | ||
15 | |||
16 | @Override | ||
17 | public Class<TruthValue> abstractType() { | ||
18 | return null; | ||
19 | } | ||
20 | |||
21 | @Override | ||
22 | public Class<Boolean> concreteType() { | ||
23 | return null; | ||
24 | } | ||
25 | |||
26 | @Override | ||
27 | public TruthValue toAbstract(Boolean concreteValue) { | ||
28 | return null; | ||
29 | } | ||
30 | |||
31 | @Override | ||
32 | public Optional<Boolean> toConcrete(TruthValue abstractValue) { | ||
33 | return Optional.empty(); | ||
34 | } | ||
35 | |||
36 | @Override | ||
37 | public boolean isConcrete(TruthValue abstractValue) { | ||
38 | return AbstractDomain.super.isConcrete(abstractValue); | ||
39 | } | ||
40 | |||
41 | @Override | ||
42 | public boolean isRefinement(TruthValue originalValue, TruthValue refinedValue) { | ||
43 | return false; | ||
44 | } | ||
45 | |||
46 | @Override | ||
47 | public TruthValue commonRefinement(TruthValue leftValue, TruthValue rightValue) { | ||
48 | return null; | ||
49 | } | ||
50 | |||
51 | @Override | ||
52 | public TruthValue commonAncestor(TruthValue leftValue, TruthValue rightValue) { | ||
53 | return null; | ||
54 | } | ||
55 | |||
56 | @Override | ||
57 | public TruthValue unknown() { | ||
58 | return null; | ||
59 | } | ||
60 | |||
61 | @Override | ||
62 | public boolean isError(TruthValue abstractValue) { | ||
63 | return false; | ||
64 | } | ||
65 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/CardinalityInterval.java b/subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/CardinalityInterval.java index 273d0de7..704ca2fc 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/CardinalityInterval.java +++ b/subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/CardinalityInterval.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.representation.cardinality; | 6 | package tools.refinery.store.representation.cardinality; |
2 | 7 | ||
3 | public sealed interface CardinalityInterval permits NonEmptyCardinalityInterval, EmptyCardinalityInterval { | 8 | public sealed interface CardinalityInterval permits NonEmptyCardinalityInterval, EmptyCardinalityInterval { |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/CardinalityIntervals.java b/subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/CardinalityIntervals.java index e1a08bf9..ad16a3e8 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/CardinalityIntervals.java +++ b/subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/CardinalityIntervals.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.representation.cardinality; | 6 | package tools.refinery.store.representation.cardinality; |
2 | 7 | ||
3 | public final class CardinalityIntervals { | 8 | public final class CardinalityIntervals { |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/EmptyCardinalityInterval.java b/subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/EmptyCardinalityInterval.java index ab3ad9d1..49911c29 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/EmptyCardinalityInterval.java +++ b/subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/EmptyCardinalityInterval.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.representation.cardinality; | 6 | package tools.refinery.store.representation.cardinality; |
2 | 7 | ||
3 | public final class EmptyCardinalityInterval implements CardinalityInterval { | 8 | public final class EmptyCardinalityInterval implements CardinalityInterval { |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/FiniteUpperCardinality.java b/subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/FiniteUpperCardinality.java index 381c8a57..82afdbbc 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/FiniteUpperCardinality.java +++ b/subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/FiniteUpperCardinality.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.representation.cardinality; | 6 | package tools.refinery.store.representation.cardinality; |
2 | 7 | ||
3 | import org.jetbrains.annotations.NotNull; | 8 | import org.jetbrains.annotations.NotNull; |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/NonEmptyCardinalityInterval.java b/subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/NonEmptyCardinalityInterval.java index 32b3786f..38bd53bf 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/NonEmptyCardinalityInterval.java +++ b/subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/NonEmptyCardinalityInterval.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.representation.cardinality; | 6 | package tools.refinery.store.representation.cardinality; |
2 | 7 | ||
3 | import java.util.function.BinaryOperator; | 8 | import java.util.function.BinaryOperator; |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/UnboundedUpperCardinality.java b/subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/UnboundedUpperCardinality.java index 593bc322..a5634020 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/UnboundedUpperCardinality.java +++ b/subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/UnboundedUpperCardinality.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.representation.cardinality; | 6 | package tools.refinery.store.representation.cardinality; |
2 | 7 | ||
3 | import org.jetbrains.annotations.NotNull; | 8 | import org.jetbrains.annotations.NotNull; |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/UpperCardinalities.java b/subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/UpperCardinalities.java index d850fdc9..1e18dde0 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/UpperCardinalities.java +++ b/subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/UpperCardinalities.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.representation.cardinality; | 6 | package tools.refinery.store.representation.cardinality; |
2 | 7 | ||
3 | public final class UpperCardinalities { | 8 | public final class UpperCardinalities { |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/UpperCardinality.java b/subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/UpperCardinality.java index c6e31cb7..5dbaa922 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/UpperCardinality.java +++ b/subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/UpperCardinality.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.representation.cardinality; | 6 | package tools.refinery.store.representation.cardinality; |
2 | 7 | ||
3 | public sealed interface UpperCardinality extends Comparable<UpperCardinality> permits FiniteUpperCardinality, | 8 | public sealed interface UpperCardinality extends Comparable<UpperCardinality> permits FiniteUpperCardinality, |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/tuple/Tuple.java b/subprojects/store/src/main/java/tools/refinery/store/tuple/Tuple.java index bf844c6d..aae7b344 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/tuple/Tuple.java +++ b/subprojects/store/src/main/java/tools/refinery/store/tuple/Tuple.java | |||
@@ -1,28 +1,60 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.tuple; | 6 | package tools.refinery.store.tuple; |
2 | 7 | ||
3 | public sealed interface Tuple extends TupleLike permits Tuple0, Tuple1, Tuple2, TupleN { | 8 | import org.jetbrains.annotations.NotNull; |
9 | |||
10 | public sealed interface Tuple extends Comparable<Tuple> permits Tuple0, Tuple1, Tuple2, Tuple3, Tuple4, TupleN { | ||
11 | int getSize(); | ||
12 | |||
13 | int get(int element); | ||
14 | |||
4 | @Override | 15 | @Override |
5 | default Tuple toTuple() { | 16 | default int compareTo(@NotNull Tuple other) { |
6 | return this; | 17 | int size = getSize(); |
18 | int compareSize = Integer.compare(size, other.getSize()); | ||
19 | if (compareSize != 0) { | ||
20 | return compareSize; | ||
21 | } | ||
22 | for (int i = 0; i < size; i++) { | ||
23 | int compareElement = Integer.compare(get(i), other.get(i)); | ||
24 | if (compareElement != 0) { | ||
25 | return compareElement; | ||
26 | } | ||
27 | } | ||
28 | return 0; | ||
7 | } | 29 | } |
8 | 30 | ||
9 | static Tuple of() { | 31 | static Tuple0 of() { |
10 | return Tuple0.INSTANCE; | 32 | return Tuple0.INSTANCE; |
11 | } | 33 | } |
12 | 34 | ||
13 | static Tuple of(int value) { | 35 | static Tuple1 of(int value) { |
14 | return Tuple1.Cache.INSTANCE.getOrCreate(value); | 36 | return Tuple1.Cache.INSTANCE.getOrCreate(value); |
15 | } | 37 | } |
16 | 38 | ||
17 | static Tuple of(int value1, int value2) { | 39 | static Tuple2 of(int value1, int value2) { |
18 | return new Tuple2(value1, value2); | 40 | return new Tuple2(value1, value2); |
19 | } | 41 | } |
20 | 42 | ||
43 | static Tuple3 of(int value1, int value2, int value3) { | ||
44 | return new Tuple3(value1, value2, value3); | ||
45 | } | ||
46 | |||
47 | static Tuple4 of(int value1, int value2, int value3, int value4) { | ||
48 | return new Tuple4(value1, value2, value3, value4); | ||
49 | } | ||
50 | |||
21 | static Tuple of(int... values) { | 51 | static Tuple of(int... values) { |
22 | return switch (values.length) { | 52 | return switch (values.length) { |
23 | case 0 -> of(); | 53 | case 0 -> of(); |
24 | case 1 -> of(values[0]); | 54 | case 1 -> of(values[0]); |
25 | case 2 -> of(values[0], values[1]); | 55 | case 2 -> of(values[0], values[1]); |
56 | case 3 -> of(values[0], values[1], values[2]); | ||
57 | case 4 -> of(values[0], values[1], values[2], values[3]); | ||
26 | default -> new TupleN(values); | 58 | default -> new TupleN(values); |
27 | }; | 59 | }; |
28 | } | 60 | } |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/tuple/Tuple0.java b/subprojects/store/src/main/java/tools/refinery/store/tuple/Tuple0.java index 8eea5c3a..a9aa9bf2 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/tuple/Tuple0.java +++ b/subprojects/store/src/main/java/tools/refinery/store/tuple/Tuple0.java | |||
@@ -1,7 +1,22 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.tuple; | 6 | package tools.refinery.store.tuple; |
2 | 7 | ||
3 | public record Tuple0() implements Tuple { | 8 | import static tools.refinery.store.tuple.TupleConstants.TUPLE_BEGIN; |
4 | public static Tuple0 INSTANCE = new Tuple0(); | 9 | import static tools.refinery.store.tuple.TupleConstants.TUPLE_END; |
10 | |||
11 | /** | ||
12 | * Singleton implementation to ensure only a single empty tuple exists. | ||
13 | */ | ||
14 | @SuppressWarnings("squid:S6548") | ||
15 | public final class Tuple0 implements Tuple { | ||
16 | public static final Tuple0 INSTANCE = new Tuple0(); | ||
17 | |||
18 | private Tuple0() { | ||
19 | } | ||
5 | 20 | ||
6 | @Override | 21 | @Override |
7 | public int getSize() { | 22 | public int getSize() { |
@@ -14,12 +29,7 @@ public record Tuple0() implements Tuple { | |||
14 | } | 29 | } |
15 | 30 | ||
16 | @Override | 31 | @Override |
17 | public int[] toArray() { | ||
18 | return new int[]{}; | ||
19 | } | ||
20 | |||
21 | @Override | ||
22 | public String toString() { | 32 | public String toString() { |
23 | return "[]"; | 33 | return TUPLE_BEGIN + TUPLE_END; |
24 | } | 34 | } |
25 | } | 35 | } |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/tuple/Tuple1.java b/subprojects/store/src/main/java/tools/refinery/store/tuple/Tuple1.java index 07380966..388ee3a9 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/tuple/Tuple1.java +++ b/subprojects/store/src/main/java/tools/refinery/store/tuple/Tuple1.java | |||
@@ -1,10 +1,29 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.tuple; | 6 | package tools.refinery.store.tuple; |
2 | 7 | ||
8 | import org.jetbrains.annotations.NotNull; | ||
3 | import tools.refinery.store.model.TupleHashProvider; | 9 | import tools.refinery.store.model.TupleHashProvider; |
4 | 10 | ||
5 | import java.util.Arrays; | 11 | import java.util.Arrays; |
6 | 12 | ||
7 | public record Tuple1(int value0) implements Tuple { | 13 | import static tools.refinery.store.tuple.TupleConstants.TUPLE_BEGIN; |
14 | import static tools.refinery.store.tuple.TupleConstants.TUPLE_END; | ||
15 | |||
16 | public final class Tuple1 implements Tuple { | ||
17 | private final int value0; | ||
18 | |||
19 | private Tuple1(int value0) { | ||
20 | this.value0 = value0; | ||
21 | } | ||
22 | |||
23 | public int value0() { | ||
24 | return value0; | ||
25 | } | ||
26 | |||
8 | @Override | 27 | @Override |
9 | public int getSize() { | 28 | public int getSize() { |
10 | return 1; | 29 | return 1; |
@@ -19,20 +38,40 @@ public record Tuple1(int value0) implements Tuple { | |||
19 | } | 38 | } |
20 | 39 | ||
21 | @Override | 40 | @Override |
22 | public int[] toArray() { | 41 | public String toString() { |
23 | return new int[]{value0}; | 42 | return TUPLE_BEGIN + value0 + TUPLE_END; |
24 | } | 43 | } |
25 | 44 | ||
26 | @Override | 45 | @Override |
27 | public String toString() { | 46 | public boolean equals(Object o) { |
28 | return "[" + value0 + "]"; | 47 | if (this == o) return true; |
48 | if (o == null || getClass() != o.getClass()) return false; | ||
49 | Tuple1 tuple1 = (Tuple1) o; | ||
50 | return value0 == tuple1.value0; | ||
51 | } | ||
52 | |||
53 | @Override | ||
54 | public int hashCode() { | ||
55 | return 31 + value0; | ||
56 | } | ||
57 | |||
58 | @Override | ||
59 | public int compareTo(@NotNull Tuple other) { | ||
60 | if (other instanceof Tuple1 other1) { | ||
61 | return Integer.compare(value0, other1.value0); | ||
62 | } | ||
63 | return Tuple.super.compareTo(other); | ||
29 | } | 64 | } |
30 | 65 | ||
31 | /** | 66 | /** |
32 | * This class uses safe double-checked locking, see | 67 | * This class uses safe double-checked locking, see |
33 | * <a href="https://shipilev.net/blog/2014/safe-public-construction/">Safe Publication and Safe Initialization in | 68 | * <a href="https://shipilev.net/blog/2014/safe-public-construction/">Safe Publication and Safe Initialization in |
34 | * Java</a> for details. | 69 | * Java</a> for details. |
70 | * <p> | ||
71 | * This class implements the singleton pattern to ensure only a single cache exists. This is thread-safe because | ||
72 | * of the locking of the cache. | ||
35 | */ | 73 | */ |
74 | @SuppressWarnings("squid:S6548") | ||
36 | public static class Cache { | 75 | public static class Cache { |
37 | private static final int MIN_CACHE_SIZE = 256; | 76 | private static final int MIN_CACHE_SIZE = 256; |
38 | 77 | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/tuple/Tuple2.java b/subprojects/store/src/main/java/tools/refinery/store/tuple/Tuple2.java index 0836a32d..6d886fd3 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/tuple/Tuple2.java +++ b/subprojects/store/src/main/java/tools/refinery/store/tuple/Tuple2.java | |||
@@ -1,5 +1,14 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.tuple; | 6 | package tools.refinery.store.tuple; |
2 | 7 | ||
8 | import org.jetbrains.annotations.NotNull; | ||
9 | |||
10 | import static tools.refinery.store.tuple.TupleConstants.*; | ||
11 | |||
3 | public record Tuple2(int value0, int value1) implements Tuple { | 12 | public record Tuple2(int value0, int value1) implements Tuple { |
4 | @Override | 13 | @Override |
5 | public int getSize() { | 14 | public int getSize() { |
@@ -16,12 +25,34 @@ public record Tuple2(int value0, int value1) implements Tuple { | |||
16 | } | 25 | } |
17 | 26 | ||
18 | @Override | 27 | @Override |
19 | public int[] toArray() { | 28 | public String toString() { |
20 | return new int[]{value0, value1}; | 29 | return TUPLE_BEGIN + value0 + TUPLE_SEPARATOR + value1 + TUPLE_END; |
21 | } | 30 | } |
22 | 31 | ||
23 | @Override | 32 | @Override |
24 | public String toString() { | 33 | public boolean equals(Object o) { |
25 | return "[" + value0 + ", " + value1 + "]"; | 34 | if (this == o) return true; |
35 | if (o == null || getClass() != o.getClass()) return false; | ||
36 | Tuple2 tuple2 = (Tuple2) o; | ||
37 | return value0 == tuple2.value0 && value1 == tuple2.value1; | ||
38 | } | ||
39 | |||
40 | @Override | ||
41 | public int hashCode() { | ||
42 | int hash = 31 + value0; | ||
43 | hash = 31 * hash + value1; | ||
44 | return hash; | ||
45 | } | ||
46 | |||
47 | @Override | ||
48 | public int compareTo(@NotNull Tuple other) { | ||
49 | if (other instanceof Tuple2 other2) { | ||
50 | int compare0 = Integer.compare(value0, other2.value0); | ||
51 | if (compare0 != 0) { | ||
52 | return compare0; | ||
53 | } | ||
54 | return Integer.compare(value1, other2.value1); | ||
55 | } | ||
56 | return Tuple.super.compareTo(other); | ||
26 | } | 57 | } |
27 | } | 58 | } |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/tuple/Tuple3.java b/subprojects/store/src/main/java/tools/refinery/store/tuple/Tuple3.java new file mode 100644 index 00000000..734e45c2 --- /dev/null +++ b/subprojects/store/src/main/java/tools/refinery/store/tuple/Tuple3.java | |||
@@ -0,0 +1,64 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.tuple; | ||
7 | |||
8 | import org.jetbrains.annotations.NotNull; | ||
9 | |||
10 | import static tools.refinery.store.tuple.TupleConstants.*; | ||
11 | |||
12 | public record Tuple3(int value0, int value1, int value2) implements Tuple { | ||
13 | @Override | ||
14 | public int getSize() { | ||
15 | return 3; | ||
16 | } | ||
17 | |||
18 | @Override | ||
19 | public int get(int element) { | ||
20 | return switch (element) { | ||
21 | case 0 -> value0; | ||
22 | case 1 -> value1; | ||
23 | case 2 -> value2; | ||
24 | default -> throw new ArrayIndexOutOfBoundsException(element); | ||
25 | }; | ||
26 | } | ||
27 | |||
28 | @Override | ||
29 | public String toString() { | ||
30 | return TUPLE_BEGIN + value0 + TUPLE_SEPARATOR + value1 + TUPLE_SEPARATOR + value2 + TUPLE_END; | ||
31 | } | ||
32 | |||
33 | @Override | ||
34 | public boolean equals(Object o) { | ||
35 | if (this == o) return true; | ||
36 | if (o == null || getClass() != o.getClass()) return false; | ||
37 | Tuple3 tuple3 = (Tuple3) o; | ||
38 | return value0 == tuple3.value0 && value1 == tuple3.value1 && value2 == tuple3.value2; | ||
39 | } | ||
40 | |||
41 | @Override | ||
42 | public int hashCode() { | ||
43 | int hash = 31 + value0; | ||
44 | hash = 31 * hash + value1; | ||
45 | hash = 31 * hash + value2; | ||
46 | return hash; | ||
47 | } | ||
48 | |||
49 | @Override | ||
50 | public int compareTo(@NotNull Tuple other) { | ||
51 | if (other instanceof Tuple3 other3) { | ||
52 | int compare0 = Integer.compare(value0, other3.value0); | ||
53 | if (compare0 != 0) { | ||
54 | return compare0; | ||
55 | } | ||
56 | int compare1 = Integer.compare(value1, other3.value1); | ||
57 | if (compare1 != 0) { | ||
58 | return compare1; | ||
59 | } | ||
60 | return Integer.compare(value2, other3.value2); | ||
61 | } | ||
62 | return Tuple.super.compareTo(other); | ||
63 | } | ||
64 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/tuple/Tuple4.java b/subprojects/store/src/main/java/tools/refinery/store/tuple/Tuple4.java new file mode 100644 index 00000000..e1b93e7b --- /dev/null +++ b/subprojects/store/src/main/java/tools/refinery/store/tuple/Tuple4.java | |||
@@ -0,0 +1,71 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.tuple; | ||
7 | |||
8 | import org.jetbrains.annotations.NotNull; | ||
9 | |||
10 | import static tools.refinery.store.tuple.TupleConstants.*; | ||
11 | |||
12 | public record Tuple4(int value0, int value1, int value2, int value3) implements Tuple { | ||
13 | @Override | ||
14 | public int getSize() { | ||
15 | return 4; | ||
16 | } | ||
17 | |||
18 | @Override | ||
19 | public int get(int element) { | ||
20 | return switch (element) { | ||
21 | case 0 -> value0; | ||
22 | case 1 -> value1; | ||
23 | case 2 -> value2; | ||
24 | case 3 -> value3; | ||
25 | default -> throw new ArrayIndexOutOfBoundsException(element); | ||
26 | }; | ||
27 | } | ||
28 | |||
29 | @Override | ||
30 | public String toString() { | ||
31 | return TUPLE_BEGIN + value0 + TUPLE_SEPARATOR + value1 + TUPLE_SEPARATOR + value2 + TUPLE_SEPARATOR + value3 + | ||
32 | TUPLE_END; | ||
33 | } | ||
34 | |||
35 | @Override | ||
36 | public boolean equals(Object o) { | ||
37 | if (this == o) return true; | ||
38 | if (o == null || getClass() != o.getClass()) return false; | ||
39 | Tuple4 tuple4 = (Tuple4) o; | ||
40 | return value0 == tuple4.value0 && value1 == tuple4.value1 && value2 == tuple4.value2 && value3 == tuple4.value3; | ||
41 | } | ||
42 | |||
43 | @Override | ||
44 | public int hashCode() { | ||
45 | int hash = 31 + value0; | ||
46 | hash = 31 * hash + value1; | ||
47 | hash = 31 * hash + value2; | ||
48 | hash = 31 * hash + value3; | ||
49 | return hash; | ||
50 | } | ||
51 | |||
52 | @Override | ||
53 | public int compareTo(@NotNull Tuple other) { | ||
54 | if (other instanceof Tuple4 other4) { | ||
55 | int compare0 = Integer.compare(value0, other4.value0); | ||
56 | if (compare0 != 0) { | ||
57 | return compare0; | ||
58 | } | ||
59 | int compare1 = Integer.compare(value1, other4.value1); | ||
60 | if (compare1 != 0) { | ||
61 | return compare1; | ||
62 | } | ||
63 | int compare2 = Integer.compare(value2, other4.value2); | ||
64 | if (compare2 != 0) { | ||
65 | return compare2; | ||
66 | } | ||
67 | return Integer.compare(value3, other4.value3); | ||
68 | } | ||
69 | return Tuple.super.compareTo(other); | ||
70 | } | ||
71 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/tuple/TupleConstants.java b/subprojects/store/src/main/java/tools/refinery/store/tuple/TupleConstants.java new file mode 100644 index 00000000..f7d27848 --- /dev/null +++ b/subprojects/store/src/main/java/tools/refinery/store/tuple/TupleConstants.java | |||
@@ -0,0 +1,17 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.tuple; | ||
7 | |||
8 | final class TupleConstants { | ||
9 | public static final int MAX_STATIC_ARITY_TUPLE_SIZE = 4; | ||
10 | public static final String TUPLE_BEGIN = "["; | ||
11 | public static final String TUPLE_SEPARATOR = ", "; | ||
12 | public static final String TUPLE_END = "]"; | ||
13 | |||
14 | private TupleConstants() { | ||
15 | throw new IllegalArgumentException("This is a static utility class an should not instantiated directly"); | ||
16 | } | ||
17 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/tuple/TupleLike.java b/subprojects/store/src/main/java/tools/refinery/store/tuple/TupleLike.java deleted file mode 100644 index 470ca298..00000000 --- a/subprojects/store/src/main/java/tools/refinery/store/tuple/TupleLike.java +++ /dev/null | |||
@@ -1,25 +0,0 @@ | |||
1 | package tools.refinery.store.tuple; | ||
2 | |||
3 | public interface TupleLike { | ||
4 | int getSize(); | ||
5 | |||
6 | int get(int element); | ||
7 | |||
8 | default int[] toArray() { | ||
9 | int size = getSize(); | ||
10 | var array = new int[size]; | ||
11 | for (int i = 0; i < size; i++) { | ||
12 | array[i] = get(i); | ||
13 | } | ||
14 | return array; | ||
15 | } | ||
16 | |||
17 | default Tuple toTuple() { | ||
18 | return switch (getSize()) { | ||
19 | case 0 -> Tuple.of(); | ||
20 | case 1 -> Tuple.of(get(0)); | ||
21 | case 2 -> Tuple.of(get(0), get(1)); | ||
22 | default -> Tuple.of(toArray()); | ||
23 | }; | ||
24 | } | ||
25 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/tuple/TupleN.java b/subprojects/store/src/main/java/tools/refinery/store/tuple/TupleN.java index 15fd063b..b66af491 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/tuple/TupleN.java +++ b/subprojects/store/src/main/java/tools/refinery/store/tuple/TupleN.java | |||
@@ -1,14 +1,23 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.tuple; | 6 | package tools.refinery.store.tuple; |
2 | 7 | ||
3 | import java.util.Arrays; | 8 | import java.util.Arrays; |
4 | import java.util.stream.Collectors; | 9 | import java.util.stream.Collectors; |
5 | 10 | ||
6 | public record TupleN(int[] values) implements Tuple { | 11 | import static tools.refinery.store.tuple.TupleConstants.*; |
7 | static final int CUSTOM_TUPLE_SIZE = 2; | ||
8 | 12 | ||
9 | public TupleN(int[] values) { | 13 | public final class TupleN implements Tuple { |
10 | if (values.length < CUSTOM_TUPLE_SIZE) | 14 | private final int[] values; |
11 | throw new IllegalArgumentException(); | 15 | |
16 | TupleN(int[] values) { | ||
17 | if (values.length < MAX_STATIC_ARITY_TUPLE_SIZE) { | ||
18 | throw new IllegalArgumentException("Tuples of size at most %d must use static arity Tuple classes" | ||
19 | .formatted(MAX_STATIC_ARITY_TUPLE_SIZE)); | ||
20 | } | ||
12 | this.values = Arrays.copyOf(values, values.length); | 21 | this.values = Arrays.copyOf(values, values.length); |
13 | } | 22 | } |
14 | 23 | ||
@@ -23,19 +32,11 @@ public record TupleN(int[] values) implements Tuple { | |||
23 | } | 32 | } |
24 | 33 | ||
25 | @Override | 34 | @Override |
26 | public int[] toArray() { | ||
27 | return values; | ||
28 | } | ||
29 | |||
30 | @Override | ||
31 | public String toString() { | 35 | public String toString() { |
32 | var valuesString = Arrays.stream(values).mapToObj(Integer::toString).collect(Collectors.joining(", ")); | 36 | var valuesString = Arrays.stream(values) |
33 | return "[" + valuesString + "]"; | 37 | .mapToObj(Integer::toString) |
34 | } | 38 | .collect(Collectors.joining(TUPLE_SEPARATOR)); |
35 | 39 | return TUPLE_BEGIN + valuesString + TUPLE_END; | |
36 | @Override | ||
37 | public int hashCode() { | ||
38 | return Arrays.hashCode(values); | ||
39 | } | 40 | } |
40 | 41 | ||
41 | @Override | 42 | @Override |
@@ -49,4 +50,9 @@ public record TupleN(int[] values) implements Tuple { | |||
49 | TupleN other = (TupleN) obj; | 50 | TupleN other = (TupleN) obj; |
50 | return Arrays.equals(values, other.values); | 51 | return Arrays.equals(values, other.values); |
51 | } | 52 | } |
53 | |||
54 | @Override | ||
55 | public int hashCode() { | ||
56 | return Arrays.hashCode(values); | ||
57 | } | ||
52 | } | 58 | } |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/util/CollectionsUtil.java b/subprojects/store/src/main/java/tools/refinery/store/util/CollectionsUtil.java index 841d0dfa..adecd79b 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/util/CollectionsUtil.java +++ b/subprojects/store/src/main/java/tools/refinery/store/util/CollectionsUtil.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.util; | 6 | package tools.refinery.store.util; |
2 | 7 | ||
3 | import java.util.Iterator; | 8 | import java.util.Iterator; |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/util/CycleDetectingMapper.java b/subprojects/store/src/main/java/tools/refinery/store/util/CycleDetectingMapper.java new file mode 100644 index 00000000..78ad2ad7 --- /dev/null +++ b/subprojects/store/src/main/java/tools/refinery/store/util/CycleDetectingMapper.java | |||
@@ -0,0 +1,57 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.util; | ||
7 | |||
8 | import java.util.*; | ||
9 | import java.util.function.Function; | ||
10 | import java.util.stream.Collectors; | ||
11 | |||
12 | public class CycleDetectingMapper<T, R> { | ||
13 | private static final String SEPARATOR = " -> "; | ||
14 | |||
15 | private final Function<T, String> getName; | ||
16 | |||
17 | private final Function<T, R> doMap; | ||
18 | |||
19 | private final Set<T> inProgress = new LinkedHashSet<>(); | ||
20 | |||
21 | private final Map<T, R> results = new HashMap<>(); | ||
22 | |||
23 | public CycleDetectingMapper(Function<T, String> getName, Function<T, R> doMap) { | ||
24 | this.getName = getName; | ||
25 | this.doMap = doMap; | ||
26 | } | ||
27 | |||
28 | public R map(T input) { | ||
29 | if (inProgress.contains(input)) { | ||
30 | var path = inProgress.stream().map(getName).collect(Collectors.joining(SEPARATOR)); | ||
31 | throw new IllegalArgumentException("Circular reference %s%s%s detected".formatted(path, SEPARATOR, | ||
32 | getName.apply(input))); | ||
33 | } | ||
34 | // We can't use computeIfAbsent here, because translating referenced queries calls this method in a reentrant | ||
35 | // way, which would cause a ConcurrentModificationException with computeIfAbsent. | ||
36 | @SuppressWarnings("squid:S3824") | ||
37 | var result = results.get(input); | ||
38 | if (result == null) { | ||
39 | inProgress.add(input); | ||
40 | try { | ||
41 | result = doMap.apply(input); | ||
42 | results.put(input, result); | ||
43 | } finally { | ||
44 | inProgress.remove(input); | ||
45 | } | ||
46 | } | ||
47 | return result; | ||
48 | } | ||
49 | |||
50 | public List<T> getInProgress() { | ||
51 | return List.copyOf(inProgress); | ||
52 | } | ||
53 | |||
54 | public R getAlreadyMapped(T input) { | ||
55 | return results.get(input); | ||
56 | } | ||
57 | } | ||