diff options
author | Kristóf Marussy <kristof@marussy.com> | 2023-04-21 02:12:04 +0200 |
---|---|---|
committer | Kristóf Marussy <kristof@marussy.com> | 2023-04-21 02:34:52 +0200 |
commit | ea0f09096afe05e2d414c707584e1e33c0c44383 (patch) | |
tree | 60763156db85be14e34aaf1b504ccbd1faad8bff /subprojects/store/src | |
parent | fix: REAL_SUM input and result type (diff) | |
download | refinery-ea0f09096afe05e2d414c707584e1e33c0c44383.tar.gz refinery-ea0f09096afe05e2d414c707584e1e33c0c44383.tar.zst refinery-ea0f09096afe05e2d414c707584e1e33c0c44383.zip |
refactor: simplify ModelAdapter
* Remove the reflection-based machinery around adapter types.
* Adapter builders, store adapters, and model adapters are now only associated
with each other based on static and runtime types.
* Simplifies writing new adapters.
* Hierarchical syntax for adding adapter builders to the store builder.
Diffstat (limited to 'subprojects/store/src')
13 files changed, 111 insertions, 327 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 70602ef5..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,32 +1,48 @@ | |||
1 | package tools.refinery.store.adapter; | ||
1 | /* | 2 | /* |
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | 3 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> |
3 | * | 4 | * |
4 | * SPDX-License-Identifier: EPL-2.0 | 5 | * SPDX-License-Identifier: EPL-2.0 |
5 | */ | 6 | */ |
6 | package tools.refinery.store.adapter; | ||
7 | |||
8 | import tools.refinery.store.model.ModelStore; | 7 | import tools.refinery.store.model.ModelStore; |
9 | import tools.refinery.store.model.ModelStoreBuilder; | 8 | import tools.refinery.store.model.ModelStoreBuilder; |
10 | 9 | ||
11 | public abstract class AbstractModelAdapterBuilder implements ModelAdapterBuilder { | 10 | public abstract class AbstractModelAdapterBuilder<T extends ModelStoreAdapter> implements ModelAdapterBuilder { |
12 | private final ModelStoreBuilder storeBuilder; | 11 | private boolean configured; |
13 | 12 | ||
14 | protected AbstractModelAdapterBuilder(ModelStoreBuilder storeBuilder) { | 13 | @Override |
15 | this.storeBuilder = storeBuilder; | 14 | public boolean isConfigured() { |
15 | return configured; | ||
16 | } | 16 | } |
17 | 17 | ||
18 | @Override | 18 | protected void checkConfigured() { |
19 | public <T extends ModelAdapterBuilder> T with(ModelAdapterBuilderFactory<?, ?, T> adapterBuilderFactory) { | 19 | if (!configured) { |
20 | 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. | ||
21 | } | 32 | } |
22 | 33 | ||
23 | @Override | 34 | @Override |
24 | public ModelStoreBuilder getStoreBuilder() { | 35 | public final void configure(ModelStoreBuilder storeBuilder) { |
25 | return storeBuilder; | 36 | checkNotConfigured(); |
37 | doConfigure(storeBuilder); | ||
38 | configured = true; | ||
26 | } | 39 | } |
27 | 40 | ||
41 | protected abstract T doBuild(ModelStore store); | ||
42 | |||
28 | @Override | 43 | @Override |
29 | public ModelStore build() { | 44 | public final T build(ModelStore store) { |
30 | return storeBuilder.build(); | 45 | checkConfigured(); |
46 | return doBuild(store); | ||
31 | } | 47 | } |
32 | } | 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 e896d8d9..00000000 --- a/subprojects/store/src/main/java/tools/refinery/store/adapter/AdapterList.java +++ /dev/null | |||
@@ -1,102 +0,0 @@ | |||
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 org.jetbrains.annotations.NotNull; | ||
9 | |||
10 | import java.util.*; | ||
11 | import java.util.function.Consumer; | ||
12 | |||
13 | public class AdapterList<T> implements Iterable<T> { | ||
14 | private final List<AnyModelAdapterType> adapterTypes; | ||
15 | private final List<T> adapters; | ||
16 | |||
17 | public AdapterList() { | ||
18 | adapterTypes = new ArrayList<>(); | ||
19 | adapters = new ArrayList<>(); | ||
20 | } | ||
21 | |||
22 | public AdapterList(int adapterCount) { | ||
23 | adapterTypes = new ArrayList<>(adapterCount); | ||
24 | adapters = new ArrayList<>(adapterCount); | ||
25 | } | ||
26 | |||
27 | public int size() { | ||
28 | return adapters.size(); | ||
29 | } | ||
30 | |||
31 | public void add(AnyModelAdapterType adapterType, T adapter) { | ||
32 | adapterTypes.add(adapterType); | ||
33 | adapters.add(adapter); | ||
34 | } | ||
35 | |||
36 | public <U extends T> Optional<U> tryGet(AnyModelAdapterType adapterType, Class<? extends U> adapterClass) { | ||
37 | int size = size(); | ||
38 | for (int i = 0; i < size; i++) { | ||
39 | if (getType(i).supports(adapterType)) { | ||
40 | return Optional.of(adapterClass.cast(get(i))); | ||
41 | } | ||
42 | } | ||
43 | return Optional.empty(); | ||
44 | } | ||
45 | |||
46 | public <U extends T> U get(AnyModelAdapterType adapterType, Class<U> adapterClass) { | ||
47 | return tryGet(adapterType, adapterClass).orElseThrow(() -> new IllegalArgumentException( | ||
48 | "No %s was configured".formatted(adapterType))); | ||
49 | } | ||
50 | |||
51 | public AnyModelAdapterType getType(int i) { | ||
52 | return adapterTypes.get(i); | ||
53 | } | ||
54 | |||
55 | public T get(int i) { | ||
56 | return adapters.get(i); | ||
57 | } | ||
58 | |||
59 | public Collection<AnyModelAdapterType> getAdapterTypes() { | ||
60 | return Collections.unmodifiableCollection(adapterTypes); | ||
61 | } | ||
62 | |||
63 | public Iterable<Entry<T>> withAdapterTypes() { | ||
64 | return () -> new Iterator<>() { | ||
65 | private int i = 0; | ||
66 | |||
67 | @Override | ||
68 | public boolean hasNext() { | ||
69 | return i < size(); | ||
70 | } | ||
71 | |||
72 | @Override | ||
73 | public Entry<T> next() { | ||
74 | if (i >= size()) { | ||
75 | throw new NoSuchElementException(); | ||
76 | } | ||
77 | var entry = new Entry<>(getType(i), get(i)); | ||
78 | i++; | ||
79 | return entry; | ||
80 | } | ||
81 | }; | ||
82 | } | ||
83 | |||
84 | @NotNull | ||
85 | @Override | ||
86 | public Iterator<T> iterator() { | ||
87 | return adapters.iterator(); | ||
88 | } | ||
89 | |||
90 | @Override | ||
91 | public void forEach(Consumer<? super T> action) { | ||
92 | adapters.forEach(action); | ||
93 | } | ||
94 | |||
95 | @Override | ||
96 | public Spliterator<T> spliterator() { | ||
97 | return adapters.spliterator(); | ||
98 | } | ||
99 | |||
100 | public record Entry<T>(AnyModelAdapterType adapterType, T adapter) { | ||
101 | } | ||
102 | } | ||
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 f161a60b..00000000 --- a/subprojects/store/src/main/java/tools/refinery/store/adapter/AnyModelAdapterType.java +++ /dev/null | |||
@@ -1,24 +0,0 @@ | |||
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 | |||
10 | public sealed interface AnyModelAdapterType permits ModelAdapterType { | ||
11 | Class<? extends ModelAdapter> getModelAdapterClass(); | ||
12 | |||
13 | Class<? extends ModelStoreAdapter> getModelStoreAdapterClass(); | ||
14 | |||
15 | Class<? extends ModelAdapterBuilder> getModelAdapterBuilderClass(); | ||
16 | |||
17 | Collection<AnyModelAdapterType> getSupportedAdapterTypes(); | ||
18 | |||
19 | default boolean supports(AnyModelAdapterType targetAdapter) { | ||
20 | return getSupportedAdapterTypes().contains(targetAdapter); | ||
21 | } | ||
22 | |||
23 | String getName(); | ||
24 | } | ||
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 709cbb3e..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 | |||
@@ -9,14 +9,9 @@ import tools.refinery.store.model.ModelStore; | |||
9 | import tools.refinery.store.model.ModelStoreBuilder; | 9 | import tools.refinery.store.model.ModelStoreBuilder; |
10 | 10 | ||
11 | public interface ModelAdapterBuilder { | 11 | public interface ModelAdapterBuilder { |
12 | ModelStoreAdapter createStoreAdapter(ModelStore store); | 12 | boolean isConfigured(); |
13 | 13 | ||
14 | <T extends ModelAdapterBuilder> T with(ModelAdapterBuilderFactory<?, ?, T> adapterBuilderFactory); | 14 | void configure(ModelStoreBuilder storeBuilder); |
15 | 15 | ||
16 | ModelStoreBuilder getStoreBuilder(); | 16 | ModelStoreAdapter build(ModelStore store); |
17 | |||
18 | default void configure() { | ||
19 | } | ||
20 | |||
21 | ModelStore build(); | ||
22 | } | 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 1d549d5b..00000000 --- a/subprojects/store/src/main/java/tools/refinery/store/adapter/ModelAdapterBuilderFactory.java +++ /dev/null | |||
@@ -1,19 +0,0 @@ | |||
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 tools.refinery.store.model.ModelStoreBuilder; | ||
9 | |||
10 | public abstract class ModelAdapterBuilderFactory<T1 extends ModelAdapter, T2 extends ModelStoreAdapter, | ||
11 | T3 extends ModelAdapterBuilder> extends ModelAdapterType<T1, T2, T3> { | ||
12 | |||
13 | protected ModelAdapterBuilderFactory(Class<T1> modelAdapterClass, Class<T2> modelStoreAdapterClass, | ||
14 | Class<T3> modelAdapterBuilderClass) { | ||
15 | super(modelAdapterClass, modelStoreAdapterClass, modelAdapterBuilderClass); | ||
16 | } | ||
17 | |||
18 | public abstract T3 createBuilder(ModelStoreBuilder storeBuilder); | ||
19 | } | ||
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 6255fe52..00000000 --- a/subprojects/store/src/main/java/tools/refinery/store/adapter/ModelAdapterType.java +++ /dev/null | |||
@@ -1,84 +0,0 @@ | |||
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 tools.refinery.store.model.Model; | ||
9 | import tools.refinery.store.model.ModelStore; | ||
10 | |||
11 | import java.lang.reflect.Method; | ||
12 | import java.util.Collection; | ||
13 | import java.util.Collections; | ||
14 | import java.util.HashSet; | ||
15 | import java.util.Set; | ||
16 | |||
17 | public abstract non-sealed class ModelAdapterType<T1 extends ModelAdapter, T2 extends ModelStoreAdapter, | ||
18 | T3 extends ModelAdapterBuilder> implements AnyModelAdapterType { | ||
19 | private final Class<? extends T1> modelAdapterClass; | ||
20 | private final Class<? extends T2> modelStoreAdapterClass; | ||
21 | private final Class<? extends T3> modelAdapterBuilderClass; | ||
22 | private final Set<AnyModelAdapterType> supportedAdapters = new HashSet<>(); | ||
23 | |||
24 | protected ModelAdapterType(Class<T1> modelAdapterClass, Class<T2> modelStoreAdapterClass, | ||
25 | Class<T3> modelAdapterBuilderClass) { | ||
26 | checkReturnType(modelAdapterClass, modelStoreAdapterClass, "createModelAdapter", Model.class); | ||
27 | checkReturnType(modelStoreAdapterClass, modelAdapterBuilderClass, "createStoreAdapter", ModelStore.class); | ||
28 | this.modelAdapterClass = modelAdapterClass; | ||
29 | this.modelStoreAdapterClass = modelStoreAdapterClass; | ||
30 | this.modelAdapterBuilderClass = modelAdapterBuilderClass; | ||
31 | supportedAdapters.add(this); | ||
32 | } | ||
33 | |||
34 | private void checkReturnType(Class<?> expectedReturnType, Class<?> ownerClass, String methodName, | ||
35 | Class<?>... argumentTypes) { | ||
36 | Method method; | ||
37 | try { | ||
38 | method = ownerClass.getMethod(methodName, argumentTypes); | ||
39 | } catch (NoSuchMethodException e) { | ||
40 | throw new IllegalStateException("Invalid %s: %s#%s method is required" | ||
41 | .formatted(this, ownerClass.getName(), methodName), e); | ||
42 | } | ||
43 | var returnType = method.getReturnType(); | ||
44 | if (!expectedReturnType.isAssignableFrom(returnType)) { | ||
45 | throw new IllegalStateException("Invalid %s: %s is not assignable from the return type %s of %s#%s" | ||
46 | .formatted(this, expectedReturnType.getName(), returnType.getCanonicalName(), | ||
47 | ownerClass.getName(), methodName)); | ||
48 | } | ||
49 | } | ||
50 | |||
51 | protected void extendsAdapter(ModelAdapterType<? super T1, ? super T2, ? super T3> superAdapter) { | ||
52 | supportedAdapters.addAll(superAdapter.supportedAdapters); | ||
53 | } | ||
54 | |||
55 | @Override | ||
56 | public final Class<? extends T1> getModelAdapterClass() { | ||
57 | return modelAdapterClass; | ||
58 | } | ||
59 | |||
60 | @Override | ||
61 | public final Class<? extends T2> getModelStoreAdapterClass() { | ||
62 | return modelStoreAdapterClass; | ||
63 | } | ||
64 | |||
65 | @Override | ||
66 | public final Class<? extends T3> getModelAdapterBuilderClass() { | ||
67 | return modelAdapterBuilderClass; | ||
68 | } | ||
69 | |||
70 | @Override | ||
71 | public Collection<AnyModelAdapterType> getSupportedAdapterTypes() { | ||
72 | return Collections.unmodifiableCollection(supportedAdapters); | ||
73 | } | ||
74 | |||
75 | @Override | ||
76 | public String getName() { | ||
77 | return "%s.ADAPTER".formatted(this.getClass().getName()); | ||
78 | } | ||
79 | |||
80 | @Override | ||
81 | public String toString() { | ||
82 | return getName(); | ||
83 | } | ||
84 | } | ||
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 f4131756..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 | |||
@@ -6,7 +6,6 @@ | |||
6 | package tools.refinery.store.model; | 6 | package tools.refinery.store.model; |
7 | 7 | ||
8 | import tools.refinery.store.adapter.ModelAdapter; | 8 | import tools.refinery.store.adapter.ModelAdapter; |
9 | import tools.refinery.store.adapter.ModelAdapterType; | ||
10 | import tools.refinery.store.map.Versioned; | 9 | import tools.refinery.store.map.Versioned; |
11 | import tools.refinery.store.representation.AnySymbol; | 10 | import tools.refinery.store.representation.AnySymbol; |
12 | import tools.refinery.store.representation.Symbol; | 11 | import tools.refinery.store.representation.Symbol; |
@@ -30,9 +29,9 @@ public interface Model extends Versioned { | |||
30 | 29 | ||
31 | ModelDiffCursor getDiffCursor(long to); | 30 | ModelDiffCursor getDiffCursor(long to); |
32 | 31 | ||
33 | <T extends ModelAdapter> Optional<T> tryGetAdapter(ModelAdapterType<? extends T, ?, ?> adapterType); | 32 | <T extends ModelAdapter> Optional<T> tryGetAdapter(Class<? extends T> adapterType); |
34 | 33 | ||
35 | <T extends ModelAdapter> T getAdapter(ModelAdapterType<T, ?, ?> adapterType); | 34 | <T extends ModelAdapter> T getAdapter(Class<T> adapterType); |
36 | 35 | ||
37 | void addListener(ModelListener listener); | 36 | void addListener(ModelListener listener); |
38 | 37 | ||
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 a72399f7..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 | |||
@@ -5,7 +5,6 @@ | |||
5 | */ | 5 | */ |
6 | package tools.refinery.store.model; | 6 | package tools.refinery.store.model; |
7 | 7 | ||
8 | import tools.refinery.store.adapter.ModelAdapterType; | ||
9 | import tools.refinery.store.adapter.ModelStoreAdapter; | 8 | import tools.refinery.store.adapter.ModelStoreAdapter; |
10 | import tools.refinery.store.model.internal.ModelStoreBuilderImpl; | 9 | import tools.refinery.store.model.internal.ModelStoreBuilderImpl; |
11 | import tools.refinery.store.representation.AnySymbol; | 10 | import tools.refinery.store.representation.AnySymbol; |
@@ -25,9 +24,9 @@ public interface ModelStore { | |||
25 | 24 | ||
26 | ModelDiffCursor getDiffCursor(long from, long to); | 25 | ModelDiffCursor getDiffCursor(long from, long to); |
27 | 26 | ||
28 | <T extends ModelStoreAdapter> Optional<T> tryGetAdapter(ModelAdapterType<?, ? extends T, ?> adapterType); | 27 | <T extends ModelStoreAdapter> Optional<T> tryGetAdapter(Class<? extends T> adapterType); |
29 | 28 | ||
30 | <T extends ModelStoreAdapter> T getAdapter(ModelAdapterType<?, T, ?> adapterType); | 29 | <T extends ModelStoreAdapter> T getAdapter(Class<T> adapterType); |
31 | 30 | ||
32 | static ModelStoreBuilder builder() { | 31 | static ModelStoreBuilder builder() { |
33 | 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 d9354bdb..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 | |||
@@ -6,8 +6,6 @@ | |||
6 | package tools.refinery.store.model; | 6 | package tools.refinery.store.model; |
7 | 7 | ||
8 | import tools.refinery.store.adapter.ModelAdapterBuilder; | 8 | import tools.refinery.store.adapter.ModelAdapterBuilder; |
9 | import tools.refinery.store.adapter.ModelAdapterBuilderFactory; | ||
10 | import tools.refinery.store.adapter.ModelAdapterType; | ||
11 | import tools.refinery.store.representation.AnySymbol; | 9 | import tools.refinery.store.representation.AnySymbol; |
12 | import tools.refinery.store.representation.Symbol; | 10 | import tools.refinery.store.representation.Symbol; |
13 | 11 | ||
@@ -31,11 +29,11 @@ public interface ModelStoreBuilder { | |||
31 | 29 | ||
32 | <T> ModelStoreBuilder symbol(Symbol<T> symbol); | 30 | <T> ModelStoreBuilder symbol(Symbol<T> symbol); |
33 | 31 | ||
34 | <T extends ModelAdapterBuilder> T with(ModelAdapterBuilderFactory<?, ?, T> adapterBuilderFactory); | 32 | <T extends ModelAdapterBuilder> ModelStoreBuilder with(T adapterBuilder); |
35 | 33 | ||
36 | <T extends ModelAdapterBuilder> Optional<T> tryGetAdapter(ModelAdapterType<?, ?, ? extends T> adapterType); | 34 | <T extends ModelAdapterBuilder> Optional<T> tryGetAdapter(Class<? extends T> adapterType); |
37 | 35 | ||
38 | <T extends ModelAdapterBuilder> T getAdapter(ModelAdapterType<?, ?, T> adapterType); | 36 | <T extends ModelAdapterBuilder> T getAdapter(Class<T> adapterType); |
39 | 37 | ||
40 | ModelStore build(); | 38 | ModelStore build(); |
41 | } | 39 | } |
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 50a408da..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 | |||
@@ -5,10 +5,8 @@ | |||
5 | */ | 5 | */ |
6 | package tools.refinery.store.model.internal; | 6 | package tools.refinery.store.model.internal; |
7 | 7 | ||
8 | import tools.refinery.store.adapter.AdapterList; | 8 | import tools.refinery.store.adapter.AdapterUtils; |
9 | import tools.refinery.store.adapter.AnyModelAdapterType; | ||
10 | import tools.refinery.store.adapter.ModelAdapter; | 9 | import tools.refinery.store.adapter.ModelAdapter; |
11 | import tools.refinery.store.adapter.ModelAdapterType; | ||
12 | import tools.refinery.store.map.DiffCursor; | 10 | import tools.refinery.store.map.DiffCursor; |
13 | import tools.refinery.store.model.*; | 11 | import tools.refinery.store.model.*; |
14 | import tools.refinery.store.representation.AnySymbol; | 12 | import tools.refinery.store.representation.AnySymbol; |
@@ -21,7 +19,7 @@ public class ModelImpl implements Model { | |||
21 | private final ModelStore store; | 19 | private final ModelStore store; |
22 | private long state; | 20 | private long state; |
23 | private Map<? extends AnySymbol, ? extends VersionedInterpretation<?>> interpretations; | 21 | private Map<? extends AnySymbol, ? extends VersionedInterpretation<?>> interpretations; |
24 | private final AdapterList<ModelAdapter> adapters; | 22 | private final List<ModelAdapter> adapters; |
25 | private final List<ModelListener> listeners = new ArrayList<>(); | 23 | private final List<ModelListener> listeners = new ArrayList<>(); |
26 | private boolean uncommittedChanges; | 24 | private boolean uncommittedChanges; |
27 | private ModelAction pendingAction = ModelAction.NONE; | 25 | private ModelAction pendingAction = ModelAction.NONE; |
@@ -30,7 +28,7 @@ public class ModelImpl implements Model { | |||
30 | ModelImpl(ModelStore store, long state, int adapterCount) { | 28 | ModelImpl(ModelStore store, long state, int adapterCount) { |
31 | this.store = store; | 29 | this.store = store; |
32 | this.state = state; | 30 | this.state = state; |
33 | adapters = new AdapterList<>(adapterCount); | 31 | adapters = new ArrayList<>(adapterCount); |
34 | } | 32 | } |
35 | 33 | ||
36 | void setInterpretations(Map<? extends AnySymbol, ? extends VersionedInterpretation<?>> interpretations) { | 34 | void setInterpretations(Map<? extends AnySymbol, ? extends VersionedInterpretation<?>> interpretations) { |
@@ -167,17 +165,17 @@ public class ModelImpl implements Model { | |||
167 | } | 165 | } |
168 | 166 | ||
169 | @Override | 167 | @Override |
170 | public <T extends ModelAdapter> Optional<T> tryGetAdapter(ModelAdapterType<? extends T, ?, ?> adapterType) { | 168 | public <T extends ModelAdapter> Optional<T> tryGetAdapter(Class<? extends T> adapterType) { |
171 | return adapters.tryGet(adapterType, adapterType.getModelAdapterClass()); | 169 | return AdapterUtils.tryGetAdapter(adapters, adapterType); |
172 | } | 170 | } |
173 | 171 | ||
174 | @Override | 172 | @Override |
175 | public <T extends ModelAdapter> T getAdapter(ModelAdapterType<T, ?, ?> adapterType) { | 173 | public <T extends ModelAdapter> T getAdapter(Class<T> adapterType) { |
176 | return adapters.get(adapterType, adapterType.getModelAdapterClass()); | 174 | return AdapterUtils.getAdapter(adapters, adapterType); |
177 | } | 175 | } |
178 | 176 | ||
179 | void addAdapter(AnyModelAdapterType adapterType, ModelAdapter adapter) { | 177 | void addAdapter(ModelAdapter adapter) { |
180 | adapters.add(adapterType, adapter); | 178 | adapters.add(adapter); |
181 | } | 179 | } |
182 | 180 | ||
183 | @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 70bccb96..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 | |||
@@ -5,10 +5,8 @@ | |||
5 | */ | 5 | */ |
6 | package tools.refinery.store.model.internal; | 6 | package tools.refinery.store.model.internal; |
7 | 7 | ||
8 | import tools.refinery.store.adapter.AdapterList; | 8 | import tools.refinery.store.adapter.AdapterUtils; |
9 | import tools.refinery.store.adapter.ModelAdapterBuilder; | 9 | import tools.refinery.store.adapter.ModelAdapterBuilder; |
10 | import tools.refinery.store.adapter.ModelAdapterBuilderFactory; | ||
11 | import tools.refinery.store.adapter.ModelAdapterType; | ||
12 | import tools.refinery.store.map.VersionedMapStore; | 10 | import tools.refinery.store.map.VersionedMapStore; |
13 | import tools.refinery.store.map.VersionedMapStoreImpl; | 11 | import tools.refinery.store.map.VersionedMapStoreImpl; |
14 | import tools.refinery.store.model.ModelStore; | 12 | import tools.refinery.store.model.ModelStore; |
@@ -23,7 +21,7 @@ import java.util.*; | |||
23 | public class ModelStoreBuilderImpl implements ModelStoreBuilder { | 21 | public class ModelStoreBuilderImpl implements ModelStoreBuilder { |
24 | private final Set<AnySymbol> allSymbols = new HashSet<>(); | 22 | private final Set<AnySymbol> allSymbols = new HashSet<>(); |
25 | private final Map<SymbolEquivalenceClass<?>, List<AnySymbol>> equivalenceClasses = new HashMap<>(); | 23 | private final Map<SymbolEquivalenceClass<?>, List<AnySymbol>> equivalenceClasses = new HashMap<>(); |
26 | private final AdapterList<ModelAdapterBuilder> adapters = new AdapterList<>(); | 24 | private final List<ModelAdapterBuilder> adapters = new ArrayList<>(); |
27 | 25 | ||
28 | @Override | 26 | @Override |
29 | public <T> ModelStoreBuilder symbol(Symbol<T> symbol) { | 27 | public <T> ModelStoreBuilder symbol(Symbol<T> symbol) { |
@@ -38,46 +36,25 @@ public class ModelStoreBuilderImpl implements ModelStoreBuilder { | |||
38 | } | 36 | } |
39 | 37 | ||
40 | @Override | 38 | @Override |
41 | public <T extends ModelAdapterBuilder> T with(ModelAdapterBuilderFactory<?, ?, T> adapterBuilderFactory) { | 39 | public <T extends ModelAdapterBuilder> ModelStoreBuilder with(T adapterBuilder) { |
42 | return adapters.<T>tryGet(adapterBuilderFactory, adapterBuilderFactory.getModelAdapterBuilderClass()) | 40 | for (var existingAdapter : adapters) { |
43 | .orElseGet(() -> addAdapter(adapterBuilderFactory)); | 41 | if (existingAdapter.getClass().equals(adapterBuilder.getClass())) { |
44 | } | 42 | throw new IllegalArgumentException("%s adapter was already configured for store builder" |
45 | 43 | .formatted(adapterBuilder.getClass().getName())); | |
46 | private <T extends ModelAdapterBuilder> T addAdapter(ModelAdapterBuilderFactory<?, ?, T> adapterBuilderFactory) { | ||
47 | for (var configuredAdapterType : adapters.getAdapterTypes()) { | ||
48 | var intersection = new HashSet<>(adapterBuilderFactory.getSupportedAdapterTypes()); | ||
49 | intersection.retainAll(configuredAdapterType.getSupportedAdapterTypes()); | ||
50 | if (!intersection.isEmpty()) { | ||
51 | if (configuredAdapterType.supports(adapterBuilderFactory)) { | ||
52 | // Impossible to end up here from <code>#with</code>, because we should have returned | ||
53 | // the existing adapter there instead of adding a new one. | ||
54 | throw new IllegalArgumentException( | ||
55 | "Cannot add %s, because it is already provided by configured adapter %s" | ||
56 | .formatted(adapterBuilderFactory, configuredAdapterType)); | ||
57 | } else if (adapterBuilderFactory.supports(configuredAdapterType)) { | ||
58 | throw new IllegalArgumentException( | ||
59 | "Cannot add %s, because it provides already configured adapter %s" | ||
60 | .formatted(adapterBuilderFactory, configuredAdapterType)); | ||
61 | } else { | ||
62 | throw new IllegalArgumentException( | ||
63 | "Cannot add %s, because configured adapter %s already provides %s" | ||
64 | .formatted(adapterBuilderFactory, configuredAdapterType, intersection)); | ||
65 | } | ||
66 | } | 44 | } |
67 | } | 45 | } |
68 | var newAdapter = adapterBuilderFactory.createBuilder(this); | 46 | adapters.add(adapterBuilder); |
69 | adapters.add(adapterBuilderFactory, newAdapter); | 47 | return this; |
70 | return newAdapter; | ||
71 | } | 48 | } |
72 | 49 | ||
73 | @Override | 50 | @Override |
74 | public <T extends ModelAdapterBuilder> Optional<T> tryGetAdapter(ModelAdapterType<?, ?, ? extends T> adapterType) { | 51 | public <T extends ModelAdapterBuilder> Optional<T> tryGetAdapter(Class<? extends T> adapterType) { |
75 | return adapters.tryGet(adapterType, adapterType.getModelAdapterBuilderClass()); | 52 | return AdapterUtils.tryGetAdapter(adapters, adapterType); |
76 | } | 53 | } |
77 | 54 | ||
78 | @Override | 55 | @Override |
79 | public <T extends ModelAdapterBuilder> T getAdapter(ModelAdapterType<?, ?, T> adapterType) { | 56 | public <T extends ModelAdapterBuilder> T getAdapter(Class<T> adapterType) { |
80 | return adapters.get(adapterType, adapterType.getModelAdapterBuilderClass()); | 57 | return AdapterUtils.getAdapter(adapters, adapterType); |
81 | } | 58 | } |
82 | 59 | ||
83 | @Override | 60 | @Override |
@@ -86,13 +63,13 @@ public class ModelStoreBuilderImpl implements ModelStoreBuilder { | |||
86 | for (var entry : equivalenceClasses.entrySet()) { | 63 | for (var entry : equivalenceClasses.entrySet()) { |
87 | createStores(stores, entry.getKey(), entry.getValue()); | 64 | createStores(stores, entry.getKey(), entry.getValue()); |
88 | } | 65 | } |
89 | var modelStore = new ModelStoreImpl(stores, adapters.size()); | ||
90 | for (int i = adapters.size() - 1; i >= 0; i--) { | 66 | for (int i = adapters.size() - 1; i >= 0; i--) { |
91 | adapters.get(i).configure(); | 67 | adapters.get(i).configure(this); |
92 | } | 68 | } |
93 | for (var entry : adapters.withAdapterTypes()) { | 69 | var modelStore = new ModelStoreImpl(stores, adapters.size()); |
94 | var adapter = entry.adapter().createStoreAdapter(modelStore); | 70 | for (var adapterBuilder : adapters) { |
95 | modelStore.addAdapter(entry.adapterType(), adapter); | 71 | var storeAdapter = adapterBuilder.build(modelStore); |
72 | modelStore.addAdapter(storeAdapter); | ||
96 | } | 73 | } |
97 | return modelStore; | 74 | return modelStore; |
98 | } | 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 bfae7181..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 | |||
@@ -5,9 +5,7 @@ | |||
5 | */ | 5 | */ |
6 | package tools.refinery.store.model.internal; | 6 | package tools.refinery.store.model.internal; |
7 | 7 | ||
8 | import tools.refinery.store.adapter.AdapterList; | 8 | import tools.refinery.store.adapter.AdapterUtils; |
9 | import tools.refinery.store.adapter.AnyModelAdapterType; | ||
10 | import tools.refinery.store.adapter.ModelAdapterType; | ||
11 | import tools.refinery.store.adapter.ModelStoreAdapter; | 9 | import tools.refinery.store.adapter.ModelStoreAdapter; |
12 | import tools.refinery.store.map.DiffCursor; | 10 | import tools.refinery.store.map.DiffCursor; |
13 | import tools.refinery.store.map.VersionedMapStore; | 11 | import tools.refinery.store.map.VersionedMapStore; |
@@ -21,11 +19,11 @@ import java.util.*; | |||
21 | 19 | ||
22 | public class ModelStoreImpl implements ModelStore { | 20 | public class ModelStoreImpl implements ModelStore { |
23 | private final Map<? extends AnySymbol, ? extends VersionedMapStore<Tuple, ?>> stores; | 21 | private final Map<? extends AnySymbol, ? extends VersionedMapStore<Tuple, ?>> stores; |
24 | private final AdapterList<ModelStoreAdapter> adapters; | 22 | private final List<ModelStoreAdapter> adapters; |
25 | 23 | ||
26 | ModelStoreImpl(Map<? extends AnySymbol, ? extends VersionedMapStore<Tuple, ?>> stores, int adapterCount) { | 24 | ModelStoreImpl(Map<? extends AnySymbol, ? extends VersionedMapStore<Tuple, ?>> stores, int adapterCount) { |
27 | this.stores = stores; | 25 | this.stores = stores; |
28 | adapters = new AdapterList<>(adapterCount); | 26 | adapters = new ArrayList<>(adapterCount); |
29 | } | 27 | } |
30 | 28 | ||
31 | @Override | 29 | @Override |
@@ -64,9 +62,9 @@ public class ModelStoreImpl implements ModelStore { | |||
64 | } | 62 | } |
65 | 63 | ||
66 | private void adaptModel(ModelImpl model) { | 64 | private void adaptModel(ModelImpl model) { |
67 | for (var entry : adapters.withAdapterTypes()) { | 65 | for (var storeAdapter : adapters) { |
68 | var adapter = entry.adapter().createModelAdapter(model); | 66 | var adapter = storeAdapter.createModelAdapter(model); |
69 | model.addAdapter(entry.adapterType(), adapter); | 67 | model.addAdapter(adapter); |
70 | } | 68 | } |
71 | } | 69 | } |
72 | 70 | ||
@@ -91,16 +89,16 @@ public class ModelStoreImpl implements ModelStore { | |||
91 | } | 89 | } |
92 | 90 | ||
93 | @Override | 91 | @Override |
94 | public <T extends ModelStoreAdapter> Optional<T> tryGetAdapter(ModelAdapterType<?, ? extends T, ?> adapterType) { | 92 | public <T extends ModelStoreAdapter> Optional<T> tryGetAdapter(Class<? extends T> adapterType) { |
95 | return adapters.tryGet(adapterType, adapterType.getModelStoreAdapterClass()); | 93 | return AdapterUtils.tryGetAdapter(adapters, adapterType); |
96 | } | 94 | } |
97 | 95 | ||
98 | @Override | 96 | @Override |
99 | public <T extends ModelStoreAdapter> T getAdapter(ModelAdapterType<?, T, ?> adapterType) { | 97 | public <T extends ModelStoreAdapter> T getAdapter(Class<T> adapterType) { |
100 | return adapters.get(adapterType, adapterType.getModelStoreAdapterClass()); | 98 | return AdapterUtils.getAdapter(adapters, adapterType); |
101 | } | 99 | } |
102 | 100 | ||
103 | void addAdapter(AnyModelAdapterType adapterType, ModelStoreAdapter adapter) { | 101 | void addAdapter(ModelStoreAdapter adapter) { |
104 | adapters.add(adapterType, adapter); | 102 | adapters.add(adapter); |
105 | } | 103 | } |
106 | } | 104 | } |