diff options
11 files changed, 104 insertions, 37 deletions
diff --git a/subprojects/generator/src/main/java/tools/refinery/generator/ModelSemanticsFactory.java b/subprojects/generator/src/main/java/tools/refinery/generator/ModelSemanticsFactory.java index 77f05a9d..3c3488df 100644 --- a/subprojects/generator/src/main/java/tools/refinery/generator/ModelSemanticsFactory.java +++ b/subprojects/generator/src/main/java/tools/refinery/generator/ModelSemanticsFactory.java | |||
@@ -41,7 +41,8 @@ public final class ModelSemanticsFactory { | |||
41 | var storeBuilder = ModelStore.builder() | 41 | var storeBuilder = ModelStore.builder() |
42 | .cancellationToken(cancellationToken) | 42 | .cancellationToken(cancellationToken) |
43 | .with(QueryInterpreterAdapter.builder()) | 43 | .with(QueryInterpreterAdapter.builder()) |
44 | .with(PropagationAdapter.builder()) | 44 | .with(PropagationAdapter.builder() |
45 | .throwOnFatalRejection(false)) | ||
45 | .with(ReasoningAdapter.builder() | 46 | .with(ReasoningAdapter.builder() |
46 | .requiredInterpretations(Set.of(Concreteness.PARTIAL))); | 47 | .requiredInterpretations(Set.of(Concreteness.PARTIAL))); |
47 | initializer.configureStoreBuilder(storeBuilder); | 48 | initializer.configureStoreBuilder(storeBuilder); |
diff --git a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/ModelInitializer.java b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/ModelInitializer.java index c2243f08..8bfc8acd 100644 --- a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/ModelInitializer.java +++ b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/ModelInitializer.java | |||
@@ -967,6 +967,7 @@ public class ModelInitializer { | |||
967 | .orElseGet(() -> "::rule" + ruleCount); | 967 | .orElseGet(() -> "::rule" + ruleCount); |
968 | ruleCount++; | 968 | ruleCount++; |
969 | var rule = toRule(name, ruleDefinition); | 969 | var rule = toRule(name, ruleDefinition); |
970 | problemTrace.putRuleDefinition(ruleDefinition, rule); | ||
970 | switch (ruleDefinition.getKind()) { | 971 | switch (ruleDefinition.getKind()) { |
971 | case DECISION -> storeBuilder.tryGetAdapter(DesignSpaceExplorationBuilder.class) | 972 | case DECISION -> storeBuilder.tryGetAdapter(DesignSpaceExplorationBuilder.class) |
972 | .ifPresent(dseBuilder -> dseBuilder.transformation(rule)); | 973 | .ifPresent(dseBuilder -> dseBuilder.transformation(rule)); |
diff --git a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/ProblemTrace.java b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/ProblemTrace.java index b8d0b804..9122cf1f 100644 --- a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/ProblemTrace.java +++ b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/ProblemTrace.java | |||
@@ -10,6 +10,8 @@ import org.eclipse.xtext.naming.QualifiedName; | |||
10 | import tools.refinery.language.model.problem.Node; | 10 | import tools.refinery.language.model.problem.Node; |
11 | import tools.refinery.language.model.problem.Problem; | 11 | import tools.refinery.language.model.problem.Problem; |
12 | import tools.refinery.language.model.problem.Relation; | 12 | import tools.refinery.language.model.problem.Relation; |
13 | import tools.refinery.language.model.problem.RuleDefinition; | ||
14 | import tools.refinery.store.dse.transition.Rule; | ||
13 | import tools.refinery.store.reasoning.representation.AnyPartialSymbol; | 15 | import tools.refinery.store.reasoning.representation.AnyPartialSymbol; |
14 | import tools.refinery.store.reasoning.representation.PartialRelation; | 16 | import tools.refinery.store.reasoning.representation.PartialRelation; |
15 | import tools.refinery.store.reasoning.translator.TranslationException; | 17 | import tools.refinery.store.reasoning.translator.TranslationException; |
@@ -36,6 +38,8 @@ public interface ProblemTrace { | |||
36 | 38 | ||
37 | Relation getRelation(AnyPartialSymbol partialSymbol); | 39 | Relation getRelation(AnyPartialSymbol partialSymbol); |
38 | 40 | ||
41 | RuleDefinition getRuleDefinition(Rule rule); | ||
42 | |||
39 | RuntimeException wrapException(TranslationException translationException); | 43 | RuntimeException wrapException(TranslationException translationException); |
40 | 44 | ||
41 | PartialRelation getPartialRelation(Relation relation); | 45 | PartialRelation getPartialRelation(Relation relation); |
diff --git a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/ProblemTraceImpl.java b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/ProblemTraceImpl.java index 4b44339c..5584af10 100644 --- a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/ProblemTraceImpl.java +++ b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/ProblemTraceImpl.java | |||
@@ -13,10 +13,8 @@ import org.eclipse.xtext.naming.IQualifiedNameConverter; | |||
13 | import org.eclipse.xtext.naming.QualifiedName; | 13 | import org.eclipse.xtext.naming.QualifiedName; |
14 | import org.eclipse.xtext.scoping.IScope; | 14 | import org.eclipse.xtext.scoping.IScope; |
15 | import org.eclipse.xtext.scoping.IScopeProvider; | 15 | import org.eclipse.xtext.scoping.IScopeProvider; |
16 | import tools.refinery.language.model.problem.Node; | 16 | import tools.refinery.language.model.problem.*; |
17 | import tools.refinery.language.model.problem.Problem; | 17 | import tools.refinery.store.dse.transition.Rule; |
18 | import tools.refinery.language.model.problem.ProblemPackage; | ||
19 | import tools.refinery.language.model.problem.Relation; | ||
20 | import tools.refinery.store.reasoning.representation.AnyPartialSymbol; | 18 | import tools.refinery.store.reasoning.representation.AnyPartialSymbol; |
21 | import tools.refinery.store.reasoning.representation.PartialRelation; | 19 | import tools.refinery.store.reasoning.representation.PartialRelation; |
22 | import tools.refinery.store.reasoning.translator.TranslationException; | 20 | import tools.refinery.store.reasoning.translator.TranslationException; |
@@ -46,6 +44,7 @@ class ProblemTraceImpl implements ProblemTrace { | |||
46 | Collections.unmodifiableMap(mutableRelationTrace); | 44 | Collections.unmodifiableMap(mutableRelationTrace); |
47 | private final Map<AnyPartialSymbol, Relation> mutableInverseTrace = new HashMap<>(); | 45 | private final Map<AnyPartialSymbol, Relation> mutableInverseTrace = new HashMap<>(); |
48 | private final Map<AnyPartialSymbol, Relation> inverseTrace = Collections.unmodifiableMap(mutableInverseTrace); | 46 | private final Map<AnyPartialSymbol, Relation> inverseTrace = Collections.unmodifiableMap(mutableInverseTrace); |
47 | private final Map<Rule, RuleDefinition> mutableInverseRuleDefinitionTrace = new LinkedHashMap<>(); | ||
49 | 48 | ||
50 | @Override | 49 | @Override |
51 | public Problem getProblem() { | 50 | public Problem getProblem() { |
@@ -129,6 +128,23 @@ class ProblemTraceImpl implements ProblemTrace { | |||
129 | return relation; | 128 | return relation; |
130 | } | 129 | } |
131 | 130 | ||
131 | void putRuleDefinition(RuleDefinition ruleDefinition, Rule rule) { | ||
132 | var oldRuleDefinition = mutableInverseRuleDefinitionTrace.put(rule, ruleDefinition); | ||
133 | if (oldRuleDefinition != null) { | ||
134 | throw new TracedException(oldRuleDefinition, "Rule definition %s was already mapped to rule" | ||
135 | .formatted(rule.getName())); | ||
136 | } | ||
137 | } | ||
138 | |||
139 | @Override | ||
140 | public RuleDefinition getRuleDefinition(Rule rule) { | ||
141 | var ruleDefinition = mutableInverseRuleDefinitionTrace.get(rule); | ||
142 | if (ruleDefinition == null) { | ||
143 | throw new IllegalArgumentException("No definition for rule: " + rule.getName()); | ||
144 | } | ||
145 | return ruleDefinition; | ||
146 | } | ||
147 | |||
132 | @Override | 148 | @Override |
133 | public RuntimeException wrapException(TranslationException translationException) { | 149 | public RuntimeException wrapException(TranslationException translationException) { |
134 | var partialSymbol = translationException.getPartialSymbol(); | 150 | var partialSymbol = translationException.getPartialSymbol(); |
diff --git a/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/SemanticsWorker.java b/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/SemanticsWorker.java index 4ec11bb9..c6485309 100644 --- a/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/SemanticsWorker.java +++ b/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/SemanticsWorker.java | |||
@@ -8,6 +8,7 @@ package tools.refinery.language.web.semantics; | |||
8 | import com.google.inject.Inject; | 8 | import com.google.inject.Inject; |
9 | import org.eclipse.emf.common.util.Diagnostic; | 9 | import org.eclipse.emf.common.util.Diagnostic; |
10 | import org.eclipse.emf.ecore.EObject; | 10 | import org.eclipse.emf.ecore.EObject; |
11 | import org.eclipse.emf.ecore.EStructuralFeature; | ||
11 | import org.eclipse.xtext.service.OperationCanceledManager; | 12 | import org.eclipse.xtext.service.OperationCanceledManager; |
12 | import org.eclipse.xtext.util.CancelIndicator; | 13 | import org.eclipse.xtext.util.CancelIndicator; |
13 | import org.eclipse.xtext.validation.CheckType; | 14 | import org.eclipse.xtext.validation.CheckType; |
@@ -18,11 +19,14 @@ import org.eclipse.xtext.web.server.validation.ValidationResult; | |||
18 | import tools.refinery.generator.ModelSemantics; | 19 | import tools.refinery.generator.ModelSemantics; |
19 | import tools.refinery.generator.ModelSemanticsFactory; | 20 | import tools.refinery.generator.ModelSemanticsFactory; |
20 | import tools.refinery.language.model.problem.Problem; | 21 | import tools.refinery.language.model.problem.Problem; |
22 | import tools.refinery.language.model.problem.ProblemPackage; | ||
21 | import tools.refinery.language.model.problem.ScopeDeclaration; | 23 | import tools.refinery.language.model.problem.ScopeDeclaration; |
24 | import tools.refinery.language.semantics.ProblemTrace; | ||
22 | import tools.refinery.language.semantics.TracedException; | 25 | import tools.refinery.language.semantics.TracedException; |
23 | import tools.refinery.language.web.semantics.metadata.MetadataCreator; | 26 | import tools.refinery.language.web.semantics.metadata.MetadataCreator; |
24 | import tools.refinery.store.dse.propagation.PropagationRejectedResult; | 27 | import tools.refinery.store.dse.propagation.PropagationRejectedResult; |
25 | import tools.refinery.store.dse.propagation.PropagationResult; | 28 | import tools.refinery.store.dse.propagation.PropagationResult; |
29 | import tools.refinery.store.dse.transition.Rule; | ||
26 | import tools.refinery.store.reasoning.literal.Concreteness; | 30 | import tools.refinery.store.reasoning.literal.Concreteness; |
27 | import tools.refinery.store.reasoning.scope.ScopePropagator; | 31 | import tools.refinery.store.reasoning.scope.ScopePropagator; |
28 | import tools.refinery.store.reasoning.translator.TranslationException; | 32 | import tools.refinery.store.reasoning.translator.TranslationException; |
@@ -79,18 +83,31 @@ class SemanticsWorker implements Callable<SemanticsResult> { | |||
79 | } | 83 | } |
80 | cancellationToken.checkCancelled(); | 84 | cancellationToken.checkCancelled(); |
81 | var modelResult = createSemanticsModelResult(semantics); | 85 | var modelResult = createSemanticsModelResult(semantics); |
82 | return createSemanticsResult(modelResult, semantics.getPropagationResult()); | 86 | return createSemanticsResult(modelResult, semantics.getProblemTrace(), semantics.getPropagationResult()); |
83 | } | 87 | } |
84 | 88 | ||
85 | |||
86 | private SemanticsResult getTracedErrorResult(EObject sourceElement, String message) { | 89 | private SemanticsResult getTracedErrorResult(EObject sourceElement, String message) { |
90 | var diagnostics = getTracedDiagnostics(sourceElement, null, message); | ||
91 | return getSemanticsResultWithDiagnostics(null, message, diagnostics); | ||
92 | } | ||
93 | |||
94 | private List<FeatureBasedDiagnostic> getTracedDiagnostics( | ||
95 | EObject sourceElement, EStructuralFeature feature, String message) { | ||
87 | if (sourceElement == null || !problem.eResource().equals(sourceElement.eResource())) { | 96 | if (sourceElement == null || !problem.eResource().equals(sourceElement.eResource())) { |
88 | return new SemanticsResult(message); | 97 | return List.of(); |
89 | } | 98 | } |
90 | var diagnostic = new FeatureBasedDiagnostic(Diagnostic.ERROR, message, sourceElement, null, 0, | 99 | var diagnostic = new FeatureBasedDiagnostic(Diagnostic.ERROR, message, sourceElement, feature, 0, |
91 | CheckType.EXPENSIVE, DIAGNOSTIC_ID); | 100 | CheckType.EXPENSIVE, DIAGNOSTIC_ID); |
92 | var issues = convertIssues(List.of(diagnostic)); | 101 | return List.of(diagnostic); |
93 | return new SemanticsResult(issues); | 102 | } |
103 | |||
104 | private SemanticsResult getSemanticsResultWithDiagnostics( | ||
105 | SemanticsModelResult modelResult, String message, List<FeatureBasedDiagnostic> diagnostics) { | ||
106 | if (diagnostics.isEmpty()) { | ||
107 | return new SemanticsResult(modelResult, message); | ||
108 | } | ||
109 | var issues = convertIssues(diagnostics); | ||
110 | return new SemanticsResult(modelResult, issues); | ||
94 | } | 111 | } |
95 | 112 | ||
96 | private List<ValidationResult.Issue> convertIssues(List<FeatureBasedDiagnostic> diagnostics) { | 113 | private List<ValidationResult.Issue> convertIssues(List<FeatureBasedDiagnostic> diagnostics) { |
@@ -114,26 +131,30 @@ class SemanticsWorker implements Callable<SemanticsResult> { | |||
114 | return new SemanticsModelResult(nodesMetadata, relationsMetadata, partialInterpretation); | 131 | return new SemanticsModelResult(nodesMetadata, relationsMetadata, partialInterpretation); |
115 | } | 132 | } |
116 | 133 | ||
117 | private SemanticsResult createSemanticsResult(SemanticsModelResult modelResult, | 134 | private SemanticsResult createSemanticsResult( |
118 | PropagationResult propagationResult) { | 135 | SemanticsModelResult modelResult, ProblemTrace trace, PropagationResult propagationResult) { |
119 | if (!(propagationResult instanceof PropagationRejectedResult rejectedResult)) { | 136 | if (!(propagationResult instanceof PropagationRejectedResult rejectedResult)) { |
120 | return new SemanticsResult(modelResult); | 137 | return new SemanticsResult(modelResult); |
121 | } | 138 | } |
122 | var message = rejectedResult.formatMessage(); | 139 | var message = rejectedResult.formatMessage(); |
123 | if (!(rejectedResult.reason() instanceof ScopePropagator)) { | 140 | List<FeatureBasedDiagnostic> diagnostics = switch (rejectedResult.reason()) { |
124 | return new SemanticsResult(modelResult, message); | 141 | case ScopePropagator ignored -> getScopePropagatorDiagnostics(message); |
125 | } | 142 | case Rule rule -> getRuleDiagnostics(rule, trace, message); |
126 | var diagnostics = new ArrayList<FeatureBasedDiagnostic>(); | 143 | default -> List.of(); |
127 | for (var statement : problem.getStatements()) { | 144 | }; |
128 | if (statement instanceof ScopeDeclaration scopeDeclaration) { | 145 | return getSemanticsResultWithDiagnostics(modelResult, message, diagnostics); |
129 | diagnostics.add(new FeatureBasedDiagnostic(Diagnostic.ERROR, message, scopeDeclaration, null, 0, | 146 | } |
130 | CheckType.EXPENSIVE, DIAGNOSTIC_ID)); | 147 | |
131 | } | 148 | private List<FeatureBasedDiagnostic> getScopePropagatorDiagnostics(String message) { |
132 | } | 149 | return problem.getStatements().stream() |
133 | if (diagnostics.isEmpty()) { | 150 | .filter(ScopeDeclaration.class::isInstance) |
134 | return new SemanticsResult(modelResult, message); | 151 | .map(eObject -> new FeatureBasedDiagnostic(Diagnostic.ERROR, message, eObject, null, 0, |
135 | } | 152 | CheckType.EXPENSIVE, DIAGNOSTIC_ID)) |
136 | var issues = convertIssues(diagnostics); | 153 | .toList(); |
137 | return new SemanticsResult(modelResult, issues); | 154 | } |
155 | |||
156 | private List<FeatureBasedDiagnostic> getRuleDiagnostics(Rule rule, ProblemTrace trace, String message) { | ||
157 | var ruleDefinition = trace.getRuleDefinition(rule); | ||
158 | return getTracedDiagnostics(ruleDefinition, ProblemPackage.Literals.NAMED_ELEMENT__NAME, message); | ||
138 | } | 159 | } |
139 | } | 160 | } |
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 index f8a89b30..2a22f00d 100644 --- 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 | |||
@@ -27,6 +27,8 @@ public interface PropagationBuilder extends ModelAdapterBuilder { | |||
27 | 27 | ||
28 | PropagationBuilder propagator(Propagator propagator); | 28 | PropagationBuilder propagator(Propagator propagator); |
29 | 29 | ||
30 | PropagationBuilder throwOnFatalRejection(boolean throwOnFatalRejection); | ||
31 | |||
30 | @Override | 32 | @Override |
31 | PropagationStoreAdapter build(ModelStore store); | 33 | PropagationStoreAdapter build(ModelStore store); |
32 | } | 34 | } |
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/propagation/PropagationRejectedResult.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/propagation/PropagationRejectedResult.java index 6d696de7..0ef1dc38 100644 --- a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/propagation/PropagationRejectedResult.java +++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/propagation/PropagationRejectedResult.java | |||
@@ -5,7 +5,11 @@ | |||
5 | */ | 5 | */ |
6 | package tools.refinery.store.dse.propagation; | 6 | package tools.refinery.store.dse.propagation; |
7 | 7 | ||
8 | public record PropagationRejectedResult(Object reason, String message) implements PropagationResult { | 8 | public record PropagationRejectedResult(Object reason, String message, boolean fatal) implements PropagationResult { |
9 | public PropagationRejectedResult(Object reason, String message) { | ||
10 | this(reason, message, false); | ||
11 | } | ||
12 | |||
9 | @Override | 13 | @Override |
10 | public PropagationResult andThen(PropagationResult next) { | 14 | public PropagationResult andThen(PropagationResult next) { |
11 | return this; | 15 | return this; |
@@ -18,7 +22,7 @@ public record PropagationRejectedResult(Object reason, String message) implement | |||
18 | 22 | ||
19 | @Override | 23 | @Override |
20 | public void throwIfRejected() { | 24 | public void throwIfRejected() { |
21 | throw new IllegalArgumentException(formatMessage()); | 25 | throw new IllegalStateException(formatMessage()); |
22 | } | 26 | } |
23 | 27 | ||
24 | public String formatMessage() { | 28 | public String formatMessage() { |
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 index fdd19217..7158a7ab 100644 --- 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 | |||
@@ -5,10 +5,7 @@ | |||
5 | */ | 5 | */ |
6 | package tools.refinery.store.dse.propagation.impl; | 6 | package tools.refinery.store.dse.propagation.impl; |
7 | 7 | ||
8 | import tools.refinery.store.dse.propagation.BoundPropagator; | 8 | import tools.refinery.store.dse.propagation.*; |
9 | import tools.refinery.store.dse.propagation.PropagationAdapter; | ||
10 | import tools.refinery.store.dse.propagation.PropagationResult; | ||
11 | import tools.refinery.store.dse.propagation.PropagationStoreAdapter; | ||
12 | import tools.refinery.store.model.Model; | 9 | import tools.refinery.store.model.Model; |
13 | 10 | ||
14 | class PropagationAdapterImpl implements PropagationAdapter { | 11 | class PropagationAdapterImpl implements PropagationAdapter { |
@@ -35,6 +32,11 @@ class PropagationAdapterImpl implements PropagationAdapter { | |||
35 | lastResult = propagateOne(); | 32 | lastResult = propagateOne(); |
36 | result = result.andThen(lastResult); | 33 | result = result.andThen(lastResult); |
37 | } while (lastResult.isChanged()); | 34 | } while (lastResult.isChanged()); |
35 | if (lastResult instanceof PropagationRejectedResult rejectedResult && | ||
36 | rejectedResult.fatal() && | ||
37 | storeAdapter.isThrowOnFatalRejection()) { | ||
38 | rejectedResult.throwIfRejected(); | ||
39 | } | ||
38 | return result; | 40 | return result; |
39 | } | 41 | } |
40 | 42 | ||
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 index c844a89f..da32fe44 100644 --- 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 | |||
@@ -20,6 +20,7 @@ public class PropagationBuilderImpl extends AbstractModelAdapterBuilder<Propagat | |||
20 | implements PropagationBuilder { | 20 | implements PropagationBuilder { |
21 | private final Set<Rule> propagationRules = new LinkedHashSet<>(); | 21 | private final Set<Rule> propagationRules = new LinkedHashSet<>(); |
22 | private final Deque<Propagator> propagators = new ArrayDeque<>(); | 22 | private final Deque<Propagator> propagators = new ArrayDeque<>(); |
23 | private boolean throwOnFatalRejection = true; | ||
23 | 24 | ||
24 | @Override | 25 | @Override |
25 | public PropagationBuilder rule(Rule propagationRule) { | 26 | public PropagationBuilder rule(Rule propagationRule) { |
@@ -36,6 +37,12 @@ public class PropagationBuilderImpl extends AbstractModelAdapterBuilder<Propagat | |||
36 | } | 37 | } |
37 | 38 | ||
38 | @Override | 39 | @Override |
40 | public PropagationBuilder throwOnFatalRejection(boolean throwOnFatalRejection) { | ||
41 | this.throwOnFatalRejection = throwOnFatalRejection; | ||
42 | return this; | ||
43 | } | ||
44 | |||
45 | @Override | ||
39 | protected void doConfigure(ModelStoreBuilder storeBuilder) { | 46 | protected void doConfigure(ModelStoreBuilder storeBuilder) { |
40 | super.doConfigure(storeBuilder); | 47 | super.doConfigure(storeBuilder); |
41 | if (!propagationRules.isEmpty()) { | 48 | if (!propagationRules.isEmpty()) { |
@@ -48,6 +55,6 @@ public class PropagationBuilderImpl extends AbstractModelAdapterBuilder<Propagat | |||
48 | 55 | ||
49 | @Override | 56 | @Override |
50 | protected PropagationStoreAdapter doBuild(ModelStore store) { | 57 | protected PropagationStoreAdapter doBuild(ModelStore store) { |
51 | return new PropagationStoreAdapterImpl(store, List.copyOf(propagators)); | 58 | return new PropagationStoreAdapterImpl(store, List.copyOf(propagators), throwOnFatalRejection); |
52 | } | 59 | } |
53 | } | 60 | } |
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 index a223caed..4f7b8622 100644 --- 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 | |||
@@ -13,13 +13,17 @@ import tools.refinery.store.model.ModelStore; | |||
13 | 13 | ||
14 | import java.util.List; | 14 | import java.util.List; |
15 | 15 | ||
16 | // This should not be a record, because we don't want auto-generated {@code equals} and {@code hashCode} methods. | ||
17 | @SuppressWarnings("ClassCanBeRecord") | ||
16 | class PropagationStoreAdapterImpl implements PropagationStoreAdapter { | 18 | class PropagationStoreAdapterImpl implements PropagationStoreAdapter { |
17 | private final ModelStore store; | 19 | private final ModelStore store; |
18 | private final List<Propagator> propagators; | 20 | private final List<Propagator> propagators; |
21 | private final boolean throwOnFatalRejection; | ||
19 | 22 | ||
20 | PropagationStoreAdapterImpl(ModelStore store, List<Propagator> propagators) { | 23 | PropagationStoreAdapterImpl(ModelStore store, List<Propagator> propagators, boolean throwOnFatalRejection) { |
21 | this.store = store; | 24 | this.store = store; |
22 | this.propagators = propagators; | 25 | this.propagators = propagators; |
26 | this.throwOnFatalRejection = throwOnFatalRejection; | ||
23 | } | 27 | } |
24 | 28 | ||
25 | @Override | 29 | @Override |
@@ -35,4 +39,8 @@ class PropagationStoreAdapterImpl implements PropagationStoreAdapter { | |||
35 | List<Propagator> getPropagators() { | 39 | List<Propagator> getPropagators() { |
36 | return propagators; | 40 | return propagators; |
37 | } | 41 | } |
42 | |||
43 | boolean isThrowOnFatalRejection() { | ||
44 | return throwOnFatalRejection; | ||
45 | } | ||
38 | } | 46 | } |
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 index f91882be..cc1e0486 100644 --- 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 | |||
@@ -44,7 +44,8 @@ class BoundPropagationRule { | |||
44 | 44 | ||
45 | public PropagationResult fireAll() { | 45 | public PropagationResult fireAll() { |
46 | if (!firedActivations.isEmpty()) { | 46 | if (!firedActivations.isEmpty()) { |
47 | throw new IllegalStateException("Stuck propagation rule '%s'.".formatted(rule.getName())); | 47 | return new PropagationRejectedResult(rule, "Propagation rule '%s' got stuck.".formatted(rule.getName()), |
48 | true); | ||
48 | } | 49 | } |
49 | if (resultSet.size() == 0) { | 50 | if (resultSet.size() == 0) { |
50 | return PropagationResult.UNCHANGED; | 51 | return PropagationResult.UNCHANGED; |