diff options
Diffstat (limited to 'subprojects/store-dse/src/main/java/tools/refinery/store/dse/modification')
10 files changed, 340 insertions, 0 deletions
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/modification/DanglingEdges.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/modification/DanglingEdges.java new file mode 100644 index 00000000..ac9d125b --- /dev/null +++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/modification/DanglingEdges.java | |||
@@ -0,0 +1,12 @@ | |||
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; | ||
7 | |||
8 | public enum DanglingEdges { | ||
9 | IGNORE, | ||
10 | DELETE, | ||
11 | FAIL | ||
12 | } | ||
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/modification/ModificationAdapter.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/modification/ModificationAdapter.java new file mode 100644 index 00000000..58b60499 --- /dev/null +++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/modification/ModificationAdapter.java | |||
@@ -0,0 +1,24 @@ | |||
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; | ||
7 | |||
8 | import tools.refinery.store.adapter.ModelAdapter; | ||
9 | import tools.refinery.store.dse.modification.internal.ModificationBuilderImpl; | ||
10 | import tools.refinery.store.tuple.Tuple; | ||
11 | import tools.refinery.store.tuple.Tuple1; | ||
12 | |||
13 | public interface ModificationAdapter extends ModelAdapter { | ||
14 | |||
15 | int getModelSize(); | ||
16 | |||
17 | Tuple1 createObject(); | ||
18 | |||
19 | boolean deleteObject(Tuple tuple, DanglingEdges danglingEdges); | ||
20 | |||
21 | static ModificationBuilder builder() { | ||
22 | return new ModificationBuilderImpl(); | ||
23 | } | ||
24 | } | ||
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/modification/ModificationBuilder.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/modification/ModificationBuilder.java new file mode 100644 index 00000000..48c22bdf --- /dev/null +++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/modification/ModificationBuilder.java | |||
@@ -0,0 +1,11 @@ | |||
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; | ||
7 | |||
8 | import tools.refinery.store.adapter.ModelAdapterBuilder; | ||
9 | |||
10 | public interface ModificationBuilder extends ModelAdapterBuilder { | ||
11 | } | ||
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/modification/ModificationStoreAdapter.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/modification/ModificationStoreAdapter.java new file mode 100644 index 00000000..144c4d05 --- /dev/null +++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/modification/ModificationStoreAdapter.java | |||
@@ -0,0 +1,11 @@ | |||
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; | ||
7 | |||
8 | import tools.refinery.store.adapter.ModelStoreAdapter; | ||
9 | |||
10 | public interface ModificationStoreAdapter extends ModelStoreAdapter { | ||
11 | } | ||
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/modification/actions/CreateActionLiteral.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/modification/actions/CreateActionLiteral.java new file mode 100644 index 00000000..5b86a5e1 --- /dev/null +++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/modification/actions/CreateActionLiteral.java | |||
@@ -0,0 +1,43 @@ | |||
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.actions; | ||
7 | |||
8 | import tools.refinery.store.dse.modification.ModificationAdapter; | ||
9 | import tools.refinery.store.dse.transition.actions.AbstractActionLiteral; | ||
10 | import tools.refinery.store.dse.transition.actions.BoundActionLiteral; | ||
11 | import tools.refinery.store.model.Model; | ||
12 | import tools.refinery.store.query.term.NodeVariable; | ||
13 | |||
14 | import java.util.List; | ||
15 | |||
16 | public class CreateActionLiteral extends AbstractActionLiteral { | ||
17 | private final NodeVariable variable; | ||
18 | |||
19 | public CreateActionLiteral(NodeVariable variable) { | ||
20 | |||
21 | this.variable = variable; | ||
22 | } | ||
23 | |||
24 | public NodeVariable getVariable() { | ||
25 | return variable; | ||
26 | } | ||
27 | |||
28 | @Override | ||
29 | public List<NodeVariable> getInputVariables() { | ||
30 | return List.of(); | ||
31 | } | ||
32 | |||
33 | @Override | ||
34 | public List<NodeVariable> getOutputVariables() { | ||
35 | return List.of(variable); | ||
36 | } | ||
37 | |||
38 | @Override | ||
39 | public BoundActionLiteral bindToModel(Model model) { | ||
40 | var adapter = model.getAdapter(ModificationAdapter.class); | ||
41 | return ignoredTuple -> adapter.createObject(); | ||
42 | } | ||
43 | } | ||
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/modification/actions/DeleteActionLiteral.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/modification/actions/DeleteActionLiteral.java new file mode 100644 index 00000000..18ad2b9d --- /dev/null +++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/modification/actions/DeleteActionLiteral.java | |||
@@ -0,0 +1,51 @@ | |||
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.actions; | ||
7 | |||
8 | import tools.refinery.store.dse.modification.DanglingEdges; | ||
9 | import tools.refinery.store.dse.modification.ModificationAdapter; | ||
10 | import tools.refinery.store.dse.transition.actions.AbstractActionLiteral; | ||
11 | import tools.refinery.store.dse.transition.actions.BoundActionLiteral; | ||
12 | import tools.refinery.store.model.Model; | ||
13 | import tools.refinery.store.query.term.NodeVariable; | ||
14 | import tools.refinery.store.tuple.Tuple; | ||
15 | |||
16 | import java.util.List; | ||
17 | |||
18 | public class DeleteActionLiteral extends AbstractActionLiteral { | ||
19 | private final NodeVariable variable; | ||
20 | private final DanglingEdges danglingEdges; | ||
21 | |||
22 | public DeleteActionLiteral(NodeVariable variable, DanglingEdges danglingEdges) { | ||
23 | |||
24 | this.variable = variable; | ||
25 | this.danglingEdges = danglingEdges; | ||
26 | } | ||
27 | |||
28 | public NodeVariable getVariable() { | ||
29 | return variable; | ||
30 | } | ||
31 | |||
32 | public DanglingEdges getDanglingEdges() { | ||
33 | return danglingEdges; | ||
34 | } | ||
35 | |||
36 | @Override | ||
37 | public List<NodeVariable> getInputVariables() { | ||
38 | return List.of(variable); | ||
39 | } | ||
40 | |||
41 | @Override | ||
42 | public List<NodeVariable> getOutputVariables() { | ||
43 | return List.of(); | ||
44 | } | ||
45 | |||
46 | @Override | ||
47 | public BoundActionLiteral bindToModel(Model model) { | ||
48 | var adapter = model.getAdapter(ModificationAdapter.class); | ||
49 | return tuple -> adapter.deleteObject(tuple, danglingEdges) ? Tuple.of() : null; | ||
50 | } | ||
51 | } | ||
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/modification/actions/ModificationActionLiterals.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/modification/actions/ModificationActionLiterals.java new file mode 100644 index 00000000..31f50ac7 --- /dev/null +++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/modification/actions/ModificationActionLiterals.java | |||
@@ -0,0 +1,23 @@ | |||
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.actions; | ||
7 | |||
8 | import tools.refinery.store.dse.modification.DanglingEdges; | ||
9 | import tools.refinery.store.query.term.NodeVariable; | ||
10 | |||
11 | public class ModificationActionLiterals { | ||
12 | private ModificationActionLiterals() { | ||
13 | throw new IllegalArgumentException("This is a static utility class and should not be instantiated directly"); | ||
14 | } | ||
15 | |||
16 | public static CreateActionLiteral create(NodeVariable variable) { | ||
17 | return new CreateActionLiteral(variable); | ||
18 | } | ||
19 | |||
20 | public static DeleteActionLiteral delete(NodeVariable variable, DanglingEdges danglingEdges) { | ||
21 | return new DeleteActionLiteral(variable, danglingEdges); | ||
22 | } | ||
23 | } | ||
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 | } | ||
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/modification/internal/ModificationBuilderImpl.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/modification/internal/ModificationBuilderImpl.java new file mode 100644 index 00000000..c4d38d22 --- /dev/null +++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/modification/internal/ModificationBuilderImpl.java | |||
@@ -0,0 +1,29 @@ | |||
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.AbstractModelAdapterBuilder; | ||
9 | import tools.refinery.store.dse.modification.ModificationBuilder; | ||
10 | import tools.refinery.store.dse.modification.ModificationStoreAdapter; | ||
11 | import tools.refinery.store.model.ModelStore; | ||
12 | import tools.refinery.store.model.ModelStoreBuilder; | ||
13 | import tools.refinery.store.statecoding.StateCoderBuilder; | ||
14 | |||
15 | public class ModificationBuilderImpl extends AbstractModelAdapterBuilder<ModificationStoreAdapter> implements ModificationBuilder { | ||
16 | |||
17 | @Override | ||
18 | protected void doConfigure(ModelStoreBuilder storeBuilder) { | ||
19 | storeBuilder.symbols(ModificationAdapterImpl.NEXT_ID); | ||
20 | storeBuilder.tryGetAdapter(StateCoderBuilder.class).ifPresent( | ||
21 | coderBuilder -> coderBuilder.exclude(ModificationAdapterImpl.NEXT_ID)); | ||
22 | super.doConfigure(storeBuilder); | ||
23 | } | ||
24 | |||
25 | @Override | ||
26 | protected ModificationStoreAdapter doBuild(ModelStore store) { | ||
27 | return new ModificationStoreAdapterImpl(store); | ||
28 | } | ||
29 | } | ||
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/modification/internal/ModificationStoreAdapterImpl.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/modification/internal/ModificationStoreAdapterImpl.java new file mode 100644 index 00000000..62e4227b --- /dev/null +++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/modification/internal/ModificationStoreAdapterImpl.java | |||
@@ -0,0 +1,29 @@ | |||
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.ModelAdapter; | ||
9 | import tools.refinery.store.dse.modification.ModificationStoreAdapter; | ||
10 | import tools.refinery.store.model.Model; | ||
11 | import tools.refinery.store.model.ModelStore; | ||
12 | |||
13 | public class ModificationStoreAdapterImpl implements ModificationStoreAdapter { | ||
14 | ModelStore store; | ||
15 | |||
16 | ModificationStoreAdapterImpl(ModelStore store) { | ||
17 | this.store = store; | ||
18 | } | ||
19 | |||
20 | @Override | ||
21 | public ModelStore getStore() { | ||
22 | return store; | ||
23 | } | ||
24 | |||
25 | @Override | ||
26 | public ModelAdapter createModelAdapter(Model model) { | ||
27 | return new ModificationAdapterImpl(this, model); | ||
28 | } | ||
29 | } | ||