1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
|
/*
* SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
*
* SPDX-License-Identifier: EPL-2.0
*/
package tools.refinery.store.model.internal;
import tools.refinery.store.adapter.AdapterUtils;
import tools.refinery.store.adapter.ModelAdapterBuilder;
import tools.refinery.store.map.VersionedMapStore;
import tools.refinery.store.map.VersionedMapStoreFactory;
import tools.refinery.store.map.VersionedMapStoreFactoryBuilder;
import tools.refinery.store.model.ModelStore;
import tools.refinery.store.model.ModelStoreBuilder;
import tools.refinery.store.model.ModelStoreConfiguration;
import tools.refinery.store.representation.AnySymbol;
import tools.refinery.store.representation.Symbol;
import tools.refinery.store.tuple.Tuple;
import java.util.*;
public class ModelStoreBuilderImpl implements ModelStoreBuilder {
private final LinkedHashSet<AnySymbol> allSymbols = new LinkedHashSet<>();
private final LinkedHashMap<SymbolEquivalenceClass<?>, List<AnySymbol>> equivalenceClasses = new LinkedHashMap<>();
private final List<ModelAdapterBuilder> adapters = new ArrayList<>();
@Override
public <T> ModelStoreBuilder symbol(Symbol<T> symbol) {
if (!allSymbols.add(symbol)) {
// No need to add symbol twice.
return this;
}
var equivalenceClass = new SymbolEquivalenceClass<>(symbol);
var symbolsInEquivalenceClass = equivalenceClasses.computeIfAbsent(equivalenceClass,
ignored -> new ArrayList<>());
symbolsInEquivalenceClass.add(symbol);
return this;
}
@Override
public ModelStoreBuilder with(ModelAdapterBuilder adapterBuilder) {
for (var existingAdapter : adapters) {
if (existingAdapter.getClass().equals(adapterBuilder.getClass())) {
throw new IllegalArgumentException("%s adapter was already configured for store builder"
.formatted(adapterBuilder.getClass().getName()));
}
}
adapters.add(adapterBuilder);
return this;
}
@Override
public ModelStoreBuilder with(ModelStoreConfiguration configuration) {
configuration.apply(this);
return this;
}
@Override
public <T extends ModelAdapterBuilder> Optional<T> tryGetAdapter(Class<? extends T> adapterType) {
return AdapterUtils.tryGetAdapter(adapters, adapterType);
}
@Override
public <T extends ModelAdapterBuilder> T getAdapter(Class<T> adapterType) {
return AdapterUtils.getAdapter(adapters, adapterType);
}
@Override
public ModelStore build() {
// First configure adapters and let them register any symbols we don't know about yet.
for (int i = adapters.size() - 1; i >= 0; i--) {
adapters.get(i).configure(this);
}
var stores = new LinkedHashMap<AnySymbol, VersionedMapStore<Tuple, ?>>(allSymbols.size());
for (var entry : equivalenceClasses.entrySet()) {
createStores(stores, entry.getKey(), entry.getValue());
}
var modelStore = new ModelStoreImpl(stores, adapters.size());
for (var adapterBuilder : adapters) {
var storeAdapter = adapterBuilder.build(modelStore);
modelStore.addAdapter(storeAdapter);
}
return modelStore;
}
private <T> void createStores(Map<AnySymbol, VersionedMapStore<Tuple, ?>> stores,
SymbolEquivalenceClass<T> equivalenceClass, List<AnySymbol> symbols) {
int size = symbols.size();
VersionedMapStoreFactory<Tuple,T> mapFactory = VersionedMapStore
.<Tuple,T>builder()
.strategy(VersionedMapStoreFactoryBuilder.StoreStrategy.DELTA)
.defaultValue(equivalenceClass.defaultValue())
.build();
var storeGroup = mapFactory.createGroup(size);
for (int i = 0; i < size; i++) {
stores.put(symbols.get(i), storeGroup.get(i));
}
}
}
|