diff options
Diffstat (limited to 'subprojects/store-dse/src/main/java/tools/refinery/store/dse/modification/internal/ModificationAdapterImpl.java')
-rw-r--r-- | subprojects/store-dse/src/main/java/tools/refinery/store/dse/modification/internal/ModificationAdapterImpl.java | 107 |
1 files changed, 107 insertions, 0 deletions
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/modification/internal/ModificationAdapterImpl.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/modification/internal/ModificationAdapterImpl.java new file mode 100644 index 00000000..4e77c462 --- /dev/null +++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/modification/internal/ModificationAdapterImpl.java | |||
@@ -0,0 +1,107 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.dse.modification.internal; | ||
7 | |||
8 | import tools.refinery.store.adapter.ModelStoreAdapter; | ||
9 | import tools.refinery.store.dse.modification.DanglingEdges; | ||
10 | import tools.refinery.store.dse.modification.ModificationAdapter; | ||
11 | import tools.refinery.store.model.Interpretation; | ||
12 | import tools.refinery.store.model.Model; | ||
13 | import tools.refinery.store.representation.Symbol; | ||
14 | import tools.refinery.store.tuple.Tuple; | ||
15 | import tools.refinery.store.tuple.Tuple1; | ||
16 | |||
17 | import java.util.HashSet; | ||
18 | |||
19 | public class ModificationAdapterImpl implements ModificationAdapter { | ||
20 | static final Symbol<Integer> NEXT_ID = Symbol.of("NEXT_ID", 0, Integer.class, 0); | ||
21 | |||
22 | final ModelStoreAdapter storeAdapter; | ||
23 | final Model model; | ||
24 | Interpretation<Integer> nodeCountInterpretation; | ||
25 | |||
26 | ModificationAdapterImpl(ModelStoreAdapter storeAdapter, Model model) { | ||
27 | this.storeAdapter = storeAdapter; | ||
28 | this.model = model; | ||
29 | this.nodeCountInterpretation = model.getInterpretation(NEXT_ID); | ||
30 | } | ||
31 | |||
32 | @Override | ||
33 | public Model getModel() { | ||
34 | return model; | ||
35 | } | ||
36 | |||
37 | @Override | ||
38 | public ModelStoreAdapter getStoreAdapter() { | ||
39 | return storeAdapter; | ||
40 | } | ||
41 | |||
42 | @Override | ||
43 | public int getModelSize() { | ||
44 | return nodeCountInterpretation.get(Tuple.of()); | ||
45 | } | ||
46 | |||
47 | @Override | ||
48 | public Tuple1 createObject() { | ||
49 | var newNodeId = getModelSize(); | ||
50 | nodeCountInterpretation.put(Tuple.of(), newNodeId + 1); | ||
51 | return Tuple.of(newNodeId); | ||
52 | } | ||
53 | |||
54 | @Override | ||
55 | public boolean deleteObject(Tuple tuple, DanglingEdges danglingEdges) { | ||
56 | if (tuple.getSize() != 1) { | ||
57 | throw new IllegalArgumentException("Tuple size must be 1"); | ||
58 | } | ||
59 | int objectId = tuple.get(0); | ||
60 | if (danglingEdges == DanglingEdges.DELETE) { | ||
61 | deleteDanglingEdges(objectId); | ||
62 | } else if (danglingEdges == DanglingEdges.FAIL && hasDanglingEdges(objectId)) { | ||
63 | return false; | ||
64 | |||
65 | } | ||
66 | int modelSize = getModelSize(); | ||
67 | if (objectId == modelSize - 1) { | ||
68 | nodeCountInterpretation.put(Tuple.of(), modelSize - 1); | ||
69 | } | ||
70 | return true; | ||
71 | } | ||
72 | |||
73 | private void deleteDanglingEdges(int objectId) { | ||
74 | for (var symbol : model.getStore().getSymbols()) { | ||
75 | deleteDanglingEdges(objectId, (Symbol<?>) symbol); | ||
76 | } | ||
77 | } | ||
78 | |||
79 | private <T> void deleteDanglingEdges(int objectId, Symbol<T> symbol) { | ||
80 | var interpretation = model.getInterpretation(symbol); | ||
81 | var toDelete = new HashSet<Tuple>(); | ||
82 | int arity = symbol.arity(); | ||
83 | for (int i = 0; i < arity; i++) { | ||
84 | var cursor = interpretation.getAdjacent(i, objectId); | ||
85 | while (cursor.move()) { | ||
86 | toDelete.add(cursor.getKey()); | ||
87 | } | ||
88 | } | ||
89 | var defaultValue = symbol.defaultValue(); | ||
90 | for (var tuple : toDelete) { | ||
91 | interpretation.put(tuple, defaultValue); | ||
92 | } | ||
93 | } | ||
94 | |||
95 | private boolean hasDanglingEdges(int objectId) { | ||
96 | for (var symbol : model.getStore().getSymbols()) { | ||
97 | var interpretation = model.getInterpretation(symbol); | ||
98 | int arity = symbol.arity(); | ||
99 | for (int i = 0; i < arity; i++) { | ||
100 | if (interpretation.getAdjacentSize(i, objectId) > 0) { | ||
101 | return true; | ||
102 | } | ||
103 | } | ||
104 | } | ||
105 | return false; | ||
106 | } | ||
107 | } | ||