aboutsummaryrefslogtreecommitdiffstats
path: root/subprojects/store-dse/src/main/java/tools/refinery/store/dse/propagation
diff options
context:
space:
mode:
Diffstat (limited to 'subprojects/store-dse/src/main/java/tools/refinery/store/dse/propagation')
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/propagation/BoundPropagator.java11
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/propagation/PropagationAdapter.java20
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/propagation/PropagationBuilder.java32
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/propagation/PropagationResult.java28
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/propagation/PropagationStoreAdapter.java14
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/propagation/Propagator.java17
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/propagation/impl/PropagationAdapterImpl.java75
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/propagation/impl/PropagationBuilderImpl.java53
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/propagation/impl/PropagationStoreAdapterImpl.java38
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/propagation/impl/rule/BoundPropagationRule.java40
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/propagation/impl/rule/BoundRuleBasedPropagator.java43
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/propagation/impl/rule/RuleBasedPropagator.java36
12 files changed, 407 insertions, 0 deletions
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/propagation/BoundPropagator.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/propagation/BoundPropagator.java
new file mode 100644
index 00000000..5ad61463
--- /dev/null
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/propagation/BoundPropagator.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 */
6package tools.refinery.store.dse.propagation;
7
8@FunctionalInterface
9public interface BoundPropagator {
10 PropagationResult propagateOne();
11}
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/propagation/PropagationAdapter.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/propagation/PropagationAdapter.java
new file mode 100644
index 00000000..3ea5a75f
--- /dev/null
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/propagation/PropagationAdapter.java
@@ -0,0 +1,20 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.dse.propagation;
7
8import tools.refinery.store.adapter.ModelAdapter;
9import tools.refinery.store.dse.propagation.impl.PropagationBuilderImpl;
10
11public interface PropagationAdapter extends ModelAdapter {
12 @Override
13 PropagationStoreAdapter getStoreAdapter();
14
15 PropagationResult propagate();
16
17 static PropagationBuilder builder() {
18 return new PropagationBuilderImpl();
19 }
20}
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/propagation/PropagationBuilder.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/propagation/PropagationBuilder.java
new file mode 100644
index 00000000..f8a89b30
--- /dev/null
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/propagation/PropagationBuilder.java
@@ -0,0 +1,32 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.dse.propagation;
7
8import tools.refinery.store.adapter.ModelAdapterBuilder;
9import tools.refinery.store.dse.transition.Rule;
10import tools.refinery.store.model.ModelStore;
11
12import java.util.Collection;
13import java.util.List;
14
15@SuppressWarnings("UnusedReturnValue")
16public interface PropagationBuilder extends ModelAdapterBuilder {
17 PropagationBuilder rule(Rule propagationRule);
18
19 default PropagationBuilder rules(Rule... propagationRules) {
20 return rules(List.of(propagationRules));
21 }
22
23 default PropagationBuilder rules(Collection<Rule> propagationRules) {
24 propagationRules.forEach(this::rule);
25 return this;
26 }
27
28 PropagationBuilder propagator(Propagator propagator);
29
30 @Override
31 PropagationStoreAdapter build(ModelStore store);
32}
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/propagation/PropagationResult.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/propagation/PropagationResult.java
new file mode 100644
index 00000000..ea56653a
--- /dev/null
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/propagation/PropagationResult.java
@@ -0,0 +1,28 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.dse.propagation;
7
8public enum PropagationResult {
9 UNCHANGED,
10 PROPAGATED,
11 REJECTED;
12
13 public PropagationResult andThen(PropagationResult next) {
14 return switch (this) {
15 case UNCHANGED -> next;
16 case PROPAGATED -> next == REJECTED ? REJECTED : PROPAGATED;
17 case REJECTED -> REJECTED;
18 };
19 }
20
21 public boolean isRejected() {
22 return this == REJECTED;
23 }
24
25 public boolean isChanged() {
26 return this == PROPAGATED;
27 }
28}
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/propagation/PropagationStoreAdapter.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/propagation/PropagationStoreAdapter.java
new file mode 100644
index 00000000..82cba909
--- /dev/null
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/propagation/PropagationStoreAdapter.java
@@ -0,0 +1,14 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.dse.propagation;
7
8import tools.refinery.store.adapter.ModelStoreAdapter;
9import tools.refinery.store.model.Model;
10
11public interface PropagationStoreAdapter extends ModelStoreAdapter {
12 @Override
13 PropagationAdapter createModelAdapter(Model model);
14}
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/propagation/Propagator.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/propagation/Propagator.java
new file mode 100644
index 00000000..c6b4e1c9
--- /dev/null
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/propagation/Propagator.java
@@ -0,0 +1,17 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.dse.propagation;
7
8import tools.refinery.store.model.Model;
9import tools.refinery.store.model.ModelStoreBuilder;
10
11@FunctionalInterface
12public interface Propagator {
13 default void configure(ModelStoreBuilder storeBuilder) {
14 }
15
16 BoundPropagator bindToModel(Model model);
17}
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/propagation/impl/PropagationAdapterImpl.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/propagation/impl/PropagationAdapterImpl.java
new file mode 100644
index 00000000..fdd19217
--- /dev/null
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/propagation/impl/PropagationAdapterImpl.java
@@ -0,0 +1,75 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.dse.propagation.impl;
7
8import tools.refinery.store.dse.propagation.BoundPropagator;
9import tools.refinery.store.dse.propagation.PropagationAdapter;
10import tools.refinery.store.dse.propagation.PropagationResult;
11import tools.refinery.store.dse.propagation.PropagationStoreAdapter;
12import tools.refinery.store.model.Model;
13
14class PropagationAdapterImpl implements PropagationAdapter {
15 private final Model model;
16 private final PropagationStoreAdapterImpl storeAdapter;
17 private final BoundPropagator[] boundPropagators;
18
19 public PropagationAdapterImpl(Model model, PropagationStoreAdapterImpl storeAdapter) {
20 this.model = model;
21 this.storeAdapter = storeAdapter;
22 var propagators = storeAdapter.getPropagators();
23 boundPropagators = new BoundPropagator[propagators.size()];
24 for (int i = 0; i < boundPropagators.length; i++) {
25 boundPropagators[i] = propagators.get(i).bindToModel(model);
26 }
27 }
28
29 @Override
30 public PropagationResult propagate() {
31 PropagationResult result = PropagationResult.UNCHANGED;
32 PropagationResult lastResult;
33 do {
34 model.checkCancelled();
35 lastResult = propagateOne();
36 result = result.andThen(lastResult);
37 } while (lastResult.isChanged());
38 return result;
39 }
40
41 private PropagationResult propagateOne() {
42 PropagationResult result = PropagationResult.UNCHANGED;
43 for (int i = 0; i < boundPropagators.length; i++) {
44 model.checkCancelled();
45 var lastResult = propagateUntilFixedPoint(i);
46 result = result.andThen(lastResult);
47 if (result.isRejected()) {
48 break;
49 }
50 }
51 return result;
52 }
53
54 private PropagationResult propagateUntilFixedPoint(int propagatorIndex) {
55 var propagator = boundPropagators[propagatorIndex];
56 PropagationResult result = PropagationResult.UNCHANGED;
57 PropagationResult lastResult;
58 do {
59 model.checkCancelled();
60 lastResult = propagator.propagateOne();
61 result = result.andThen(lastResult);
62 } while (lastResult.isChanged());
63 return result;
64 }
65
66 @Override
67 public Model getModel() {
68 return model;
69 }
70
71 @Override
72 public PropagationStoreAdapter getStoreAdapter() {
73 return storeAdapter;
74 }
75}
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/propagation/impl/PropagationBuilderImpl.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/propagation/impl/PropagationBuilderImpl.java
new file mode 100644
index 00000000..c844a89f
--- /dev/null
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/propagation/impl/PropagationBuilderImpl.java
@@ -0,0 +1,53 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.dse.propagation.impl;
7
8import tools.refinery.store.adapter.AbstractModelAdapterBuilder;
9import tools.refinery.store.dse.propagation.PropagationBuilder;
10import tools.refinery.store.dse.propagation.PropagationStoreAdapter;
11import tools.refinery.store.dse.propagation.Propagator;
12import tools.refinery.store.dse.propagation.impl.rule.RuleBasedPropagator;
13import tools.refinery.store.dse.transition.Rule;
14import tools.refinery.store.model.ModelStore;
15import tools.refinery.store.model.ModelStoreBuilder;
16
17import java.util.*;
18
19public class PropagationBuilderImpl extends AbstractModelAdapterBuilder<PropagationStoreAdapter>
20 implements PropagationBuilder {
21 private final Set<Rule> propagationRules = new LinkedHashSet<>();
22 private final Deque<Propagator> propagators = new ArrayDeque<>();
23
24 @Override
25 public PropagationBuilder rule(Rule propagationRule) {
26 checkNotConfigured();
27 propagationRules.add(propagationRule);
28 return this;
29 }
30
31 @Override
32 public PropagationBuilder propagator(Propagator propagator) {
33 checkNotConfigured();
34 propagators.addFirst(propagator);
35 return this;
36 }
37
38 @Override
39 protected void doConfigure(ModelStoreBuilder storeBuilder) {
40 super.doConfigure(storeBuilder);
41 if (!propagationRules.isEmpty()) {
42 propagators.addFirst(new RuleBasedPropagator(List.copyOf(propagationRules)));
43 }
44 for (var propagator : propagators) {
45 propagator.configure(storeBuilder);
46 }
47 }
48
49 @Override
50 protected PropagationStoreAdapter doBuild(ModelStore store) {
51 return new PropagationStoreAdapterImpl(store, List.copyOf(propagators));
52 }
53}
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/propagation/impl/PropagationStoreAdapterImpl.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/propagation/impl/PropagationStoreAdapterImpl.java
new file mode 100644
index 00000000..a223caed
--- /dev/null
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/propagation/impl/PropagationStoreAdapterImpl.java
@@ -0,0 +1,38 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.dse.propagation.impl;
7
8import tools.refinery.store.dse.propagation.PropagationAdapter;
9import tools.refinery.store.dse.propagation.PropagationStoreAdapter;
10import tools.refinery.store.dse.propagation.Propagator;
11import tools.refinery.store.model.Model;
12import tools.refinery.store.model.ModelStore;
13
14import java.util.List;
15
16class PropagationStoreAdapterImpl implements PropagationStoreAdapter {
17 private final ModelStore store;
18 private final List<Propagator> propagators;
19
20 PropagationStoreAdapterImpl(ModelStore store, List<Propagator> propagators) {
21 this.store = store;
22 this.propagators = propagators;
23 }
24
25 @Override
26 public ModelStore getStore() {
27 return store;
28 }
29
30 @Override
31 public PropagationAdapter createModelAdapter(Model model) {
32 return new PropagationAdapterImpl(model, this);
33 }
34
35 List<Propagator> getPropagators() {
36 return propagators;
37 }
38}
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/propagation/impl/rule/BoundPropagationRule.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/propagation/impl/rule/BoundPropagationRule.java
new file mode 100644
index 00000000..a70292ad
--- /dev/null
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/propagation/impl/rule/BoundPropagationRule.java
@@ -0,0 +1,40 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.dse.propagation.impl.rule;
7
8import tools.refinery.store.dse.propagation.PropagationResult;
9import tools.refinery.store.dse.transition.Rule;
10import tools.refinery.store.dse.transition.actions.BoundAction;
11import tools.refinery.store.model.Model;
12import tools.refinery.store.query.ModelQueryAdapter;
13import tools.refinery.store.query.resultset.ResultSet;
14
15class BoundPropagationRule {
16 private final Model model;
17 private final ResultSet<Boolean> resultSet;
18 private final BoundAction action;
19
20 public BoundPropagationRule(Model model, Rule rule) {
21 this.model = model;
22 resultSet = model.getAdapter(ModelQueryAdapter.class).getResultSet(rule.getPrecondition());
23 action = rule.createAction(model);
24 }
25
26 public PropagationResult fireAll() {
27 if (resultSet.size() == 0) {
28 return PropagationResult.UNCHANGED;
29 }
30 var cursor = resultSet.getAll();
31 while (cursor.move()) {
32 model.checkCancelled();
33 var result = action.fire(cursor.getKey());
34 if (!result) {
35 return PropagationResult.REJECTED;
36 }
37 }
38 return PropagationResult.PROPAGATED;
39 }
40}
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/propagation/impl/rule/BoundRuleBasedPropagator.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/propagation/impl/rule/BoundRuleBasedPropagator.java
new file mode 100644
index 00000000..bd03f923
--- /dev/null
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/propagation/impl/rule/BoundRuleBasedPropagator.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 */
6package tools.refinery.store.dse.propagation.impl.rule;
7
8import tools.refinery.store.dse.propagation.BoundPropagator;
9import tools.refinery.store.dse.propagation.PropagationResult;
10import tools.refinery.store.dse.transition.Rule;
11import tools.refinery.store.model.Model;
12import tools.refinery.store.query.ModelQueryAdapter;
13
14import java.util.List;
15
16public class BoundRuleBasedPropagator implements BoundPropagator {
17 private final ModelQueryAdapter queryEngine;
18 private final BoundPropagationRule[] boundRules;
19
20 public BoundRuleBasedPropagator(Model model, List<Rule> propagationRules) {
21 queryEngine = model.getAdapter(ModelQueryAdapter.class);
22 boundRules = new BoundPropagationRule[propagationRules.size()];
23 for (int i = 0; i < boundRules.length; i++) {
24 boundRules[i] = new BoundPropagationRule(model, propagationRules.get(i));
25 }
26 }
27
28 @Override
29 public PropagationResult propagateOne() {
30 queryEngine.flushChanges();
31 PropagationResult result = PropagationResult.UNCHANGED;
32 // Use a classic for loop to avoid allocating an iterator.
33 //noinspection ForLoopReplaceableByForEach
34 for (int i = 0; i < boundRules.length; i++) {
35 var lastResult = boundRules[i].fireAll();
36 result = result.andThen(lastResult);
37 if (result.isRejected()) {
38 break;
39 }
40 }
41 return result;
42 }
43}
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/propagation/impl/rule/RuleBasedPropagator.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/propagation/impl/rule/RuleBasedPropagator.java
new file mode 100644
index 00000000..709b2416
--- /dev/null
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/propagation/impl/rule/RuleBasedPropagator.java
@@ -0,0 +1,36 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.dse.propagation.impl.rule;
7
8import tools.refinery.store.dse.propagation.BoundPropagator;
9import tools.refinery.store.dse.propagation.Propagator;
10import tools.refinery.store.dse.transition.Rule;
11import tools.refinery.store.model.Model;
12import tools.refinery.store.model.ModelStoreBuilder;
13import tools.refinery.store.query.ModelQueryBuilder;
14
15import java.util.List;
16
17public class RuleBasedPropagator implements Propagator {
18 private final List<Rule> propagationRules;
19
20 public RuleBasedPropagator(List<Rule> propagationRules) {
21 this.propagationRules = propagationRules;
22 }
23
24 @Override
25 public void configure(ModelStoreBuilder storeBuilder) {
26 var queryBuilder = storeBuilder.getAdapter(ModelQueryBuilder.class);
27 for (var propagationRule : propagationRules) {
28 queryBuilder.query(propagationRule.getPrecondition());
29 }
30 }
31
32 @Override
33 public BoundPropagator bindToModel(Model model) {
34 return new BoundRuleBasedPropagator(model, propagationRules);
35 }
36}