aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Kristóf Marussy <marussy@mit.bme.hu>2023-11-03 19:24:07 +0100
committerLibravatar GitHub <noreply@github.com>2023-11-03 19:24:07 +0100
commit62058e085ddf925ae14573379ded2c3333a4fde5 (patch)
treedcff140c1af411612c2ca61a34471134d762843a
parentrefactor(interpreter): aggreagator batching (diff)
parentrefactor: smenatics and facades (diff)
downloadrefinery-62058e085ddf925ae14573379ded2c3333a4fde5.tar.gz
refinery-62058e085ddf925ae14573379ded2c3333a4fde5.tar.zst
refinery-62058e085ddf925ae14573379ded2c3333a4fde5.zip
Merge pull request #47 from kris7t/generator-facade
Generator facade
-rw-r--r--settings.gradle.kts1
-rw-r--r--subprojects/generator/build.gradle.kts15
-rw-r--r--subprojects/generator/src/main/java/tools/refinery/generator/ModelFacade.java58
-rw-r--r--subprojects/generator/src/main/java/tools/refinery/generator/ModelGenerator.java71
-rw-r--r--subprojects/generator/src/main/java/tools/refinery/generator/ModelGeneratorFactory.java63
-rw-r--r--subprojects/generator/src/main/java/tools/refinery/generator/ModelSemantics.java17
-rw-r--r--subprojects/generator/src/main/java/tools/refinery/generator/ModelSemanticsFactory.java45
-rw-r--r--subprojects/generator/src/main/java/tools/refinery/generator/ProblemLoader.java90
-rw-r--r--subprojects/generator/src/main/java/tools/refinery/generator/UnsatisfiableProblemException.java12
-rw-r--r--subprojects/generator/src/main/java/tools/refinery/generator/ValidationErrorsException.java64
-rw-r--r--subprojects/generator/src/main/java/tools/refinery/generator/standalone/StandaloneRefinery.java46
-rw-r--r--subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/ModelInitializer.java (renamed from subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/ModelInitializer.java)185
-rw-r--r--subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/ProblemTrace.java46
-rw-r--r--subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/ProblemTraceImpl.java187
-rw-r--r--subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/SemanticsUtils.java (renamed from subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/SemanticsUtils.java)2
-rw-r--r--subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/TracedException.java (renamed from subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/TracedException.java)2
-rw-r--r--subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/internal/DecisionTree.java (renamed from subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/DecisionTree.java)2
-rw-r--r--subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/internal/DecisionTreeCursor.java (renamed from subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/DecisionTreeCursor.java)2
-rw-r--r--subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/internal/DecisionTreeNode.java (renamed from subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/DecisionTreeNode.java)2
-rw-r--r--subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/internal/DecisionTreeValue.java (renamed from subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/DecisionTreeValue.java)2
-rw-r--r--subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/internal/IntermediateNode.java (renamed from subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/IntermediateNode.java)2
-rw-r--r--subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/internal/MutableSeed.java (renamed from subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/MutableSeed.java)2
-rw-r--r--subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/internal/NullaryMutableSeed.java (renamed from subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/NullaryMutableSeed.java)2
-rw-r--r--subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/internal/TerminalNode.java (renamed from subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/TerminalNode.java)2
-rw-r--r--subprojects/language-semantics/src/test/java/tools/refinery/language/semantics/CountPropagationTest.java (renamed from subprojects/language-semantics/src/test/java/tools/refinery/language/semantics/model/CountPropagationTest.java)2
-rw-r--r--subprojects/language-semantics/src/test/java/tools/refinery/language/semantics/ModelGenerationTest.java (renamed from subprojects/language-semantics/src/test/java/tools/refinery/language/semantics/model/ModelGenerationTest.java)2
-rw-r--r--subprojects/language-semantics/src/test/java/tools/refinery/language/semantics/internal/DecisionTreeTests.java (renamed from subprojects/language-semantics/src/test/java/tools/refinery/language/semantics/model/internal/DecisionTreeTests.java)2
-rw-r--r--subprojects/language-web/build.gradle.kts4
-rw-r--r--subprojects/language-web/src/main/java/tools/refinery/language/web/generator/ModelGenerationSuccessResult.java4
-rw-r--r--subprojects/language-web/src/main/java/tools/refinery/language/web/generator/ModelGenerationWorker.java91
-rw-r--r--subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/PartialInterpretation2Json.java20
-rw-r--r--subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/SemanticsSuccessResult.java4
-rw-r--r--subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/SemanticsWorker.java63
-rw-r--r--subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/BuiltInDetail.java (renamed from subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/metadata/BuiltInDetail.java)2
-rw-r--r--subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/ClassDetail.java (renamed from subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/metadata/ClassDetail.java)2
-rw-r--r--subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/Metadata.java (renamed from subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/metadata/Metadata.java)2
-rw-r--r--subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/MetadataCreator.java (renamed from subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/metadata/MetadataCreator.java)41
-rw-r--r--subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/NodeKind.java (renamed from subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/metadata/NodeKind.java)2
-rw-r--r--subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/NodeMetadata.java (renamed from subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/metadata/NodeMetadata.java)2
-rw-r--r--subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/OppositeReferenceDetail.java (renamed from subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/metadata/OppositeReferenceDetail.java)2
-rw-r--r--subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/PredicateDetail.java (renamed from subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/metadata/PredicateDetail.java)2
-rw-r--r--subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/ReferenceDetail.java (renamed from subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/metadata/ReferenceDetail.java)2
-rw-r--r--subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/RelationDetail.java (renamed from subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/metadata/RelationDetail.java)2
-rw-r--r--subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/RelationMetadata.java (renamed from subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/metadata/RelationMetadata.java)2
-rw-r--r--subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/servlet/XtextWebSocket.java2
45 files changed, 912 insertions, 263 deletions
diff --git a/settings.gradle.kts b/settings.gradle.kts
index 0a9d4ca5..40df30ff 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -8,6 +8,7 @@ rootProject.name = "refinery"
8 8
9include( 9include(
10 "frontend", 10 "frontend",
11 "generator",
11 "interpreter", 12 "interpreter",
12 "interpreter-localsearch", 13 "interpreter-localsearch",
13 "interpreter-rete", 14 "interpreter-rete",
diff --git a/subprojects/generator/build.gradle.kts b/subprojects/generator/build.gradle.kts
new file mode 100644
index 00000000..d87ce6de
--- /dev/null
+++ b/subprojects/generator/build.gradle.kts
@@ -0,0 +1,15 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6
7plugins {
8 id("tools.refinery.gradle.java-library")
9}
10
11dependencies {
12 api(project(":refinery-language-semantics"))
13 api(libs.eclipseCollections.api)
14 implementation(project(":refinery-store-query-interpreter"))
15}
diff --git a/subprojects/generator/src/main/java/tools/refinery/generator/ModelFacade.java b/subprojects/generator/src/main/java/tools/refinery/generator/ModelFacade.java
new file mode 100644
index 00000000..a00ddc46
--- /dev/null
+++ b/subprojects/generator/src/main/java/tools/refinery/generator/ModelFacade.java
@@ -0,0 +1,58 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.generator;
7
8import tools.refinery.language.semantics.ProblemTrace;
9import tools.refinery.store.model.Model;
10import tools.refinery.store.model.ModelStore;
11import tools.refinery.store.reasoning.ReasoningAdapter;
12import tools.refinery.store.reasoning.ReasoningStoreAdapter;
13import tools.refinery.store.reasoning.interpretation.PartialInterpretation;
14import tools.refinery.store.reasoning.literal.Concreteness;
15import tools.refinery.store.reasoning.representation.PartialSymbol;
16import tools.refinery.store.reasoning.seed.ModelSeed;
17import tools.refinery.store.reasoning.translator.TranslationException;
18
19public abstract class ModelFacade {
20 private final ProblemTrace problemTrace;
21 private final ModelStore store;
22 private final Model model;
23 private final ReasoningAdapter reasoningAdapter;
24 private final Concreteness concreteness;
25
26 protected ModelFacade(ProblemTrace problemTrace, ModelStore store, ModelSeed modelSeed,
27 Concreteness concreteness) {
28 this.problemTrace = problemTrace;
29 this.store = store;
30 try {
31 model = store.getAdapter(ReasoningStoreAdapter.class).createInitialModel(modelSeed);
32 } catch (TranslationException e) {
33 throw problemTrace.wrapException(e);
34 }
35 reasoningAdapter = model.getAdapter(ReasoningAdapter.class);
36 this.concreteness = concreteness;
37 }
38
39 public ProblemTrace getProblemTrace() {
40 return problemTrace;
41 }
42
43 public ModelStore getModelStore() {
44 return store;
45 }
46
47 public Model getModel() {
48 return model;
49 }
50
51 public Concreteness getConcreteness() {
52 return concreteness;
53 }
54
55 public <A, C> PartialInterpretation<A, C> getPartialInterpretation(PartialSymbol<A, C> partialSymbol) {
56 return reasoningAdapter.getPartialInterpretation(concreteness, partialSymbol);
57 }
58}
diff --git a/subprojects/generator/src/main/java/tools/refinery/generator/ModelGenerator.java b/subprojects/generator/src/main/java/tools/refinery/generator/ModelGenerator.java
new file mode 100644
index 00000000..5b44c10a
--- /dev/null
+++ b/subprojects/generator/src/main/java/tools/refinery/generator/ModelGenerator.java
@@ -0,0 +1,71 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.generator;
7
8import tools.refinery.language.semantics.ProblemTrace;
9import tools.refinery.store.dse.strategy.BestFirstStoreManager;
10import tools.refinery.store.map.Version;
11import tools.refinery.store.model.ModelStore;
12import tools.refinery.store.reasoning.interpretation.PartialInterpretation;
13import tools.refinery.store.reasoning.literal.Concreteness;
14import tools.refinery.store.reasoning.representation.PartialSymbol;
15import tools.refinery.store.reasoning.seed.ModelSeed;
16
17public class ModelGenerator extends ModelFacade {
18 private final Version initialVersion;
19
20 private int randomSeed = 0;
21
22 private boolean lastGenerationSuccessful;
23
24 public ModelGenerator(ProblemTrace problemTrace, ModelStore store, ModelSeed modelSeed) {
25 super(problemTrace, store, modelSeed, Concreteness.CANDIDATE);
26 initialVersion = getModel().commit();
27 }
28
29 public int getRandomSeed() {
30 return randomSeed;
31 }
32
33 public void setRandomSeed(int randomSeed) {
34 this.randomSeed = randomSeed;
35 this.lastGenerationSuccessful = false;
36 }
37
38 public boolean isLastGenerationSuccessful() {
39 return lastGenerationSuccessful;
40 }
41
42 // This method only makes sense if it returns {@code true} on success.
43 @SuppressWarnings("BooleanMethodIsAlwaysInverted")
44 public boolean tryGenerate() {
45 lastGenerationSuccessful = false;
46 randomSeed++;
47 var bestFirst = new BestFirstStoreManager(getModelStore(), 1);
48 bestFirst.startExploration(initialVersion, randomSeed);
49 var solutions = bestFirst.getSolutionStore().getSolutions();
50 if (solutions.isEmpty()) {
51 return false;
52 }
53 getModel().restore(solutions.get(0).version());
54 lastGenerationSuccessful = true;
55 return true;
56 }
57
58 public void generate() {
59 if (!tryGenerate()) {
60 throw new UnsatisfiableProblemException();
61 }
62 }
63
64 @Override
65 public <A, C> PartialInterpretation<A, C> getPartialInterpretation(PartialSymbol<A, C> partialSymbol) {
66 if (!lastGenerationSuccessful) {
67 throw new IllegalStateException("No generated model is available");
68 }
69 return super.getPartialInterpretation(partialSymbol);
70 }
71}
diff --git a/subprojects/generator/src/main/java/tools/refinery/generator/ModelGeneratorFactory.java b/subprojects/generator/src/main/java/tools/refinery/generator/ModelGeneratorFactory.java
new file mode 100644
index 00000000..6642d591
--- /dev/null
+++ b/subprojects/generator/src/main/java/tools/refinery/generator/ModelGeneratorFactory.java
@@ -0,0 +1,63 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.generator;
7
8import com.google.inject.Inject;
9import com.google.inject.Provider;
10import tools.refinery.language.model.problem.Problem;
11import tools.refinery.language.semantics.ModelInitializer;
12import tools.refinery.store.dse.propagation.PropagationAdapter;
13import tools.refinery.store.dse.transition.DesignSpaceExplorationAdapter;
14import tools.refinery.store.model.ModelStore;
15import tools.refinery.store.query.interpreter.QueryInterpreterAdapter;
16import tools.refinery.store.reasoning.ReasoningAdapter;
17import tools.refinery.store.reasoning.literal.Concreteness;
18import tools.refinery.store.statecoding.StateCoderAdapter;
19import tools.refinery.store.util.CancellationToken;
20
21import java.util.Collection;
22import java.util.Set;
23
24public final class ModelGeneratorFactory {
25 @Inject
26 private Provider<ModelInitializer> initializerProvider;
27
28 private CancellationToken cancellationToken = CancellationToken.NONE;
29
30 private boolean debugPartialInterpretations;
31
32 public ModelGeneratorFactory cancellationToken(CancellationToken cancellationToken) {
33 this.cancellationToken = cancellationToken;
34 return this;
35 }
36
37 public ModelGeneratorFactory debugPartialInterpretations(boolean debugPartialInterpretations) {
38 this.debugPartialInterpretations = debugPartialInterpretations;
39 return this;
40 }
41
42 public ModelGenerator createGenerator(Problem problem) {
43 var initializer = initializerProvider.get();
44 initializer.readProblem(problem);
45 cancellationToken.checkCancelled();
46 var storeBuilder = ModelStore.builder()
47 .cancellationToken(cancellationToken)
48 .with(QueryInterpreterAdapter.builder())
49 .with(PropagationAdapter.builder())
50 .with(StateCoderAdapter.builder())
51 .with(DesignSpaceExplorationAdapter.builder())
52 .with(ReasoningAdapter.builder()
53 .requiredInterpretations(getRequiredInterpretations()));
54 initializer.configureStoreBuilder(storeBuilder);
55 var store = storeBuilder.build();
56 return new ModelGenerator(initializer.getProblemTrace(), store, initializer.getModelSeed());
57 }
58
59 private Collection<Concreteness> getRequiredInterpretations() {
60 return debugPartialInterpretations ? Set.of(Concreteness.PARTIAL, Concreteness.CANDIDATE) :
61 Set.of(Concreteness.CANDIDATE);
62 }
63}
diff --git a/subprojects/generator/src/main/java/tools/refinery/generator/ModelSemantics.java b/subprojects/generator/src/main/java/tools/refinery/generator/ModelSemantics.java
new file mode 100644
index 00000000..bc02c887
--- /dev/null
+++ b/subprojects/generator/src/main/java/tools/refinery/generator/ModelSemantics.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.generator;
7
8import tools.refinery.language.semantics.ProblemTrace;
9import tools.refinery.store.model.ModelStore;
10import tools.refinery.store.reasoning.literal.Concreteness;
11import tools.refinery.store.reasoning.seed.ModelSeed;
12
13public class ModelSemantics extends ModelFacade {
14 public ModelSemantics(ProblemTrace problemTrace, ModelStore store, ModelSeed modelSeed) {
15 super(problemTrace, store, modelSeed, Concreteness.PARTIAL);
16 }
17}
diff --git a/subprojects/generator/src/main/java/tools/refinery/generator/ModelSemanticsFactory.java b/subprojects/generator/src/main/java/tools/refinery/generator/ModelSemanticsFactory.java
new file mode 100644
index 00000000..b6263b37
--- /dev/null
+++ b/subprojects/generator/src/main/java/tools/refinery/generator/ModelSemanticsFactory.java
@@ -0,0 +1,45 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.generator;
7
8import com.google.inject.Inject;
9import com.google.inject.Provider;
10import tools.refinery.language.model.problem.Problem;
11import tools.refinery.language.semantics.ModelInitializer;
12import tools.refinery.store.dse.propagation.PropagationAdapter;
13import tools.refinery.store.model.ModelStore;
14import tools.refinery.store.query.interpreter.QueryInterpreterAdapter;
15import tools.refinery.store.reasoning.ReasoningAdapter;
16import tools.refinery.store.reasoning.literal.Concreteness;
17import tools.refinery.store.util.CancellationToken;
18
19import java.util.Set;
20
21public final class ModelSemanticsFactory {
22 @Inject
23 private Provider<ModelInitializer> initializerProvider;
24
25 private CancellationToken cancellationToken = CancellationToken.NONE;
26
27 public ModelSemanticsFactory cancellationToken(CancellationToken cancellationToken) {
28 this.cancellationToken = cancellationToken;
29 return this;
30 }
31
32 public ModelSemantics createSemantics(Problem problem) {
33 var initializer = initializerProvider.get();
34 initializer.readProblem(problem);
35 var storeBuilder = ModelStore.builder()
36 .cancellationToken(cancellationToken)
37 .with(QueryInterpreterAdapter.builder())
38 .with(PropagationAdapter.builder())
39 .with(ReasoningAdapter.builder()
40 .requiredInterpretations(Set.of(Concreteness.PARTIAL)));
41 initializer.configureStoreBuilder(storeBuilder);
42 var store = storeBuilder.build();
43 return new ModelSemantics(initializer.getProblemTrace(), store, initializer.getModelSeed());
44 }
45}
diff --git a/subprojects/generator/src/main/java/tools/refinery/generator/ProblemLoader.java b/subprojects/generator/src/main/java/tools/refinery/generator/ProblemLoader.java
new file mode 100644
index 00000000..29f80714
--- /dev/null
+++ b/subprojects/generator/src/main/java/tools/refinery/generator/ProblemLoader.java
@@ -0,0 +1,90 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.generator;
7
8import com.google.inject.Inject;
9import com.google.inject.Provider;
10import org.eclipse.emf.common.util.URI;
11import org.eclipse.emf.ecore.resource.Resource;
12import org.eclipse.xtext.diagnostics.Severity;
13import org.eclipse.xtext.resource.IResourceFactory;
14import org.eclipse.xtext.resource.XtextResourceSet;
15import org.eclipse.xtext.util.LazyStringInputStream;
16import org.eclipse.xtext.validation.CheckMode;
17import org.eclipse.xtext.validation.IResourceValidator;
18import tools.refinery.language.model.problem.Problem;
19import tools.refinery.store.util.CancellationToken;
20
21import java.io.File;
22import java.io.IOException;
23import java.io.InputStream;
24import java.util.Map;
25
26public class ProblemLoader {
27 @Inject
28 private Provider<XtextResourceSet> resourceSetProvider;
29
30 @Inject
31 private IResourceFactory resourceFactory;
32
33 @Inject
34 private IResourceValidator resourceValidator;
35
36 private CancellationToken cancellationToken = CancellationToken.NONE;
37
38 public ProblemLoader cancellationToken(CancellationToken cancellationToken) {
39 this.cancellationToken = cancellationToken;
40 return this;
41 }
42
43 public Problem loadString(String problemString) throws IOException {
44 try (var stream = new LazyStringInputStream(problemString)) {
45 return loadStream(stream);
46 }
47 }
48
49 public Problem loadStream(InputStream inputStream) throws IOException {
50 var resourceSet = resourceSetProvider.get();
51 var resource = resourceFactory.createResource(URI.createFileURI("__synthetic.problem"));
52 resourceSet.getResources().add(resource);
53 resource.load(inputStream, Map.of());
54 return loadResource(resource);
55 }
56
57 public Problem loadFile(File file) throws IOException {
58 return loadFile(file.getAbsolutePath());
59 }
60
61 public Problem loadFile(String filePath) throws IOException {
62 return loadUri(URI.createFileURI(filePath));
63 }
64
65 public Problem loadUri(URI uri) throws IOException {
66 var resourceSet = resourceSetProvider.get();
67 var resource = resourceFactory.createResource(uri);
68 resourceSet.getResources().add(resource);
69 resource.load(Map.of());
70 return loadResource(resource);
71 }
72
73 public Problem loadResource(Resource resource) {
74 var issues = resourceValidator.validate(resource, CheckMode.ALL, () -> {
75 cancellationToken.checkCancelled();
76 return Thread.interrupted();
77 });
78 cancellationToken.checkCancelled();
79 var errors = issues.stream()
80 .filter(issue -> issue.getSeverity() == Severity.ERROR)
81 .toList();
82 if (!errors.isEmpty()) {
83 throw new ValidationErrorsException(resource.getURI(), errors);
84 }
85 if (resource.getContents().isEmpty() || !(resource.getContents().get(0) instanceof Problem problem)) {
86 throw new IllegalArgumentException("Model generation problem not found in resource " + resource.getURI());
87 }
88 return problem;
89 }
90}
diff --git a/subprojects/generator/src/main/java/tools/refinery/generator/UnsatisfiableProblemException.java b/subprojects/generator/src/main/java/tools/refinery/generator/UnsatisfiableProblemException.java
new file mode 100644
index 00000000..4fb18b90
--- /dev/null
+++ b/subprojects/generator/src/main/java/tools/refinery/generator/UnsatisfiableProblemException.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 */
6package tools.refinery.generator;
7
8public class UnsatisfiableProblemException extends RuntimeException {
9 public UnsatisfiableProblemException() {
10 super("Model generation problem was unsatisfiable");
11 }
12}
diff --git a/subprojects/generator/src/main/java/tools/refinery/generator/ValidationErrorsException.java b/subprojects/generator/src/main/java/tools/refinery/generator/ValidationErrorsException.java
new file mode 100644
index 00000000..d668e51d
--- /dev/null
+++ b/subprojects/generator/src/main/java/tools/refinery/generator/ValidationErrorsException.java
@@ -0,0 +1,64 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.generator;
7
8import org.eclipse.emf.common.util.URI;
9import org.eclipse.xtext.validation.Issue;
10
11import java.util.List;
12
13public class ValidationErrorsException extends IllegalArgumentException {
14 private final transient URI resourceUri;
15
16 private final String resourceUriString;
17
18 private final transient List<Issue> errors;
19
20 private final List<String> errorStrings;
21
22 public ValidationErrorsException(URI resourceUri, List<Issue> errors) {
23 this.resourceUri = resourceUri;
24 resourceUriString = resourceUri.toString();
25 this.errors = errors;
26 errorStrings = errors.stream()
27 .map(Issue::toString)
28 .toList();
29 }
30
31 public URI getResourceUri() {
32 return resourceUri;
33 }
34
35 public String getResourceUriString() {
36 return resourceUriString;
37 }
38
39 public List<Issue> getErrors() {
40 return errors;
41 }
42
43 public List<String> getErrorStrings() {
44 return errorStrings;
45 }
46
47 @Override
48 public String getMessage() {
49 var builder = new StringBuilder();
50 builder.append("Validation errors in resource ");
51 builder.append(resourceUriString);
52 builder.append(": ");
53 var iterator = errorStrings.iterator();
54 if (!iterator.hasNext()) {
55 return builder.toString();
56 }
57 builder.append(iterator.next());
58 while (iterator.hasNext()) {
59 builder.append(",\n");
60 builder.append(iterator.next());
61 }
62 return builder.toString();
63 }
64}
diff --git a/subprojects/generator/src/main/java/tools/refinery/generator/standalone/StandaloneRefinery.java b/subprojects/generator/src/main/java/tools/refinery/generator/standalone/StandaloneRefinery.java
new file mode 100644
index 00000000..b444491b
--- /dev/null
+++ b/subprojects/generator/src/main/java/tools/refinery/generator/standalone/StandaloneRefinery.java
@@ -0,0 +1,46 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.generator.standalone;
7
8import com.google.inject.Injector;
9import tools.refinery.generator.ModelGeneratorFactory;
10import tools.refinery.generator.ModelSemanticsFactory;
11import tools.refinery.language.ProblemStandaloneSetup;
12import tools.refinery.generator.ProblemLoader;
13
14public final class StandaloneRefinery {
15 private StandaloneRefinery() {
16 throw new IllegalArgumentException("This is a static utility class and should not be instantiated directly");
17 }
18
19 public static Injector getInjector() {
20 return LazyHolder.INJECTOR;
21 }
22
23 public static <T> T getInstance(Class<T> type) {
24 return getInjector().getInstance(type);
25 }
26
27 public static ProblemLoader getProblemLoader() {
28 return getInstance(ProblemLoader.class);
29 }
30
31 public static ModelGeneratorFactory getGeneratorFactory() {
32 return getInstance(ModelGeneratorFactory.class);
33 }
34
35 public static ModelSemanticsFactory getSemanticsFactory() {
36 return getInstance(ModelSemanticsFactory.class);
37 }
38
39 private static final class LazyHolder {
40 private static final Injector INJECTOR = createInjector();
41
42 private static Injector createInjector() {
43 return new ProblemStandaloneSetup().createInjectorAndDoEMFRegistration();
44 }
45 }
46}
diff --git a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/ModelInitializer.java b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/ModelInitializer.java
index 85c8d701..b3c58366 100644
--- a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/ModelInitializer.java
+++ b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/ModelInitializer.java
@@ -3,13 +3,11 @@
3 * 3 *
4 * SPDX-License-Identifier: EPL-2.0 4 * SPDX-License-Identifier: EPL-2.0
5 */ 5 */
6package tools.refinery.language.semantics.model; 6package tools.refinery.language.semantics;
7 7
8import com.google.inject.Inject; 8import com.google.inject.Inject;
9import org.eclipse.collections.api.factory.primitive.ObjectIntMaps;
10import org.eclipse.collections.api.map.primitive.MutableObjectIntMap;
11import tools.refinery.language.model.problem.*; 9import tools.refinery.language.model.problem.*;
12import tools.refinery.language.semantics.model.internal.MutableSeed; 10import tools.refinery.language.semantics.internal.MutableSeed;
13import tools.refinery.language.utils.BuiltinSymbols; 11import tools.refinery.language.utils.BuiltinSymbols;
14import tools.refinery.language.utils.ProblemDesugarer; 12import tools.refinery.language.utils.ProblemDesugarer;
15import tools.refinery.language.utils.ProblemUtil; 13import tools.refinery.language.utils.ProblemUtil;
@@ -23,11 +21,11 @@ import tools.refinery.store.query.literal.*;
23import tools.refinery.store.query.term.NodeVariable; 21import tools.refinery.store.query.term.NodeVariable;
24import tools.refinery.store.query.term.Variable; 22import tools.refinery.store.query.term.Variable;
25import tools.refinery.store.reasoning.ReasoningAdapter; 23import tools.refinery.store.reasoning.ReasoningAdapter;
26import tools.refinery.store.reasoning.representation.AnyPartialSymbol;
27import tools.refinery.store.reasoning.representation.PartialRelation; 24import tools.refinery.store.reasoning.representation.PartialRelation;
28import tools.refinery.store.reasoning.scope.ScopePropagator; 25import tools.refinery.store.reasoning.scope.ScopePropagator;
29import tools.refinery.store.reasoning.seed.ModelSeed; 26import tools.refinery.store.reasoning.seed.ModelSeed;
30import tools.refinery.store.reasoning.seed.Seed; 27import tools.refinery.store.reasoning.seed.Seed;
28import tools.refinery.store.reasoning.translator.TranslationException;
31import tools.refinery.store.reasoning.translator.containment.ContainmentHierarchyTranslator; 29import tools.refinery.store.reasoning.translator.containment.ContainmentHierarchyTranslator;
32import tools.refinery.store.reasoning.translator.metamodel.Metamodel; 30import tools.refinery.store.reasoning.translator.metamodel.Metamodel;
33import tools.refinery.store.reasoning.translator.metamodel.MetamodelBuilder; 31import tools.refinery.store.reasoning.translator.metamodel.MetamodelBuilder;
@@ -52,24 +50,19 @@ public class ModelInitializer {
52 @Inject 50 @Inject
53 private SemanticsUtils semanticsUtils; 51 private SemanticsUtils semanticsUtils;
54 52
55 private Problem problem; 53 @Inject
54 private ProblemTraceImpl problemTrace;
56 55
57 private ModelStoreBuilder storeBuilder; 56 private Problem problem;
58 57
59 private BuiltinSymbols builtinSymbols; 58 private BuiltinSymbols builtinSymbols;
60 59
61 private PartialRelation nodeRelation; 60 private PartialRelation nodeRelation;
62 61
63 private final MutableObjectIntMap<Node> nodeTrace = ObjectIntMaps.mutable.empty();
64
65 private final Map<Relation, RelationInfo> relationInfoMap = new LinkedHashMap<>(); 62 private final Map<Relation, RelationInfo> relationInfoMap = new LinkedHashMap<>();
66 63
67 private final Map<PartialRelation, RelationInfo> partialRelationInfoMap = new HashMap<>(); 64 private final Map<PartialRelation, RelationInfo> partialRelationInfoMap = new HashMap<>();
68 65
69 private final Map<AnyPartialSymbol, Relation> inverseTrace = new HashMap<>();
70
71 private Map<Relation, PartialRelation> relationTrace;
72
73 private final MetamodelBuilder metamodelBuilder = Metamodel.builder(); 66 private final MetamodelBuilder metamodelBuilder = Metamodel.builder();
74 67
75 private Metamodel metamodel; 68 private Metamodel metamodel;
@@ -80,79 +73,89 @@ public class ModelInitializer {
80 73
81 private ModelSeed modelSeed; 74 private ModelSeed modelSeed;
82 75
83 public Problem getProblem() { 76 public void readProblem(Problem problem) {
84 return problem; 77 if (this.problem != null) {
85 } 78 throw new IllegalArgumentException("Problem was already set");
86 79 }
87 public int getNodeCount() { 80 this.problem = problem;
88 return nodeTrace.size(); 81 problemTrace.setProblem(problem);
82 try {
83 builtinSymbols = desugarer.getBuiltinSymbols(problem).orElseThrow(() -> new IllegalArgumentException(
84 "Problem has no builtin library"));
85 var nodeInfo = collectPartialRelation(builtinSymbols.node(), 1, TruthValue.TRUE, TruthValue.TRUE);
86 nodeRelation = nodeInfo.partialRelation();
87 metamodelBuilder.type(nodeRelation);
88 putRelationInfo(builtinSymbols.exists(), new RelationInfo(ReasoningAdapter.EXISTS_SYMBOL, null,
89 TruthValue.TRUE));
90 putRelationInfo(builtinSymbols.equals(), new RelationInfo(ReasoningAdapter.EQUALS_SYMBOL,
91 (TruthValue) null,
92 null));
93 putRelationInfo(builtinSymbols.contained(),
94 new RelationInfo(ContainmentHierarchyTranslator.CONTAINED_SYMBOL, null, TruthValue.UNKNOWN));
95 putRelationInfo(builtinSymbols.contains(), new RelationInfo(ContainmentHierarchyTranslator.CONTAINS_SYMBOL,
96 null, TruthValue.UNKNOWN));
97 putRelationInfo(builtinSymbols.invalidContainer(),
98 new RelationInfo(ContainmentHierarchyTranslator.INVALID_CONTAINER, TruthValue.FALSE,
99 TruthValue.FALSE));
100 collectNodes();
101 collectPartialSymbols();
102 collectMetamodel();
103 metamodel = metamodelBuilder.build();
104 problemTrace.setMetamodel(metamodel);
105 collectAssertions();
106 int nodeCount = problemTrace.getNodeTrace().size();
107 var modelSeedBuilder = ModelSeed.builder(nodeCount);
108 for (var entry : relationInfoMap.entrySet()) {
109 var info = entry.getValue();
110 var partialRelation = info.partialRelation();
111 modelSeedBuilder.seed(partialRelation, info.toSeed(nodeCount));
112 }
113 collectScopes();
114 modelSeedBuilder.seed(MultiObjectTranslator.COUNT_SYMBOL, builder -> builder
115 .reducedValue(CardinalityIntervals.SET)
116 .putAll(countSeed));
117 modelSeed = modelSeedBuilder.build();
118 } catch (TranslationException e) {
119 throw problemTrace.wrapException(e);
120 }
89 } 121 }
90 122
91 public MutableObjectIntMap<Node> getNodeTrace() { 123 public void configureStoreBuilder(ModelStoreBuilder storeBuilder) {
92 return nodeTrace; 124 checkProblem();
125 try {
126 storeBuilder.with(new MultiObjectTranslator());
127 storeBuilder.with(new MetamodelTranslator(metamodel));
128 if (scopePropagator != null) {
129 if (storeBuilder.tryGetAdapter(PropagationBuilder.class).isEmpty()) {
130 throw new TracedException(problem, "Type scopes require a PropagationBuilder");
131 }
132 storeBuilder.with(scopePropagator);
133 }
134 collectPredicates(storeBuilder);
135 } catch (TranslationException e) {
136 throw problemTrace.wrapException(e);
137 }
93 } 138 }
94 139
95 public Map<Relation, PartialRelation> getRelationTrace() { 140 private void checkProblem() {
96 return relationTrace; 141 if (problem == null) {
142 throw new IllegalStateException("Problem is not set");
143 }
97 } 144 }
98 145
99 public Relation getInverseTrace(AnyPartialSymbol partialRelation) { 146 public ModelSeed createModel(Problem problem, ModelStoreBuilder storeBuilder) {
100 return inverseTrace.get(partialRelation); 147 readProblem(problem);
148 configureStoreBuilder(storeBuilder);
149 return getModelSeed();
101 } 150 }
102 151
103 public Metamodel getMetamodel() { 152 public ProblemTrace getProblemTrace() {
104 return metamodel; 153 checkProblem();
154 return problemTrace;
105 } 155 }
106 156
107 public ModelSeed createModel(Problem problem, ModelStoreBuilder storeBuilder) { 157 public ModelSeed getModelSeed() {
108 this.problem = problem; 158 checkProblem();
109 this.storeBuilder = storeBuilder;
110 builtinSymbols = desugarer.getBuiltinSymbols(problem).orElseThrow(() -> new IllegalArgumentException(
111 "Problem has no builtin library"));
112 var nodeInfo = collectPartialRelation(builtinSymbols.node(), 1, TruthValue.TRUE, TruthValue.TRUE);
113 nodeRelation = nodeInfo.partialRelation();
114 metamodelBuilder.type(nodeRelation);
115 putRelationInfo(builtinSymbols.exists(), new RelationInfo(ReasoningAdapter.EXISTS_SYMBOL, null,
116 TruthValue.TRUE));
117 putRelationInfo(builtinSymbols.equals(), new RelationInfo(ReasoningAdapter.EQUALS_SYMBOL,
118 (TruthValue) null,
119 null));
120 putRelationInfo(builtinSymbols.contained(), new RelationInfo(ContainmentHierarchyTranslator.CONTAINED_SYMBOL,
121 null, TruthValue.UNKNOWN));
122 putRelationInfo(builtinSymbols.contains(), new RelationInfo(ContainmentHierarchyTranslator.CONTAINS_SYMBOL,
123 null, TruthValue.UNKNOWN));
124 putRelationInfo(builtinSymbols.invalidContainer(),
125 new RelationInfo(ContainmentHierarchyTranslator.INVALID_CONTAINER, TruthValue.FALSE,
126 TruthValue.FALSE));
127 collectNodes();
128 collectPartialSymbols();
129 collectMetamodel();
130 metamodel = metamodelBuilder.build();
131 collectAssertions();
132 storeBuilder.with(new MultiObjectTranslator());
133 storeBuilder.with(new MetamodelTranslator(metamodel));
134 relationTrace = new LinkedHashMap<>(relationInfoMap.size());
135 int nodeCount = getNodeCount();
136 var modelSeedBuilder = ModelSeed.builder(nodeCount);
137 for (var entry : relationInfoMap.entrySet()) {
138 var relation = entry.getKey();
139 var info = entry.getValue();
140 var partialRelation = info.partialRelation();
141 relationTrace.put(relation, partialRelation);
142 modelSeedBuilder.seed(partialRelation, info.toSeed(nodeCount));
143 }
144 collectScopes();
145 if (scopePropagator != null) {
146 if (storeBuilder.tryGetAdapter(PropagationBuilder.class).isEmpty()) {
147 throw new TracedException(problem, "Type scopes require a PropagationBuilder");
148 }
149 storeBuilder.with(scopePropagator);
150 }
151 modelSeedBuilder.seed(MultiObjectTranslator.COUNT_SYMBOL, builder -> builder
152 .reducedValue(CardinalityIntervals.SET)
153 .putAll(countSeed));
154 modelSeed = modelSeedBuilder.build();
155 collectPredicates();
156 return modelSeed; 159 return modelSeed;
157 } 160 }
158 161
@@ -179,7 +182,7 @@ public class ModelInitializer {
179 } 182 }
180 183
181 private void collectNode(Node node) { 184 private void collectNode(Node node) {
182 nodeTrace.getIfAbsentPut(node, this::getNodeCount); 185 problemTrace.collectNode(node);
183 } 186 }
184 187
185 private void collectPartialSymbols() { 188 private void collectPartialSymbols() {
@@ -221,7 +224,7 @@ public class ModelInitializer {
221 private void putRelationInfo(Relation relation, RelationInfo info) { 224 private void putRelationInfo(Relation relation, RelationInfo info) {
222 relationInfoMap.put(relation, info); 225 relationInfoMap.put(relation, info);
223 partialRelationInfoMap.put(info.partialRelation(), info); 226 partialRelationInfoMap.put(info.partialRelation(), info);
224 inverseTrace.put(info.partialRelation(), relation); 227 problemTrace.putRelation(relation, info.partialRelation());
225 } 228 }
226 229
227 private RelationInfo collectPartialRelation(Relation relation, int arity, TruthValue value, 230 private RelationInfo collectPartialRelation(Relation relation, int arity, TruthValue value,
@@ -230,7 +233,7 @@ public class ModelInitializer {
230 var name = getName(relation); 233 var name = getName(relation);
231 var info = new RelationInfo(name, arity, value, defaultValue); 234 var info = new RelationInfo(name, arity, value, defaultValue);
232 partialRelationInfoMap.put(info.partialRelation(), info); 235 partialRelationInfoMap.put(info.partialRelation(), info);
233 inverseTrace.put(info.partialRelation(), relation); 236 problemTrace.putRelation(relation, info.partialRelation());
234 return info; 237 return info;
235 }); 238 });
236 } 239 }
@@ -410,7 +413,7 @@ public class ModelInitializer {
410 } 413 }
411 414
412 private int getNodeId(Node node) { 415 private int getNodeId(Node node) {
413 return nodeTrace.getOrThrow(node); 416 return problemTrace.getNodeId(node);
414 } 417 }
415 418
416 private Tuple getTuple(Assertion assertion) { 419 private Tuple getTuple(Assertion assertion) {
@@ -442,17 +445,18 @@ public class ModelInitializer {
442 }; 445 };
443 } 446 }
444 447
445 private void collectPredicates() { 448 private void collectPredicates(ModelStoreBuilder storeBuilder) {
446 for (var statement : problem.getStatements()) { 449 for (var statement : problem.getStatements()) {
447 if (statement instanceof PredicateDefinition predicateDefinition) { 450 if (statement instanceof PredicateDefinition predicateDefinition) {
448 collectPredicateDefinitionTraced(predicateDefinition); 451 collectPredicateDefinitionTraced(predicateDefinition, storeBuilder);
449 } 452 }
450 } 453 }
451 } 454 }
452 455
453 private void collectPredicateDefinitionTraced(PredicateDefinition predicateDefinition) { 456 private void collectPredicateDefinitionTraced(PredicateDefinition predicateDefinition,
457 ModelStoreBuilder storeBuilder) {
454 try { 458 try {
455 collectPredicateDefinition(predicateDefinition); 459 collectPredicateDefinition(predicateDefinition, storeBuilder);
456 } catch (InvalidClauseException e) { 460 } catch (InvalidClauseException e) {
457 int clauseIndex = e.getClauseIndex(); 461 int clauseIndex = e.getClauseIndex();
458 var bodies = predicateDefinition.getBodies(); 462 var bodies = predicateDefinition.getBodies();
@@ -466,7 +470,7 @@ public class ModelInitializer {
466 } 470 }
467 } 471 }
468 472
469 private void collectPredicateDefinition(PredicateDefinition predicateDefinition) { 473 private void collectPredicateDefinition(PredicateDefinition predicateDefinition, ModelStoreBuilder storeBuilder) {
470 var partialRelation = getPartialRelation(predicateDefinition); 474 var partialRelation = getPartialRelation(predicateDefinition);
471 var query = toQuery(partialRelation.name(), predicateDefinition); 475 var query = toQuery(partialRelation.name(), predicateDefinition);
472 boolean mutable; 476 boolean mutable;
@@ -477,7 +481,7 @@ public class ModelInitializer {
477 } else { 481 } else {
478 var seed = modelSeed.getSeed(partialRelation); 482 var seed = modelSeed.getSeed(partialRelation);
479 defaultValue = seed.reducedValue() == TruthValue.FALSE ? TruthValue.FALSE : TruthValue.UNKNOWN; 483 defaultValue = seed.reducedValue() == TruthValue.FALSE ? TruthValue.FALSE : TruthValue.UNKNOWN;
480 var cursor = seed.getCursor(defaultValue, getNodeCount()); 484 var cursor = seed.getCursor(defaultValue, problemTrace.getNodeTrace().size());
481 // The symbol should be mutable if there is at least one non-default entry in the seed. 485 // The symbol should be mutable if there is at least one non-default entry in the seed.
482 mutable = cursor.move(); 486 mutable = cursor.move();
483 } 487 }
@@ -641,8 +645,8 @@ public class ModelInitializer {
641 if (newNode == null) { 645 if (newNode == null) {
642 throw new TracedException(typeScope, "Target of incremental type scope must be concrete class"); 646 throw new TracedException(typeScope, "Target of incremental type scope must be concrete class");
643 } 647 }
644 int newNodeId = nodeTrace.get(newNode); 648 int newNodeId = getNodeId(newNode);
645 var type = relationTrace.get(classDeclaration); 649 var type = problemTrace.getPartialRelation(classDeclaration);
646 var typeInfo = metamodel.typeHierarchy().getAnalysisResult(type); 650 var typeInfo = metamodel.typeHierarchy().getAnalysisResult(type);
647 if (!typeInfo.getDirectSubtypes().isEmpty()) { 651 if (!typeInfo.getDirectSubtypes().isEmpty()) {
648 throw new TracedException(typeScope, "Target of incremental type scope cannot have any subclasses"); 652 throw new TracedException(typeScope, "Target of incremental type scope cannot have any subclasses");
@@ -653,10 +657,7 @@ public class ModelInitializer {
653 } 657 }
654 658
655 private void collectTypeScope(TypeScope typeScope) { 659 private void collectTypeScope(TypeScope typeScope) {
656 var type = relationTrace.get(typeScope.getTargetType()); 660 var type = problemTrace.getPartialRelation(typeScope.getTargetType());
657 if (type == null) {
658 throw new TracedException(typeScope, "Unknown target type");
659 }
660 var interval = getCardinalityInterval(typeScope.getMultiplicity()); 661 var interval = getCardinalityInterval(typeScope.getMultiplicity());
661 if (scopePropagator == null) { 662 if (scopePropagator == null) {
662 scopePropagator = new ScopePropagator(); 663 scopePropagator = new ScopePropagator();
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
new file mode 100644
index 00000000..b8d0b804
--- /dev/null
+++ b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/ProblemTrace.java
@@ -0,0 +1,46 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.language.semantics;
7
8import org.eclipse.collections.api.map.primitive.ObjectIntMap;
9import org.eclipse.xtext.naming.QualifiedName;
10import tools.refinery.language.model.problem.Node;
11import tools.refinery.language.model.problem.Problem;
12import tools.refinery.language.model.problem.Relation;
13import tools.refinery.store.reasoning.representation.AnyPartialSymbol;
14import tools.refinery.store.reasoning.representation.PartialRelation;
15import tools.refinery.store.reasoning.translator.TranslationException;
16import tools.refinery.store.reasoning.translator.metamodel.Metamodel;
17
18import java.util.Map;
19
20public interface ProblemTrace {
21 Problem getProblem();
22
23 Metamodel getMetamodel();
24
25 ObjectIntMap<Node> getNodeTrace();
26
27 int getNodeId(Node node);
28
29 int getNodeId(QualifiedName qualifiedName);
30
31 int getNodeId(String qualifiedName);
32
33 Map<Relation, PartialRelation> getRelationTrace();
34
35 Map<AnyPartialSymbol, Relation> getInverseRelationTrace();
36
37 Relation getRelation(AnyPartialSymbol partialSymbol);
38
39 RuntimeException wrapException(TranslationException translationException);
40
41 PartialRelation getPartialRelation(Relation relation);
42
43 PartialRelation getPartialRelation(QualifiedName qualifiedName);
44
45 PartialRelation getPartialRelation(String qualifiedName);
46}
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
new file mode 100644
index 00000000..cc634949
--- /dev/null
+++ b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/ProblemTraceImpl.java
@@ -0,0 +1,187 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.language.semantics;
7
8import com.google.inject.Inject;
9import org.eclipse.collections.api.factory.primitive.ObjectIntMaps;
10import org.eclipse.collections.api.map.primitive.MutableObjectIntMap;
11import org.eclipse.collections.api.map.primitive.ObjectIntMap;
12import org.eclipse.emf.ecore.util.EcoreUtil;
13import org.eclipse.xtext.naming.IQualifiedNameConverter;
14import org.eclipse.xtext.naming.QualifiedName;
15import org.eclipse.xtext.scoping.IScope;
16import org.eclipse.xtext.scoping.IScopeProvider;
17import tools.refinery.language.model.problem.Node;
18import tools.refinery.language.model.problem.Problem;
19import tools.refinery.language.model.problem.ProblemPackage;
20import tools.refinery.language.model.problem.Relation;
21import tools.refinery.store.reasoning.representation.AnyPartialSymbol;
22import tools.refinery.store.reasoning.representation.PartialRelation;
23import tools.refinery.store.reasoning.translator.TranslationException;
24import tools.refinery.store.reasoning.translator.metamodel.Metamodel;
25
26import java.util.Collections;
27import java.util.HashMap;
28import java.util.LinkedHashMap;
29import java.util.Map;
30
31public class ProblemTraceImpl implements ProblemTrace {
32 @Inject
33 private IQualifiedNameConverter qualifiedNameConverter;
34
35 @Inject
36 private SemanticsUtils semanticsUtils;
37
38 @Inject
39 private IScopeProvider scopeProvider;
40
41 private Problem problem;
42 private Metamodel metamodel;
43 private final MutableObjectIntMap<Node> mutableNodeTrace = ObjectIntMaps.mutable.empty();
44 private final ObjectIntMap<Node> nodeTrace = mutableNodeTrace.asUnmodifiable();
45 private final Map<Relation, PartialRelation> mutableRelationTrace = new LinkedHashMap<>();
46 private final Map<Relation, PartialRelation> relationTrace =
47 Collections.unmodifiableMap(mutableRelationTrace);
48 private final Map<AnyPartialSymbol, Relation> mutableInverseTrace = new HashMap<>();
49 private final Map<AnyPartialSymbol, Relation> inverseTrace = Collections.unmodifiableMap(mutableInverseTrace);
50
51 @Override
52 public Problem getProblem() {
53 return problem;
54 }
55
56 void setProblem(Problem problem) {
57 this.problem = problem;
58 }
59
60 @Override
61 public Metamodel getMetamodel() {
62 return metamodel;
63 }
64
65 void setMetamodel(Metamodel metamodel) {
66 this.metamodel = metamodel;
67 }
68
69 @Override
70 public ObjectIntMap<Node> getNodeTrace() {
71 return nodeTrace;
72 }
73
74 void collectNode(Node node) {
75 mutableNodeTrace.getIfAbsentPut(node, mutableNodeTrace.size());
76 }
77
78 @Override
79 public int getNodeId(Node node) {
80 try {
81 return nodeTrace.getOrThrow(node);
82 } catch (IllegalStateException e) {
83 var qualifiedName = semanticsUtils.getName(node);
84 throw new TracedException(node, "No node ID for " + qualifiedName, e);
85 }
86 }
87
88 @Override
89 public int getNodeId(QualifiedName qualifiedName) {
90 var nodeScope = scopeProvider.getScope(problem, ProblemPackage.Literals.NODE_ASSERTION_ARGUMENT__NODE);
91 return getNodeId(getElement(nodeScope, qualifiedName, Node.class));
92 }
93
94 @Override
95 public int getNodeId(String qualifiedName) {
96 var convertedName = qualifiedNameConverter.toQualifiedName(qualifiedName);
97 return getNodeId(convertedName);
98 }
99
100 @Override
101 public Map<Relation, PartialRelation> getRelationTrace() {
102 return relationTrace;
103 }
104
105 void putRelation(Relation relation, PartialRelation partialRelation) {
106 var oldPartialRelation = mutableRelationTrace.put(relation, partialRelation);
107 if (oldPartialRelation != null) {
108 throw new TracedException(relation, "Relation already mapped to partial relation: " + oldPartialRelation);
109 }
110 var oldRelation = mutableInverseTrace.put(partialRelation, relation);
111 if (oldRelation != null) {
112 throw new TracedException(oldRelation, "Partial relation %s was already mapped to relation"
113 .formatted(partialRelation));
114 }
115 }
116
117 @Override
118 public Map<AnyPartialSymbol, Relation> getInverseRelationTrace() {
119 return inverseTrace;
120 }
121
122 @Override
123 public Relation getRelation(AnyPartialSymbol partialSymbol) {
124 var relation = mutableInverseTrace.get(partialSymbol);
125 if (relation == null) {
126 throw new IllegalArgumentException("No relation for partial symbol: " + partialSymbol);
127 }
128 return relation;
129 }
130
131 @Override
132 public RuntimeException wrapException(TranslationException translationException) {
133 var partialSymbol = translationException.getPartialSymbol();
134 if (partialSymbol == null) {
135 return translationException;
136 }
137 var relation = mutableInverseTrace.get(partialSymbol);
138 if (relation == null) {
139 return translationException;
140 }
141 return new TracedException(relation, translationException);
142 }
143
144 @Override
145 public PartialRelation getPartialRelation(Relation relation) {
146 var partialRelation = mutableRelationTrace.get(relation);
147 if (partialRelation == null) {
148 var qualifiedName = semanticsUtils.getName(relation);
149 throw new TracedException(relation, "No partial relation for " + qualifiedName);
150 }
151 return partialRelation;
152 }
153
154 @Override
155 public PartialRelation getPartialRelation(QualifiedName qualifiedName) {
156 var relationScope = scopeProvider.getScope(problem, ProblemPackage.Literals.ASSERTION__RELATION);
157 return getPartialRelation(getElement(relationScope, qualifiedName, Relation.class));
158 }
159
160 @Override
161 public PartialRelation getPartialRelation(String qualifiedName) {
162 var convertedName = qualifiedNameConverter.toQualifiedName(qualifiedName);
163 return getPartialRelation(convertedName);
164 }
165
166 private <T> T getElement(IScope scope, QualifiedName qualifiedName, Class<T> type) {
167 var iterator = scope.getElements(qualifiedName).iterator();
168 if (!iterator.hasNext()) {
169 var qualifiedNameString = qualifiedNameConverter.toString(qualifiedName);
170 throw new IllegalArgumentException("No such %s: %s"
171 .formatted(type.getName(), qualifiedNameString));
172 }
173 var eObjectDescription = iterator.next();
174 if (iterator.hasNext()) {
175 var qualifiedNameString = qualifiedNameConverter.toString(qualifiedName);
176 throw new IllegalArgumentException("Ambiguous %s: %s"
177 .formatted(type.getName(), qualifiedNameString));
178 }
179 var eObject = EcoreUtil.resolve(eObjectDescription.getEObjectOrProxy(), getProblem());
180 if (!type.isInstance(eObject)) {
181 var qualifiedNameString = qualifiedNameConverter.toString(qualifiedName);
182 throw new IllegalArgumentException("Not a %s: %s"
183 .formatted(type.getName(), qualifiedNameString));
184 }
185 return type.cast(eObject);
186 }
187}
diff --git a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/SemanticsUtils.java b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/SemanticsUtils.java
index 47c89e9b..b195a8e7 100644
--- a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/SemanticsUtils.java
+++ b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/SemanticsUtils.java
@@ -3,7 +3,7 @@
3 * 3 *
4 * SPDX-License-Identifier: EPL-2.0 4 * SPDX-License-Identifier: EPL-2.0
5 */ 5 */
6package tools.refinery.language.semantics.model; 6package tools.refinery.language.semantics;
7 7
8import com.google.inject.Inject; 8import com.google.inject.Inject;
9import com.google.inject.Singleton; 9import com.google.inject.Singleton;
diff --git a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/TracedException.java b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/TracedException.java
index 38fd8a67..8636bdab 100644
--- a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/TracedException.java
+++ b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/TracedException.java
@@ -3,7 +3,7 @@
3 * 3 *
4 * SPDX-License-Identifier: EPL-2.0 4 * SPDX-License-Identifier: EPL-2.0
5 */ 5 */
6package tools.refinery.language.semantics.model; 6package tools.refinery.language.semantics;
7 7
8import org.eclipse.emf.ecore.EObject; 8import org.eclipse.emf.ecore.EObject;
9 9
diff --git a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/DecisionTree.java b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/internal/DecisionTree.java
index 32112e61..c732f784 100644
--- a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/DecisionTree.java
+++ b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/internal/DecisionTree.java
@@ -3,7 +3,7 @@
3 * 3 *
4 * SPDX-License-Identifier: EPL-2.0 4 * SPDX-License-Identifier: EPL-2.0
5 */ 5 */
6package tools.refinery.language.semantics.model.internal; 6package tools.refinery.language.semantics.internal;
7 7
8import org.eclipse.collections.api.factory.primitive.IntObjectMaps; 8import org.eclipse.collections.api.factory.primitive.IntObjectMaps;
9import tools.refinery.store.map.Cursor; 9import tools.refinery.store.map.Cursor;
diff --git a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/DecisionTreeCursor.java b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/internal/DecisionTreeCursor.java
index a9fc644a..71b54cbd 100644
--- a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/DecisionTreeCursor.java
+++ b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/internal/DecisionTreeCursor.java
@@ -3,7 +3,7 @@
3 * 3 *
4 * SPDX-License-Identifier: EPL-2.0 4 * SPDX-License-Identifier: EPL-2.0
5 */ 5 */
6package tools.refinery.language.semantics.model.internal; 6package tools.refinery.language.semantics.internal;
7 7
8import tools.refinery.store.map.Cursor; 8import tools.refinery.store.map.Cursor;
9import tools.refinery.store.representation.TruthValue; 9import tools.refinery.store.representation.TruthValue;
diff --git a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/DecisionTreeNode.java b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/internal/DecisionTreeNode.java
index 3c54e3c5..ebca2634 100644
--- a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/DecisionTreeNode.java
+++ b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/internal/DecisionTreeNode.java
@@ -3,7 +3,7 @@
3 * 3 *
4 * SPDX-License-Identifier: EPL-2.0 4 * SPDX-License-Identifier: EPL-2.0
5 */ 5 */
6package tools.refinery.language.semantics.model.internal; 6package tools.refinery.language.semantics.internal;
7 7
8import org.eclipse.collections.api.LazyIntIterable; 8import org.eclipse.collections.api.LazyIntIterable;
9import tools.refinery.store.tuple.Tuple; 9import tools.refinery.store.tuple.Tuple;
diff --git a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/DecisionTreeValue.java b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/internal/DecisionTreeValue.java
index 915ae2bf..5053e7ac 100644
--- a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/DecisionTreeValue.java
+++ b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/internal/DecisionTreeValue.java
@@ -3,7 +3,7 @@
3 * 3 *
4 * SPDX-License-Identifier: EPL-2.0 4 * SPDX-License-Identifier: EPL-2.0
5 */ 5 */
6package tools.refinery.language.semantics.model.internal; 6package tools.refinery.language.semantics.internal;
7 7
8import tools.refinery.store.representation.TruthValue; 8import tools.refinery.store.representation.TruthValue;
9 9
diff --git a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/IntermediateNode.java b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/internal/IntermediateNode.java
index e6f01d48..0e2f5d18 100644
--- a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/IntermediateNode.java
+++ b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/internal/IntermediateNode.java
@@ -3,7 +3,7 @@
3 * 3 *
4 * SPDX-License-Identifier: EPL-2.0 4 * SPDX-License-Identifier: EPL-2.0
5 */ 5 */
6package tools.refinery.language.semantics.model.internal; 6package tools.refinery.language.semantics.internal;
7 7
8import org.eclipse.collections.api.LazyIntIterable; 8import org.eclipse.collections.api.LazyIntIterable;
9import org.eclipse.collections.api.factory.primitive.IntObjectMaps; 9import org.eclipse.collections.api.factory.primitive.IntObjectMaps;
diff --git a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/MutableSeed.java b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/internal/MutableSeed.java
index 99019e2a..693b9e1f 100644
--- a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/MutableSeed.java
+++ b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/internal/MutableSeed.java
@@ -3,7 +3,7 @@
3 * 3 *
4 * SPDX-License-Identifier: EPL-2.0 4 * SPDX-License-Identifier: EPL-2.0
5 */ 5 */
6package tools.refinery.language.semantics.model.internal; 6package tools.refinery.language.semantics.internal;
7 7
8import tools.refinery.store.reasoning.seed.Seed; 8import tools.refinery.store.reasoning.seed.Seed;
9import tools.refinery.store.representation.TruthValue; 9import tools.refinery.store.representation.TruthValue;
diff --git a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/NullaryMutableSeed.java b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/internal/NullaryMutableSeed.java
index 80644b1f..7a72c656 100644
--- a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/NullaryMutableSeed.java
+++ b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/internal/NullaryMutableSeed.java
@@ -3,7 +3,7 @@
3 * 3 *
4 * SPDX-License-Identifier: EPL-2.0 4 * SPDX-License-Identifier: EPL-2.0
5 */ 5 */
6package tools.refinery.language.semantics.model.internal; 6package tools.refinery.language.semantics.internal;
7 7
8import tools.refinery.store.map.Cursor; 8import tools.refinery.store.map.Cursor;
9import tools.refinery.store.map.Cursors; 9import tools.refinery.store.map.Cursors;
diff --git a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/TerminalNode.java b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/internal/TerminalNode.java
index ce49aa62..d3dd757c 100644
--- a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/TerminalNode.java
+++ b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/internal/TerminalNode.java
@@ -3,7 +3,7 @@
3 * 3 *
4 * SPDX-License-Identifier: EPL-2.0 4 * SPDX-License-Identifier: EPL-2.0
5 */ 5 */
6package tools.refinery.language.semantics.model.internal; 6package tools.refinery.language.semantics.internal;
7 7
8import org.eclipse.collections.api.LazyIntIterable; 8import org.eclipse.collections.api.LazyIntIterable;
9import org.eclipse.collections.api.factory.primitive.IntObjectMaps; 9import org.eclipse.collections.api.factory.primitive.IntObjectMaps;
diff --git a/subprojects/language-semantics/src/test/java/tools/refinery/language/semantics/model/CountPropagationTest.java b/subprojects/language-semantics/src/test/java/tools/refinery/language/semantics/CountPropagationTest.java
index 6beae93a..b679c1ef 100644
--- a/subprojects/language-semantics/src/test/java/tools/refinery/language/semantics/model/CountPropagationTest.java
+++ b/subprojects/language-semantics/src/test/java/tools/refinery/language/semantics/CountPropagationTest.java
@@ -3,7 +3,7 @@
3 * 3 *
4 * SPDX-License-Identifier: EPL-2.0 4 * SPDX-License-Identifier: EPL-2.0
5 */ 5 */
6package tools.refinery.language.semantics.model; 6package tools.refinery.language.semantics;
7 7
8import org.junit.jupiter.api.Test; 8import org.junit.jupiter.api.Test;
9import tools.refinery.store.dse.propagation.PropagationAdapter; 9import tools.refinery.store.dse.propagation.PropagationAdapter;
diff --git a/subprojects/language-semantics/src/test/java/tools/refinery/language/semantics/model/ModelGenerationTest.java b/subprojects/language-semantics/src/test/java/tools/refinery/language/semantics/ModelGenerationTest.java
index c8a79c37..899e3cb3 100644
--- a/subprojects/language-semantics/src/test/java/tools/refinery/language/semantics/model/ModelGenerationTest.java
+++ b/subprojects/language-semantics/src/test/java/tools/refinery/language/semantics/ModelGenerationTest.java
@@ -3,7 +3,7 @@
3 * 3 *
4 * SPDX-License-Identifier: EPL-2.0 4 * SPDX-License-Identifier: EPL-2.0
5 */ 5 */
6package tools.refinery.language.semantics.model; 6package tools.refinery.language.semantics;
7 7
8import com.google.inject.Inject; 8import com.google.inject.Inject;
9import org.eclipse.xtext.testing.InjectWith; 9import org.eclipse.xtext.testing.InjectWith;
diff --git a/subprojects/language-semantics/src/test/java/tools/refinery/language/semantics/model/internal/DecisionTreeTests.java b/subprojects/language-semantics/src/test/java/tools/refinery/language/semantics/internal/DecisionTreeTests.java
index 5d039308..2320de2c 100644
--- a/subprojects/language-semantics/src/test/java/tools/refinery/language/semantics/model/internal/DecisionTreeTests.java
+++ b/subprojects/language-semantics/src/test/java/tools/refinery/language/semantics/internal/DecisionTreeTests.java
@@ -3,7 +3,7 @@
3 * 3 *
4 * SPDX-License-Identifier: EPL-2.0 4 * SPDX-License-Identifier: EPL-2.0
5 */ 5 */
6package tools.refinery.language.semantics.model.internal; 6package tools.refinery.language.semantics.internal;
7 7
8import org.junit.jupiter.api.Test; 8import org.junit.jupiter.api.Test;
9import tools.refinery.store.representation.TruthValue; 9import tools.refinery.store.representation.TruthValue;
diff --git a/subprojects/language-web/build.gradle.kts b/subprojects/language-web/build.gradle.kts
index 2370794d..c3a0b7e9 100644
--- a/subprojects/language-web/build.gradle.kts
+++ b/subprojects/language-web/build.gradle.kts
@@ -15,11 +15,9 @@ val webapp: Configuration by configurations.creating {
15} 15}
16 16
17dependencies { 17dependencies {
18 implementation(project(":refinery-generator"))
18 implementation(project(":refinery-language")) 19 implementation(project(":refinery-language"))
19 implementation(project(":refinery-language-ide")) 20 implementation(project(":refinery-language-ide"))
20 implementation(project(":refinery-language-semantics"))
21 implementation(project(":refinery-store-query-interpreter"))
22 implementation(project(":refinery-store-reasoning-scope"))
23 implementation(libs.gson) 21 implementation(libs.gson)
24 implementation(libs.jetty.server) 22 implementation(libs.jetty.server)
25 implementation(libs.jetty.servlet) 23 implementation(libs.jetty.servlet)
diff --git a/subprojects/language-web/src/main/java/tools/refinery/language/web/generator/ModelGenerationSuccessResult.java b/subprojects/language-web/src/main/java/tools/refinery/language/web/generator/ModelGenerationSuccessResult.java
index 21be4e08..0abe116e 100644
--- a/subprojects/language-web/src/main/java/tools/refinery/language/web/generator/ModelGenerationSuccessResult.java
+++ b/subprojects/language-web/src/main/java/tools/refinery/language/web/generator/ModelGenerationSuccessResult.java
@@ -6,8 +6,8 @@
6package tools.refinery.language.web.generator; 6package tools.refinery.language.web.generator;
7 7
8import com.google.gson.JsonObject; 8import com.google.gson.JsonObject;
9import tools.refinery.language.semantics.metadata.NodeMetadata; 9import tools.refinery.language.web.semantics.metadata.NodeMetadata;
10import tools.refinery.language.semantics.metadata.RelationMetadata; 10import tools.refinery.language.web.semantics.metadata.RelationMetadata;
11 11
12import java.util.List; 12import java.util.List;
13import java.util.UUID; 13import java.util.UUID;
diff --git a/subprojects/language-web/src/main/java/tools/refinery/language/web/generator/ModelGenerationWorker.java b/subprojects/language-web/src/main/java/tools/refinery/language/web/generator/ModelGenerationWorker.java
index 1fce10a4..a3b6ca82 100644
--- a/subprojects/language-web/src/main/java/tools/refinery/language/web/generator/ModelGenerationWorker.java
+++ b/subprojects/language-web/src/main/java/tools/refinery/language/web/generator/ModelGenerationWorker.java
@@ -6,36 +6,20 @@
6package tools.refinery.language.web.generator; 6package tools.refinery.language.web.generator;
7 7
8import com.google.inject.Inject; 8import com.google.inject.Inject;
9import com.google.inject.Provider;
10import org.eclipse.emf.common.util.URI;
11import org.eclipse.xtext.diagnostics.Severity;
12import org.eclipse.xtext.resource.IResourceFactory;
13import org.eclipse.xtext.resource.XtextResourceSet;
14import org.eclipse.xtext.service.OperationCanceledManager; 9import org.eclipse.xtext.service.OperationCanceledManager;
15import org.eclipse.xtext.util.LazyStringInputStream;
16import org.eclipse.xtext.validation.CheckMode;
17import org.eclipse.xtext.validation.IResourceValidator;
18import org.slf4j.Logger; 10import org.slf4j.Logger;
19import org.slf4j.LoggerFactory; 11import org.slf4j.LoggerFactory;
20import tools.refinery.language.model.problem.Problem; 12import tools.refinery.generator.ModelGenerator;
21import tools.refinery.language.semantics.metadata.MetadataCreator; 13import tools.refinery.generator.ModelGeneratorFactory;
22import tools.refinery.language.semantics.model.ModelInitializer; 14import tools.refinery.language.web.semantics.metadata.MetadataCreator;
15import tools.refinery.generator.ProblemLoader;
16import tools.refinery.generator.ValidationErrorsException;
23import tools.refinery.language.web.semantics.PartialInterpretation2Json; 17import tools.refinery.language.web.semantics.PartialInterpretation2Json;
24import tools.refinery.language.web.xtext.server.ThreadPoolExecutorServiceProvider; 18import tools.refinery.language.web.xtext.server.ThreadPoolExecutorServiceProvider;
25import tools.refinery.language.web.xtext.server.push.PushWebDocument; 19import tools.refinery.language.web.xtext.server.push.PushWebDocument;
26import tools.refinery.store.dse.propagation.PropagationAdapter;
27import tools.refinery.store.dse.strategy.BestFirstStoreManager;
28import tools.refinery.store.dse.transition.DesignSpaceExplorationAdapter;
29import tools.refinery.store.model.ModelStore;
30import tools.refinery.store.query.interpreter.QueryInterpreterAdapter;
31import tools.refinery.store.reasoning.ReasoningAdapter;
32import tools.refinery.store.reasoning.ReasoningStoreAdapter;
33import tools.refinery.store.reasoning.literal.Concreteness;
34import tools.refinery.store.statecoding.StateCoderAdapter;
35import tools.refinery.store.util.CancellationToken; 20import tools.refinery.store.util.CancellationToken;
36 21
37import java.io.IOException; 22import java.io.IOException;
38import java.util.Map;
39import java.util.UUID; 23import java.util.UUID;
40import java.util.concurrent.*; 24import java.util.concurrent.*;
41 25
@@ -56,16 +40,10 @@ public class ModelGenerationWorker implements Runnable {
56 private OperationCanceledManager operationCanceledManager; 40 private OperationCanceledManager operationCanceledManager;
57 41
58 @Inject 42 @Inject
59 private Provider<XtextResourceSet> resourceSetProvider; 43 private ProblemLoader problemLoader;
60 44
61 @Inject 45 @Inject
62 private IResourceFactory resourceFactory; 46 private ModelGeneratorFactory generatorFactory;
63
64 @Inject
65 private IResourceValidator resourceValidator;
66
67 @Inject
68 private ModelInitializer initializer;
69 47
70 @Inject 48 @Inject
71 private MetadataCreator metadataCreator; 49 private MetadataCreator metadataCreator;
@@ -157,57 +135,30 @@ public class ModelGenerationWorker implements Runnable {
157 135
158 public ModelGenerationResult doRun() throws IOException { 136 public ModelGenerationResult doRun() throws IOException {
159 cancellationToken.checkCancelled(); 137 cancellationToken.checkCancelled();
160 var resourceSet = resourceSetProvider.get(); 138 var problem = problemLoader.cancellationToken(cancellationToken).loadString(text);
161 var uri = URI.createURI("__synthetic_" + uuid + ".problem"); 139 ModelGenerator generator;
162 var resource = resourceFactory.createResource(uri); 140 try {
163 resourceSet.getResources().add(resource); 141 generator = generatorFactory.cancellationToken(cancellationToken).createGenerator(problem);
164 var inputStream = new LazyStringInputStream(text); 142 } catch (ValidationErrorsException e) {
165 resource.load(inputStream, Map.of()); 143 var errors = e.getErrors();
166 cancellationToken.checkCancelled(); 144 if (errors != null && !errors.isEmpty()) {
167 var issues = resourceValidator.validate(resource, CheckMode.ALL, () -> cancelled || Thread.interrupted()); 145 return new ModelGenerationErrorResult(uuid, "Validation error: " + errors.get(0).getMessage());
168 cancellationToken.checkCancelled();
169 for (var issue : issues) {
170 if (issue.getSeverity() == Severity.ERROR) {
171 return new ModelGenerationErrorResult(uuid, "Validation error: " + issue.getMessage());
172 } 146 }
147 throw e;
173 } 148 }
174 if (resource.getContents().isEmpty() || !(resource.getContents().get(0) instanceof Problem problem)) {
175 return new ModelGenerationErrorResult(uuid, "Model generation problem not found");
176 }
177 cancellationToken.checkCancelled();
178 var storeBuilder = ModelStore.builder()
179 .cancellationToken(cancellationToken)
180 .with(QueryInterpreterAdapter.builder())
181 .with(PropagationAdapter.builder())
182 .with(StateCoderAdapter.builder())
183 .with(DesignSpaceExplorationAdapter.builder())
184 .with(ReasoningAdapter.builder()
185 .requiredInterpretations(Concreteness.CANDIDATE));
186 var modelSeed = initializer.createModel(problem, storeBuilder);
187 var store = storeBuilder.build();
188 cancellationToken.checkCancelled();
189 var model = store.getAdapter(ReasoningStoreAdapter.class).createInitialModel(modelSeed);
190 var initialVersion = model.commit();
191 cancellationToken.checkCancelled();
192 notifyResult(new ModelGenerationStatusResult(uuid, "Generating model")); 149 notifyResult(new ModelGenerationStatusResult(uuid, "Generating model"));
193 var bestFirst = new BestFirstStoreManager(store, 1); 150 generator.setRandomSeed(randomSeed);
194 bestFirst.startExploration(initialVersion, randomSeed); 151 if (!generator.tryGenerate()) {
195 cancellationToken.checkCancelled();
196 var solutionStore = bestFirst.getSolutionStore();
197 if (solutionStore.getSolutions().isEmpty()) {
198 return new ModelGenerationErrorResult(uuid, "Problem is unsatisfiable"); 152 return new ModelGenerationErrorResult(uuid, "Problem is unsatisfiable");
199 } 153 }
200 notifyResult(new ModelGenerationStatusResult(uuid, "Saving generated model")); 154 notifyResult(new ModelGenerationStatusResult(uuid, "Saving generated model"));
201 model.restore(solutionStore.getSolutions().get(0).version());
202 cancellationToken.checkCancelled(); 155 cancellationToken.checkCancelled();
203 metadataCreator.setInitializer(initializer); 156 metadataCreator.setProblemTrace(generator.getProblemTrace());
204 var nodesMetadata = metadataCreator.getNodesMetadata(model.getAdapter(ReasoningAdapter.class).getNodeCount(), 157 var nodesMetadata = metadataCreator.getNodesMetadata(generator.getModel(), false);
205 false);
206 cancellationToken.checkCancelled(); 158 cancellationToken.checkCancelled();
207 var relationsMetadata = metadataCreator.getRelationsMetadata(); 159 var relationsMetadata = metadataCreator.getRelationsMetadata();
208 cancellationToken.checkCancelled(); 160 cancellationToken.checkCancelled();
209 var partialInterpretation = partialInterpretation2Json.getPartialInterpretation(initializer, model, 161 var partialInterpretation = partialInterpretation2Json.getPartialInterpretation(generator, cancellationToken);
210 Concreteness.CANDIDATE, cancellationToken);
211 return new ModelGenerationSuccessResult(uuid, nodesMetadata, relationsMetadata, partialInterpretation); 162 return new ModelGenerationSuccessResult(uuid, nodesMetadata, relationsMetadata, partialInterpretation);
212 } 163 }
213 164
diff --git a/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/PartialInterpretation2Json.java b/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/PartialInterpretation2Json.java
index 5d5da8fe..efe04592 100644
--- a/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/PartialInterpretation2Json.java
+++ b/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/PartialInterpretation2Json.java
@@ -9,12 +9,10 @@ import com.google.gson.JsonArray;
9import com.google.gson.JsonObject; 9import com.google.gson.JsonObject;
10import com.google.inject.Inject; 10import com.google.inject.Inject;
11import com.google.inject.Singleton; 11import com.google.inject.Singleton;
12import tools.refinery.language.semantics.model.ModelInitializer; 12import tools.refinery.generator.ModelFacade;
13import tools.refinery.language.semantics.model.SemanticsUtils; 13import tools.refinery.language.semantics.SemanticsUtils;
14import tools.refinery.store.map.Cursor; 14import tools.refinery.store.map.Cursor;
15import tools.refinery.store.model.Model; 15import tools.refinery.store.model.Model;
16import tools.refinery.store.reasoning.ReasoningAdapter;
17import tools.refinery.store.reasoning.literal.Concreteness;
18import tools.refinery.store.reasoning.representation.PartialRelation; 16import tools.refinery.store.reasoning.representation.PartialRelation;
19import tools.refinery.store.reasoning.translator.multiobject.MultiObjectTranslator; 17import tools.refinery.store.reasoning.translator.multiobject.MultiObjectTranslator;
20import tools.refinery.store.tuple.Tuple; 18import tools.refinery.store.tuple.Tuple;
@@ -27,14 +25,13 @@ public class PartialInterpretation2Json {
27 @Inject 25 @Inject
28 private SemanticsUtils semanticsUtils; 26 private SemanticsUtils semanticsUtils;
29 27
30 public JsonObject getPartialInterpretation(ModelInitializer initializer, Model model, Concreteness concreteness, 28 public JsonObject getPartialInterpretation(ModelFacade facade, CancellationToken cancellationToken) {
31 CancellationToken cancellationToken) { 29 var model = facade.getModel();
32 var adapter = model.getAdapter(ReasoningAdapter.class);
33 var json = new JsonObject(); 30 var json = new JsonObject();
34 for (var entry : initializer.getRelationTrace().entrySet()) { 31 for (var entry : facade.getProblemTrace().getRelationTrace().entrySet()) {
35 var relation = entry.getKey(); 32 var relation = entry.getKey();
36 var partialSymbol = entry.getValue(); 33 var partialSymbol = entry.getValue();
37 var tuples = getTuplesJson(adapter, concreteness, partialSymbol); 34 var tuples = getTuplesJson(facade, partialSymbol);
38 var name = semanticsUtils.getName(relation).orElse(partialSymbol.name()); 35 var name = semanticsUtils.getName(relation).orElse(partialSymbol.name());
39 json.add(name, tuples); 36 json.add(name, tuples);
40 cancellationToken.checkCancelled(); 37 cancellationToken.checkCancelled();
@@ -43,9 +40,8 @@ public class PartialInterpretation2Json {
43 return json; 40 return json;
44 } 41 }
45 42
46 private static JsonArray getTuplesJson(ReasoningAdapter adapter, Concreteness concreteness, 43 private static JsonArray getTuplesJson(ModelFacade facade, PartialRelation partialSymbol) {
47 PartialRelation partialSymbol) { 44 var interpretation = facade.getPartialInterpretation(partialSymbol);
48 var interpretation = adapter.getPartialInterpretation(concreteness, partialSymbol);
49 var cursor = interpretation.getAll(); 45 var cursor = interpretation.getAll();
50 return getTuplesJson(cursor); 46 return getTuplesJson(cursor);
51 } 47 }
diff --git a/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/SemanticsSuccessResult.java b/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/SemanticsSuccessResult.java
index 350b0b2b..f26fa2b2 100644
--- a/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/SemanticsSuccessResult.java
+++ b/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/SemanticsSuccessResult.java
@@ -6,8 +6,8 @@
6package tools.refinery.language.web.semantics; 6package tools.refinery.language.web.semantics;
7 7
8import com.google.gson.JsonObject; 8import com.google.gson.JsonObject;
9import tools.refinery.language.semantics.metadata.NodeMetadata; 9import tools.refinery.language.web.semantics.metadata.NodeMetadata;
10import tools.refinery.language.semantics.metadata.RelationMetadata; 10import tools.refinery.language.web.semantics.metadata.RelationMetadata;
11 11
12import java.util.List; 12import java.util.List;
13 13
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 fb89bea6..44974869 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
@@ -15,16 +15,11 @@ import org.eclipse.xtext.validation.FeatureBasedDiagnostic;
15import org.eclipse.xtext.validation.IDiagnosticConverter; 15import org.eclipse.xtext.validation.IDiagnosticConverter;
16import org.eclipse.xtext.validation.Issue; 16import org.eclipse.xtext.validation.Issue;
17import org.eclipse.xtext.web.server.validation.ValidationResult; 17import org.eclipse.xtext.web.server.validation.ValidationResult;
18import tools.refinery.generator.ModelSemantics;
19import tools.refinery.generator.ModelSemanticsFactory;
18import tools.refinery.language.model.problem.Problem; 20import tools.refinery.language.model.problem.Problem;
19import tools.refinery.language.semantics.metadata.MetadataCreator; 21import tools.refinery.language.web.semantics.metadata.MetadataCreator;
20import tools.refinery.language.semantics.model.ModelInitializer; 22import tools.refinery.language.semantics.TracedException;
21import tools.refinery.language.semantics.model.TracedException;
22import tools.refinery.store.dse.propagation.PropagationAdapter;
23import tools.refinery.store.model.ModelStore;
24import tools.refinery.store.query.interpreter.QueryInterpreterAdapter;
25import tools.refinery.store.reasoning.ReasoningAdapter;
26import tools.refinery.store.reasoning.ReasoningStoreAdapter;
27import tools.refinery.store.reasoning.literal.Concreteness;
28import tools.refinery.store.reasoning.translator.TranslationException; 23import tools.refinery.store.reasoning.translator.TranslationException;
29import tools.refinery.store.util.CancellationToken; 24import tools.refinery.store.util.CancellationToken;
30 25
@@ -35,20 +30,20 @@ class SemanticsWorker implements Callable<SemanticsResult> {
35 private static final String DIAGNOSTIC_ID = "tools.refinery.language.semantics.SemanticError"; 30 private static final String DIAGNOSTIC_ID = "tools.refinery.language.semantics.SemanticError";
36 31
37 @Inject 32 @Inject
38 private PartialInterpretation2Json partialInterpretation2Json;
39
40 @Inject
41 private OperationCanceledManager operationCanceledManager; 33 private OperationCanceledManager operationCanceledManager;
42 34
43 @Inject 35 @Inject
44 private IDiagnosticConverter diagnosticConverter; 36 private IDiagnosticConverter diagnosticConverter;
45 37
46 @Inject 38 @Inject
47 private ModelInitializer initializer; 39 private ModelSemanticsFactory semanticsFactory;
48 40
49 @Inject 41 @Inject
50 private MetadataCreator metadataCreator; 42 private MetadataCreator metadataCreator;
51 43
44 @Inject
45 private PartialInterpretation2Json partialInterpretation2Json;
46
52 private Problem problem; 47 private Problem problem;
53 48
54 private CancellationToken cancellationToken; 49 private CancellationToken cancellationToken;
@@ -64,36 +59,26 @@ class SemanticsWorker implements Callable<SemanticsResult> {
64 59
65 @Override 60 @Override
66 public SemanticsResult call() { 61 public SemanticsResult call() {
67 var builder = ModelStore.builder()
68 .cancellationToken(cancellationToken)
69 .with(QueryInterpreterAdapter.builder())
70 .with(PropagationAdapter.builder())
71 .with(ReasoningAdapter.builder()
72 .requiredInterpretations(Concreteness.PARTIAL));
73 cancellationToken.checkCancelled(); 62 cancellationToken.checkCancelled();
63 ModelSemantics semantics;
74 try { 64 try {
75 var modelSeed = initializer.createModel(problem, builder); 65 semantics = semanticsFactory.cancellationToken(cancellationToken).createSemantics(problem);
76 cancellationToken.checkCancelled();
77 metadataCreator.setInitializer(initializer);
78 cancellationToken.checkCancelled();
79 var nodesMetadata = metadataCreator.getNodesMetadata();
80 cancellationToken.checkCancelled();
81 var relationsMetadata = metadataCreator.getRelationsMetadata();
82 cancellationToken.checkCancelled();
83 var store = builder.build();
84 cancellationToken.checkCancelled();
85 var model = store.getAdapter(ReasoningStoreAdapter.class).createInitialModel(modelSeed);
86 cancellationToken.checkCancelled();
87 var partialInterpretation = partialInterpretation2Json.getPartialInterpretation(initializer, model,
88 Concreteness.PARTIAL, cancellationToken);
89
90 return new SemanticsSuccessResult(nodesMetadata, relationsMetadata, partialInterpretation);
91 } catch (TracedException e) {
92 return getTracedErrorResult(e.getSourceElement(), e.getMessage());
93 } catch (TranslationException e) { 66 } catch (TranslationException e) {
94 var sourceElement = initializer.getInverseTrace(e.getPartialSymbol()); 67 return new SemanticsInternalErrorResult(e.getMessage());
95 return getTracedErrorResult(sourceElement, e.getMessage()); 68 } catch (TracedException e) {
69 var cause = e.getCause();
70 // Suppress the type of the cause exception.
71 var message = cause == null ? e.getMessage() : cause.getMessage();
72 return getTracedErrorResult(e.getSourceElement(), message);
96 } 73 }
74 cancellationToken.checkCancelled();
75 metadataCreator.setProblemTrace(semantics.getProblemTrace());
76 var nodesMetadata = metadataCreator.getNodesMetadata(semantics.getModel(), true);
77 cancellationToken.checkCancelled();
78 var relationsMetadata = metadataCreator.getRelationsMetadata();
79 cancellationToken.checkCancelled();
80 var partialInterpretation = partialInterpretation2Json.getPartialInterpretation(semantics, cancellationToken);
81 return new SemanticsSuccessResult(nodesMetadata, relationsMetadata, partialInterpretation);
97 } 82 }
98 83
99 private SemanticsResult getTracedErrorResult(EObject sourceElement, String message) { 84 private SemanticsResult getTracedErrorResult(EObject sourceElement, String message) {
diff --git a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/metadata/BuiltInDetail.java b/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/BuiltInDetail.java
index 6f706069..27eb7ad7 100644
--- a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/metadata/BuiltInDetail.java
+++ b/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/BuiltInDetail.java
@@ -3,7 +3,7 @@
3 * 3 *
4 * SPDX-License-Identifier: EPL-2.0 4 * SPDX-License-Identifier: EPL-2.0
5 */ 5 */
6package tools.refinery.language.semantics.metadata; 6package tools.refinery.language.web.semantics.metadata;
7 7
8public record BuiltInDetail() implements RelationDetail { 8public record BuiltInDetail() implements RelationDetail {
9 public static final BuiltInDetail INSTANCE = new BuiltInDetail(); 9 public static final BuiltInDetail INSTANCE = new BuiltInDetail();
diff --git a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/metadata/ClassDetail.java b/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/ClassDetail.java
index 1d3190f5..42495950 100644
--- a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/metadata/ClassDetail.java
+++ b/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/ClassDetail.java
@@ -3,7 +3,7 @@
3 * 3 *
4 * SPDX-License-Identifier: EPL-2.0 4 * SPDX-License-Identifier: EPL-2.0
5 */ 5 */
6package tools.refinery.language.semantics.metadata; 6package tools.refinery.language.web.semantics.metadata;
7 7
8public record ClassDetail(boolean abstractClass) implements RelationDetail { 8public record ClassDetail(boolean abstractClass) implements RelationDetail {
9 public static final ClassDetail CONCRETE_CLASS = new ClassDetail(false); 9 public static final ClassDetail CONCRETE_CLASS = new ClassDetail(false);
diff --git a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/metadata/Metadata.java b/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/Metadata.java
index d2dcb43a..5e1fac05 100644
--- a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/metadata/Metadata.java
+++ b/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/Metadata.java
@@ -3,7 +3,7 @@
3 * 3 *
4 * SPDX-License-Identifier: EPL-2.0 4 * SPDX-License-Identifier: EPL-2.0
5 */ 5 */
6package tools.refinery.language.semantics.metadata; 6package tools.refinery.language.web.semantics.metadata;
7 7
8public sealed interface Metadata permits NodeMetadata, RelationMetadata { 8public sealed interface Metadata permits NodeMetadata, RelationMetadata {
9 String name(); 9 String name();
diff --git a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/metadata/MetadataCreator.java b/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/MetadataCreator.java
index 3694f5f4..3fbc5d2d 100644
--- a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/metadata/MetadataCreator.java
+++ b/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/MetadataCreator.java
@@ -3,7 +3,7 @@
3 * 3 *
4 * SPDX-License-Identifier: EPL-2.0 4 * SPDX-License-Identifier: EPL-2.0
5 */ 5 */
6package tools.refinery.language.semantics.metadata; 6package tools.refinery.language.web.semantics.metadata;
7 7
8import com.google.inject.Inject; 8import com.google.inject.Inject;
9import org.eclipse.emf.ecore.EObject; 9import org.eclipse.emf.ecore.EObject;
@@ -13,12 +13,17 @@ import org.eclipse.xtext.naming.QualifiedName;
13import org.eclipse.xtext.scoping.IScope; 13import org.eclipse.xtext.scoping.IScope;
14import org.eclipse.xtext.scoping.IScopeProvider; 14import org.eclipse.xtext.scoping.IScopeProvider;
15import tools.refinery.language.model.problem.*; 15import tools.refinery.language.model.problem.*;
16import tools.refinery.language.semantics.model.ModelInitializer; 16import tools.refinery.language.semantics.ProblemTrace;
17import tools.refinery.language.semantics.model.TracedException; 17import tools.refinery.language.semantics.TracedException;
18import tools.refinery.language.utils.ProblemUtil; 18import tools.refinery.language.utils.ProblemUtil;
19import tools.refinery.store.model.Model;
20import tools.refinery.store.reasoning.ReasoningAdapter;
19import tools.refinery.store.reasoning.representation.PartialRelation; 21import tools.refinery.store.reasoning.representation.PartialRelation;
20 22
21import java.util.*; 23import java.util.ArrayList;
24import java.util.Collections;
25import java.util.Comparator;
26import java.util.List;
22 27
23public class MetadataCreator { 28public class MetadataCreator {
24 @Inject 29 @Inject
@@ -30,18 +35,18 @@ public class MetadataCreator {
30 @Inject 35 @Inject
31 private IQualifiedNameConverter qualifiedNameConverter; 36 private IQualifiedNameConverter qualifiedNameConverter;
32 37
33 private ModelInitializer initializer; 38 private ProblemTrace problemTrace;
34 39
35 private IScope nodeScope; 40 private IScope nodeScope;
36 41
37 private IScope relationScope; 42 private IScope relationScope;
38 43
39 public void setInitializer(ModelInitializer initializer) { 44 public void setProblemTrace(ProblemTrace problemTrace) {
40 if (initializer == null) { 45 if (this.problemTrace != null) {
41 throw new IllegalArgumentException("Initializer was already set"); 46 throw new IllegalArgumentException("Problem trace was already set");
42 } 47 }
43 this.initializer = initializer; 48 this.problemTrace = problemTrace;
44 var problem = initializer.getProblem(); 49 var problem = problemTrace.getProblem();
45 nodeScope = scopeProvider.getScope(problem, ProblemPackage.Literals.NODE_ASSERTION_ARGUMENT__NODE); 50 nodeScope = scopeProvider.getScope(problem, ProblemPackage.Literals.NODE_ASSERTION_ARGUMENT__NODE);
46 relationScope = scopeProvider.getScope(problem, ProblemPackage.Literals.ASSERTION__RELATION); 51 relationScope = scopeProvider.getScope(problem, ProblemPackage.Literals.ASSERTION__RELATION);
47 } 52 }
@@ -50,13 +55,11 @@ public class MetadataCreator {
50 return "::" + nodeId; 55 return "::" + nodeId;
51 } 56 }
52 57
53 public List<NodeMetadata> getNodesMetadata() { 58 public List<NodeMetadata> getNodesMetadata(Model model, boolean preserveNewNodes) {
54 return getNodesMetadata(initializer.getNodeCount(), true); 59 int nodeCount = model.getAdapter(ReasoningAdapter.class).getNodeCount();
55 } 60 var nodeTrace = problemTrace.getNodeTrace();
56 61 var nodes = new NodeMetadata[Math.max(nodeTrace.size(), nodeCount)];
57 public List<NodeMetadata> getNodesMetadata(int nodeCount, boolean preserveNewNodes) { 62 for (var entry : nodeTrace.keyValuesView()) {
58 var nodes = new NodeMetadata[Math.max(initializer.getNodeCount(), nodeCount)];
59 for (var entry : initializer.getNodeTrace().keyValuesView()) {
60 var node = entry.getOne(); 63 var node = entry.getOne();
61 var id = entry.getTwo(); 64 var id = entry.getTwo();
62 nodes[id] = getNodeMetadata(id, node, preserveNewNodes); 65 nodes[id] = getNodeMetadata(id, node, preserveNewNodes);
@@ -95,7 +98,7 @@ public class MetadataCreator {
95 } 98 }
96 99
97 public List<RelationMetadata> getRelationsMetadata() { 100 public List<RelationMetadata> getRelationsMetadata() {
98 var relationTrace = initializer.getRelationTrace(); 101 var relationTrace = problemTrace.getRelationTrace();
99 var relations = new ArrayList<RelationMetadata>(relationTrace.size()); 102 var relations = new ArrayList<RelationMetadata>(relationTrace.size());
100 for (var entry : relationTrace.entrySet()) { 103 for (var entry : relationTrace.entrySet()) {
101 var relation = entry.getKey(); 104 var relation = entry.getKey();
@@ -142,7 +145,7 @@ public class MetadataCreator {
142 } 145 }
143 146
144 private RelationDetail getReferenceDetail(PartialRelation partialRelation) { 147 private RelationDetail getReferenceDetail(PartialRelation partialRelation) {
145 var metamodel = initializer.getMetamodel(); 148 var metamodel = problemTrace.getMetamodel();
146 var opposite = metamodel.oppositeReferences().get(partialRelation); 149 var opposite = metamodel.oppositeReferences().get(partialRelation);
147 if (opposite == null) { 150 if (opposite == null) {
148 boolean isContainment = metamodel.containmentHierarchy().containsKey(partialRelation); 151 boolean isContainment = metamodel.containmentHierarchy().containsKey(partialRelation);
diff --git a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/metadata/NodeKind.java b/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/NodeKind.java
index 01f0cd09..fa863bc2 100644
--- a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/metadata/NodeKind.java
+++ b/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/NodeKind.java
@@ -3,7 +3,7 @@
3 * 3 *
4 * SPDX-License-Identifier: EPL-2.0 4 * SPDX-License-Identifier: EPL-2.0
5 */ 5 */
6package tools.refinery.language.semantics.metadata; 6package tools.refinery.language.web.semantics.metadata;
7 7
8public enum NodeKind { 8public enum NodeKind {
9 IMPLICIT, 9 IMPLICIT,
diff --git a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/metadata/NodeMetadata.java b/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/NodeMetadata.java
index 812952c0..5da28acf 100644
--- a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/metadata/NodeMetadata.java
+++ b/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/NodeMetadata.java
@@ -3,7 +3,7 @@
3 * 3 *
4 * SPDX-License-Identifier: EPL-2.0 4 * SPDX-License-Identifier: EPL-2.0
5 */ 5 */
6package tools.refinery.language.semantics.metadata; 6package tools.refinery.language.web.semantics.metadata;
7 7
8public record NodeMetadata(String name, String simpleName, NodeKind kind) implements Metadata { 8public record NodeMetadata(String name, String simpleName, NodeKind kind) implements Metadata {
9} 9}
diff --git a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/metadata/OppositeReferenceDetail.java b/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/OppositeReferenceDetail.java
index 26d7461c..98e7fec8 100644
--- a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/metadata/OppositeReferenceDetail.java
+++ b/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/OppositeReferenceDetail.java
@@ -3,7 +3,7 @@
3 * 3 *
4 * SPDX-License-Identifier: EPL-2.0 4 * SPDX-License-Identifier: EPL-2.0
5 */ 5 */
6package tools.refinery.language.semantics.metadata; 6package tools.refinery.language.web.semantics.metadata;
7 7
8public record OppositeReferenceDetail(boolean container, String opposite) implements RelationDetail { 8public record OppositeReferenceDetail(boolean container, String opposite) implements RelationDetail {
9} 9}
diff --git a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/metadata/PredicateDetail.java b/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/PredicateDetail.java
index ca397eca..d4ac4b65 100644
--- a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/metadata/PredicateDetail.java
+++ b/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/PredicateDetail.java
@@ -3,7 +3,7 @@
3 * 3 *
4 * SPDX-License-Identifier: EPL-2.0 4 * SPDX-License-Identifier: EPL-2.0
5 */ 5 */
6package tools.refinery.language.semantics.metadata; 6package tools.refinery.language.web.semantics.metadata;
7 7
8public record PredicateDetail(boolean error) implements RelationDetail { 8public record PredicateDetail(boolean error) implements RelationDetail {
9 public static final PredicateDetail PREDICATE = new PredicateDetail(false); 9 public static final PredicateDetail PREDICATE = new PredicateDetail(false);
diff --git a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/metadata/ReferenceDetail.java b/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/ReferenceDetail.java
index 36771566..42799417 100644
--- a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/metadata/ReferenceDetail.java
+++ b/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/ReferenceDetail.java
@@ -3,7 +3,7 @@
3 * 3 *
4 * SPDX-License-Identifier: EPL-2.0 4 * SPDX-License-Identifier: EPL-2.0
5 */ 5 */
6package tools.refinery.language.semantics.metadata; 6package tools.refinery.language.web.semantics.metadata;
7 7
8public record ReferenceDetail(boolean containment) implements RelationDetail { 8public record ReferenceDetail(boolean containment) implements RelationDetail {
9 public static final ReferenceDetail CROSS_REFERENCE = new ReferenceDetail(false); 9 public static final ReferenceDetail CROSS_REFERENCE = new ReferenceDetail(false);
diff --git a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/metadata/RelationDetail.java b/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/RelationDetail.java
index 105179fd..bbe563cd 100644
--- a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/metadata/RelationDetail.java
+++ b/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/RelationDetail.java
@@ -3,7 +3,7 @@
3 * 3 *
4 * SPDX-License-Identifier: EPL-2.0 4 * SPDX-License-Identifier: EPL-2.0
5 */ 5 */
6package tools.refinery.language.semantics.metadata; 6package tools.refinery.language.web.semantics.metadata;
7 7
8public sealed interface RelationDetail permits ClassDetail, ReferenceDetail, PredicateDetail, OppositeReferenceDetail, 8public sealed interface RelationDetail permits ClassDetail, ReferenceDetail, PredicateDetail, OppositeReferenceDetail,
9 BuiltInDetail { 9 BuiltInDetail {
diff --git a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/metadata/RelationMetadata.java b/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/RelationMetadata.java
index 5abcc253..e5d3a091 100644
--- a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/metadata/RelationMetadata.java
+++ b/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/RelationMetadata.java
@@ -3,7 +3,7 @@
3 * 3 *
4 * SPDX-License-Identifier: EPL-2.0 4 * SPDX-License-Identifier: EPL-2.0
5 */ 5 */
6package tools.refinery.language.semantics.metadata; 6package tools.refinery.language.web.semantics.metadata;
7 7
8public record RelationMetadata(String name, String simpleName, int arity, RelationDetail detail) implements Metadata { 8public record RelationMetadata(String name, String simpleName, int arity, RelationDetail detail) implements Metadata {
9} 9}
diff --git a/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/servlet/XtextWebSocket.java b/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/servlet/XtextWebSocket.java
index 1fde1be5..818bd80e 100644
--- a/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/servlet/XtextWebSocket.java
+++ b/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/servlet/XtextWebSocket.java
@@ -17,7 +17,7 @@ import org.eclipse.xtext.resource.IResourceServiceProvider;
17import org.eclipse.xtext.web.server.ISession; 17import org.eclipse.xtext.web.server.ISession;
18import org.slf4j.Logger; 18import org.slf4j.Logger;
19import org.slf4j.LoggerFactory; 19import org.slf4j.LoggerFactory;
20import tools.refinery.language.semantics.metadata.*; 20import tools.refinery.language.web.semantics.metadata.*;
21import tools.refinery.language.web.xtext.server.ResponseHandler; 21import tools.refinery.language.web.xtext.server.ResponseHandler;
22import tools.refinery.language.web.xtext.server.ResponseHandlerException; 22import tools.refinery.language.web.xtext.server.ResponseHandlerException;
23import tools.refinery.language.web.xtext.server.TransactionExecutor; 23import tools.refinery.language.web.xtext.server.TransactionExecutor;