diff options
Diffstat (limited to 'subprojects/language-web')
17 files changed, 368 insertions, 44 deletions
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 @@ | |||
6 | package tools.refinery.language.web.generator; | 6 | package tools.refinery.language.web.generator; |
7 | 7 | ||
8 | import com.google.gson.JsonObject; | 8 | import com.google.gson.JsonObject; |
9 | import tools.refinery.language.semantics.metadata.NodeMetadata; | 9 | import tools.refinery.language.web.semantics.metadata.NodeMetadata; |
10 | import tools.refinery.language.semantics.metadata.RelationMetadata; | 10 | import tools.refinery.language.web.semantics.metadata.RelationMetadata; |
11 | 11 | ||
12 | import java.util.List; | 12 | import java.util.List; |
13 | import java.util.UUID; | 13 | import 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 7b4f957c..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 | |||
@@ -9,12 +9,14 @@ import com.google.inject.Inject; | |||
9 | import org.eclipse.xtext.service.OperationCanceledManager; | 9 | import org.eclipse.xtext.service.OperationCanceledManager; |
10 | import org.slf4j.Logger; | 10 | import org.slf4j.Logger; |
11 | import org.slf4j.LoggerFactory; | 11 | import org.slf4j.LoggerFactory; |
12 | import tools.refinery.generator.ModelGeneratorBuilder; | 12 | import tools.refinery.generator.ModelGenerator; |
13 | import tools.refinery.generator.ModelGeneratorFactory; | ||
14 | import tools.refinery.language.web.semantics.metadata.MetadataCreator; | ||
15 | import tools.refinery.generator.ProblemLoader; | ||
13 | import tools.refinery.generator.ValidationErrorsException; | 16 | import tools.refinery.generator.ValidationErrorsException; |
14 | import tools.refinery.language.web.semantics.PartialInterpretation2Json; | 17 | import tools.refinery.language.web.semantics.PartialInterpretation2Json; |
15 | import tools.refinery.language.web.xtext.server.ThreadPoolExecutorServiceProvider; | 18 | import tools.refinery.language.web.xtext.server.ThreadPoolExecutorServiceProvider; |
16 | import tools.refinery.language.web.xtext.server.push.PushWebDocument; | 19 | import tools.refinery.language.web.xtext.server.push.PushWebDocument; |
17 | import tools.refinery.store.reasoning.literal.Concreteness; | ||
18 | import tools.refinery.store.util.CancellationToken; | 20 | import tools.refinery.store.util.CancellationToken; |
19 | 21 | ||
20 | import java.io.IOException; | 22 | import java.io.IOException; |
@@ -38,7 +40,13 @@ public class ModelGenerationWorker implements Runnable { | |||
38 | private OperationCanceledManager operationCanceledManager; | 40 | private OperationCanceledManager operationCanceledManager; |
39 | 41 | ||
40 | @Inject | 42 | @Inject |
41 | private ModelGeneratorBuilder generatorBuilder; | 43 | private ProblemLoader problemLoader; |
44 | |||
45 | @Inject | ||
46 | private ModelGeneratorFactory generatorFactory; | ||
47 | |||
48 | @Inject | ||
49 | private MetadataCreator metadataCreator; | ||
42 | 50 | ||
43 | @Inject | 51 | @Inject |
44 | private PartialInterpretation2Json partialInterpretation2Json; | 52 | private PartialInterpretation2Json partialInterpretation2Json; |
@@ -127,9 +135,10 @@ public class ModelGenerationWorker implements Runnable { | |||
127 | 135 | ||
128 | public ModelGenerationResult doRun() throws IOException { | 136 | public ModelGenerationResult doRun() throws IOException { |
129 | cancellationToken.checkCancelled(); | 137 | cancellationToken.checkCancelled(); |
138 | var problem = problemLoader.cancellationToken(cancellationToken).loadString(text); | ||
139 | ModelGenerator generator; | ||
130 | try { | 140 | try { |
131 | generatorBuilder.cancellationToken(cancellationToken); | 141 | generator = generatorFactory.cancellationToken(cancellationToken).createGenerator(problem); |
132 | generatorBuilder.fromString(text); | ||
133 | } catch (ValidationErrorsException e) { | 142 | } catch (ValidationErrorsException e) { |
134 | var errors = e.getErrors(); | 143 | var errors = e.getErrors(); |
135 | if (errors != null && !errors.isEmpty()) { | 144 | if (errors != null && !errors.isEmpty()) { |
@@ -137,20 +146,19 @@ public class ModelGenerationWorker implements Runnable { | |||
137 | } | 146 | } |
138 | throw e; | 147 | throw e; |
139 | } | 148 | } |
140 | var generator = generatorBuilder.build(); | ||
141 | notifyResult(new ModelGenerationStatusResult(uuid, "Generating model")); | 149 | notifyResult(new ModelGenerationStatusResult(uuid, "Generating model")); |
142 | generator.setRandomSeed(randomSeed); | 150 | generator.setRandomSeed(randomSeed); |
143 | if (!generator.tryRun()) { | 151 | if (!generator.tryGenerate()) { |
144 | return new ModelGenerationErrorResult(uuid, "Problem is unsatisfiable"); | 152 | return new ModelGenerationErrorResult(uuid, "Problem is unsatisfiable"); |
145 | } | 153 | } |
146 | notifyResult(new ModelGenerationStatusResult(uuid, "Saving generated model")); | 154 | notifyResult(new ModelGenerationStatusResult(uuid, "Saving generated model")); |
147 | cancellationToken.checkCancelled(); | 155 | cancellationToken.checkCancelled(); |
148 | var nodesMetadata = generator.getNodesMetadata(); | 156 | metadataCreator.setProblemTrace(generator.getProblemTrace()); |
157 | var nodesMetadata = metadataCreator.getNodesMetadata(generator.getModel(), false); | ||
149 | cancellationToken.checkCancelled(); | 158 | cancellationToken.checkCancelled(); |
150 | var relationsMetadata = generator.getProblemTrace().getRelationsMetadata(); | 159 | var relationsMetadata = metadataCreator.getRelationsMetadata(); |
151 | cancellationToken.checkCancelled(); | 160 | cancellationToken.checkCancelled(); |
152 | var partialInterpretation = partialInterpretation2Json.getPartialInterpretation(generator, | 161 | var partialInterpretation = partialInterpretation2Json.getPartialInterpretation(generator, cancellationToken); |
153 | Concreteness.CANDIDATE, cancellationToken); | ||
154 | return new ModelGenerationSuccessResult(uuid, nodesMetadata, relationsMetadata, partialInterpretation); | 162 | return new ModelGenerationSuccessResult(uuid, nodesMetadata, relationsMetadata, partialInterpretation); |
155 | } | 163 | } |
156 | 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 7afed5c0..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; | |||
9 | import com.google.gson.JsonObject; | 9 | import com.google.gson.JsonObject; |
10 | import com.google.inject.Inject; | 10 | import com.google.inject.Inject; |
11 | import com.google.inject.Singleton; | 11 | import com.google.inject.Singleton; |
12 | import tools.refinery.generator.AbstractRefinery; | 12 | import tools.refinery.generator.ModelFacade; |
13 | import tools.refinery.language.semantics.model.SemanticsUtils; | 13 | import tools.refinery.language.semantics.SemanticsUtils; |
14 | import tools.refinery.store.map.Cursor; | 14 | import tools.refinery.store.map.Cursor; |
15 | import tools.refinery.store.model.Model; | 15 | import tools.refinery.store.model.Model; |
16 | import tools.refinery.store.reasoning.ReasoningAdapter; | ||
17 | import tools.refinery.store.reasoning.literal.Concreteness; | ||
18 | import tools.refinery.store.reasoning.representation.PartialRelation; | 16 | import tools.refinery.store.reasoning.representation.PartialRelation; |
19 | import tools.refinery.store.reasoning.translator.multiobject.MultiObjectTranslator; | 17 | import tools.refinery.store.reasoning.translator.multiobject.MultiObjectTranslator; |
20 | import tools.refinery.store.tuple.Tuple; | 18 | import tools.refinery.store.tuple.Tuple; |
@@ -27,15 +25,13 @@ public class PartialInterpretation2Json { | |||
27 | @Inject | 25 | @Inject |
28 | private SemanticsUtils semanticsUtils; | 26 | private SemanticsUtils semanticsUtils; |
29 | 27 | ||
30 | public JsonObject getPartialInterpretation(AbstractRefinery refinery, Concreteness concreteness, | 28 | public JsonObject getPartialInterpretation(ModelFacade facade, CancellationToken cancellationToken) { |
31 | CancellationToken cancellationToken) { | 29 | var model = facade.getModel(); |
32 | var model = refinery.getModel(); | ||
33 | var adapter = model.getAdapter(ReasoningAdapter.class); | ||
34 | var json = new JsonObject(); | 30 | var json = new JsonObject(); |
35 | for (var entry : refinery.getProblemTrace().getRelationTrace().entrySet()) { | 31 | for (var entry : facade.getProblemTrace().getRelationTrace().entrySet()) { |
36 | var relation = entry.getKey(); | 32 | var relation = entry.getKey(); |
37 | var partialSymbol = entry.getValue(); | 33 | var partialSymbol = entry.getValue(); |
38 | var tuples = getTuplesJson(adapter, concreteness, partialSymbol); | 34 | var tuples = getTuplesJson(facade, partialSymbol); |
39 | var name = semanticsUtils.getName(relation).orElse(partialSymbol.name()); | 35 | var name = semanticsUtils.getName(relation).orElse(partialSymbol.name()); |
40 | json.add(name, tuples); | 36 | json.add(name, tuples); |
41 | cancellationToken.checkCancelled(); | 37 | cancellationToken.checkCancelled(); |
@@ -44,9 +40,8 @@ public class PartialInterpretation2Json { | |||
44 | return json; | 40 | return json; |
45 | } | 41 | } |
46 | 42 | ||
47 | private static JsonArray getTuplesJson(ReasoningAdapter adapter, Concreteness concreteness, | 43 | private static JsonArray getTuplesJson(ModelFacade facade, PartialRelation partialSymbol) { |
48 | PartialRelation partialSymbol) { | 44 | var interpretation = facade.getPartialInterpretation(partialSymbol); |
49 | var interpretation = adapter.getPartialInterpretation(concreteness, partialSymbol); | ||
50 | var cursor = interpretation.getAll(); | 45 | var cursor = interpretation.getAll(); |
51 | return getTuplesJson(cursor); | 46 | return getTuplesJson(cursor); |
52 | } | 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 @@ | |||
6 | package tools.refinery.language.web.semantics; | 6 | package tools.refinery.language.web.semantics; |
7 | 7 | ||
8 | import com.google.gson.JsonObject; | 8 | import com.google.gson.JsonObject; |
9 | import tools.refinery.language.semantics.metadata.NodeMetadata; | 9 | import tools.refinery.language.web.semantics.metadata.NodeMetadata; |
10 | import tools.refinery.language.semantics.metadata.RelationMetadata; | 10 | import tools.refinery.language.web.semantics.metadata.RelationMetadata; |
11 | 11 | ||
12 | import java.util.List; | 12 | import 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 a8f16c84..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 | |||
@@ -16,10 +16,10 @@ import org.eclipse.xtext.validation.IDiagnosticConverter; | |||
16 | import org.eclipse.xtext.validation.Issue; | 16 | import org.eclipse.xtext.validation.Issue; |
17 | import org.eclipse.xtext.web.server.validation.ValidationResult; | 17 | import org.eclipse.xtext.web.server.validation.ValidationResult; |
18 | import tools.refinery.generator.ModelSemantics; | 18 | import tools.refinery.generator.ModelSemantics; |
19 | import tools.refinery.generator.ModelSemanticsBuilder; | 19 | import tools.refinery.generator.ModelSemanticsFactory; |
20 | import tools.refinery.language.model.problem.Problem; | 20 | import tools.refinery.language.model.problem.Problem; |
21 | import tools.refinery.language.semantics.model.TracedException; | 21 | import tools.refinery.language.web.semantics.metadata.MetadataCreator; |
22 | import tools.refinery.store.reasoning.literal.Concreteness; | 22 | import tools.refinery.language.semantics.TracedException; |
23 | import tools.refinery.store.reasoning.translator.TranslationException; | 23 | import tools.refinery.store.reasoning.translator.TranslationException; |
24 | import tools.refinery.store.util.CancellationToken; | 24 | import tools.refinery.store.util.CancellationToken; |
25 | 25 | ||
@@ -30,16 +30,19 @@ class SemanticsWorker implements Callable<SemanticsResult> { | |||
30 | private static final String DIAGNOSTIC_ID = "tools.refinery.language.semantics.SemanticError"; | 30 | private static final String DIAGNOSTIC_ID = "tools.refinery.language.semantics.SemanticError"; |
31 | 31 | ||
32 | @Inject | 32 | @Inject |
33 | private PartialInterpretation2Json partialInterpretation2Json; | ||
34 | |||
35 | @Inject | ||
36 | private OperationCanceledManager operationCanceledManager; | 33 | private OperationCanceledManager operationCanceledManager; |
37 | 34 | ||
38 | @Inject | 35 | @Inject |
39 | private IDiagnosticConverter diagnosticConverter; | 36 | private IDiagnosticConverter diagnosticConverter; |
40 | 37 | ||
41 | @Inject | 38 | @Inject |
42 | private ModelSemanticsBuilder semanticsBuilder; | 39 | private ModelSemanticsFactory semanticsFactory; |
40 | |||
41 | @Inject | ||
42 | private MetadataCreator metadataCreator; | ||
43 | |||
44 | @Inject | ||
45 | private PartialInterpretation2Json partialInterpretation2Json; | ||
43 | 46 | ||
44 | private Problem problem; | 47 | private Problem problem; |
45 | 48 | ||
@@ -56,13 +59,10 @@ class SemanticsWorker implements Callable<SemanticsResult> { | |||
56 | 59 | ||
57 | @Override | 60 | @Override |
58 | public SemanticsResult call() { | 61 | public SemanticsResult call() { |
59 | semanticsBuilder.cancellationToken(cancellationToken); | ||
60 | cancellationToken.checkCancelled(); | 62 | cancellationToken.checkCancelled(); |
61 | ModelSemantics semantics; | 63 | ModelSemantics semantics; |
62 | try { | 64 | try { |
63 | semanticsBuilder.problem(problem); | 65 | semantics = semanticsFactory.cancellationToken(cancellationToken).createSemantics(problem); |
64 | cancellationToken.checkCancelled(); | ||
65 | semantics = semanticsBuilder.build(); | ||
66 | } catch (TranslationException e) { | 66 | } catch (TranslationException e) { |
67 | return new SemanticsInternalErrorResult(e.getMessage()); | 67 | return new SemanticsInternalErrorResult(e.getMessage()); |
68 | } catch (TracedException e) { | 68 | } catch (TracedException e) { |
@@ -72,12 +72,12 @@ class SemanticsWorker implements Callable<SemanticsResult> { | |||
72 | return getTracedErrorResult(e.getSourceElement(), message); | 72 | return getTracedErrorResult(e.getSourceElement(), message); |
73 | } | 73 | } |
74 | cancellationToken.checkCancelled(); | 74 | cancellationToken.checkCancelled(); |
75 | var nodesMetadata = semantics.getNodesMetadata(); | 75 | metadataCreator.setProblemTrace(semantics.getProblemTrace()); |
76 | var nodesMetadata = metadataCreator.getNodesMetadata(semantics.getModel(), true); | ||
76 | cancellationToken.checkCancelled(); | 77 | cancellationToken.checkCancelled(); |
77 | var relationsMetadata = semantics.getProblemTrace().getRelationsMetadata(); | 78 | var relationsMetadata = metadataCreator.getRelationsMetadata(); |
78 | cancellationToken.checkCancelled(); | 79 | cancellationToken.checkCancelled(); |
79 | var partialInterpretation = partialInterpretation2Json.getPartialInterpretation(semantics, | 80 | var partialInterpretation = partialInterpretation2Json.getPartialInterpretation(semantics, cancellationToken); |
80 | Concreteness.PARTIAL, cancellationToken); | ||
81 | return new SemanticsSuccessResult(nodesMetadata, relationsMetadata, partialInterpretation); | 81 | return new SemanticsSuccessResult(nodesMetadata, relationsMetadata, partialInterpretation); |
82 | } | 82 | } |
83 | 83 | ||
diff --git a/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/BuiltInDetail.java b/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/BuiltInDetail.java new file mode 100644 index 00000000..27eb7ad7 --- /dev/null +++ b/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/BuiltInDetail.java | |||
@@ -0,0 +1,10 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.language.web.semantics.metadata; | ||
7 | |||
8 | public record BuiltInDetail() implements RelationDetail { | ||
9 | public static final BuiltInDetail INSTANCE = new BuiltInDetail(); | ||
10 | } | ||
diff --git a/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/ClassDetail.java b/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/ClassDetail.java new file mode 100644 index 00000000..42495950 --- /dev/null +++ b/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/ClassDetail.java | |||
@@ -0,0 +1,16 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.language.web.semantics.metadata; | ||
7 | |||
8 | public record ClassDetail(boolean abstractClass) implements RelationDetail { | ||
9 | public static final ClassDetail CONCRETE_CLASS = new ClassDetail(false); | ||
10 | |||
11 | public static final ClassDetail ABSTRACT_CLASS = new ClassDetail(true); | ||
12 | |||
13 | public static ClassDetail ofAbstractClass(boolean abstractClass) { | ||
14 | return abstractClass ? ABSTRACT_CLASS : CONCRETE_CLASS; | ||
15 | } | ||
16 | } | ||
diff --git a/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/Metadata.java b/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/Metadata.java new file mode 100644 index 00000000..5e1fac05 --- /dev/null +++ b/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/Metadata.java | |||
@@ -0,0 +1,12 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.language.web.semantics.metadata; | ||
7 | |||
8 | public sealed interface Metadata permits NodeMetadata, RelationMetadata { | ||
9 | String name(); | ||
10 | |||
11 | String simpleName(); | ||
12 | } | ||
diff --git a/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/MetadataCreator.java b/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/MetadataCreator.java new file mode 100644 index 00000000..3fbc5d2d --- /dev/null +++ b/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/MetadataCreator.java | |||
@@ -0,0 +1,202 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.language.web.semantics.metadata; | ||
7 | |||
8 | import com.google.inject.Inject; | ||
9 | import org.eclipse.emf.ecore.EObject; | ||
10 | import org.eclipse.xtext.naming.IQualifiedNameConverter; | ||
11 | import org.eclipse.xtext.naming.IQualifiedNameProvider; | ||
12 | import org.eclipse.xtext.naming.QualifiedName; | ||
13 | import org.eclipse.xtext.scoping.IScope; | ||
14 | import org.eclipse.xtext.scoping.IScopeProvider; | ||
15 | import tools.refinery.language.model.problem.*; | ||
16 | import tools.refinery.language.semantics.ProblemTrace; | ||
17 | import tools.refinery.language.semantics.TracedException; | ||
18 | import tools.refinery.language.utils.ProblemUtil; | ||
19 | import tools.refinery.store.model.Model; | ||
20 | import tools.refinery.store.reasoning.ReasoningAdapter; | ||
21 | import tools.refinery.store.reasoning.representation.PartialRelation; | ||
22 | |||
23 | import java.util.ArrayList; | ||
24 | import java.util.Collections; | ||
25 | import java.util.Comparator; | ||
26 | import java.util.List; | ||
27 | |||
28 | public class MetadataCreator { | ||
29 | @Inject | ||
30 | private IScopeProvider scopeProvider; | ||
31 | |||
32 | @Inject | ||
33 | private IQualifiedNameProvider qualifiedNameProvider; | ||
34 | |||
35 | @Inject | ||
36 | private IQualifiedNameConverter qualifiedNameConverter; | ||
37 | |||
38 | private ProblemTrace problemTrace; | ||
39 | |||
40 | private IScope nodeScope; | ||
41 | |||
42 | private IScope relationScope; | ||
43 | |||
44 | public void setProblemTrace(ProblemTrace problemTrace) { | ||
45 | if (this.problemTrace != null) { | ||
46 | throw new IllegalArgumentException("Problem trace was already set"); | ||
47 | } | ||
48 | this.problemTrace = problemTrace; | ||
49 | var problem = problemTrace.getProblem(); | ||
50 | nodeScope = scopeProvider.getScope(problem, ProblemPackage.Literals.NODE_ASSERTION_ARGUMENT__NODE); | ||
51 | relationScope = scopeProvider.getScope(problem, ProblemPackage.Literals.ASSERTION__RELATION); | ||
52 | } | ||
53 | |||
54 | public static String unnamedNode(int nodeId) { | ||
55 | return "::" + nodeId; | ||
56 | } | ||
57 | |||
58 | public List<NodeMetadata> getNodesMetadata(Model model, boolean preserveNewNodes) { | ||
59 | int nodeCount = model.getAdapter(ReasoningAdapter.class).getNodeCount(); | ||
60 | var nodeTrace = problemTrace.getNodeTrace(); | ||
61 | var nodes = new NodeMetadata[Math.max(nodeTrace.size(), nodeCount)]; | ||
62 | for (var entry : nodeTrace.keyValuesView()) { | ||
63 | var node = entry.getOne(); | ||
64 | var id = entry.getTwo(); | ||
65 | nodes[id] = getNodeMetadata(id, node, preserveNewNodes); | ||
66 | } | ||
67 | for (int i = 0; i < nodes.length; i++) { | ||
68 | if (nodes[i] == null) { | ||
69 | var nodeName = unnamedNode(i); | ||
70 | nodes[i] = new NodeMetadata(nodeName, nodeName, NodeKind.IMPLICIT); | ||
71 | } | ||
72 | } | ||
73 | return List.of(nodes); | ||
74 | } | ||
75 | |||
76 | private NodeMetadata getNodeMetadata(int nodeId, Node node, boolean preserveNewNodes) { | ||
77 | var kind = getNodeKind(node); | ||
78 | if (!preserveNewNodes && kind == NodeKind.NEW) { | ||
79 | var nodeName = unnamedNode(nodeId); | ||
80 | return new NodeMetadata(nodeName, nodeName, NodeKind.IMPLICIT); | ||
81 | } | ||
82 | var qualifiedName = getQualifiedName(node); | ||
83 | var simpleName = getSimpleName(node, qualifiedName, nodeScope); | ||
84 | return new NodeMetadata(qualifiedNameConverter.toString(qualifiedName), | ||
85 | qualifiedNameConverter.toString(simpleName), getNodeKind(node)); | ||
86 | } | ||
87 | |||
88 | private NodeKind getNodeKind(Node node) { | ||
89 | if (ProblemUtil.isImplicitNode(node)) { | ||
90 | return NodeKind.IMPLICIT; | ||
91 | } else if (ProblemUtil.isIndividualNode(node)) { | ||
92 | return NodeKind.INDIVIDUAL; | ||
93 | } else if (ProblemUtil.isNewNode(node)) { | ||
94 | return NodeKind.NEW; | ||
95 | } else { | ||
96 | throw new TracedException(node, "Unknown node type"); | ||
97 | } | ||
98 | } | ||
99 | |||
100 | public List<RelationMetadata> getRelationsMetadata() { | ||
101 | var relationTrace = problemTrace.getRelationTrace(); | ||
102 | var relations = new ArrayList<RelationMetadata>(relationTrace.size()); | ||
103 | for (var entry : relationTrace.entrySet()) { | ||
104 | var relation = entry.getKey(); | ||
105 | var partialRelation = entry.getValue(); | ||
106 | var metadata = getRelationMetadata(relation, partialRelation); | ||
107 | relations.add(metadata); | ||
108 | } | ||
109 | return Collections.unmodifiableList(relations); | ||
110 | } | ||
111 | |||
112 | private RelationMetadata getRelationMetadata(Relation relation, PartialRelation partialRelation) { | ||
113 | var qualifiedName = getQualifiedName(relation); | ||
114 | var qualifiedNameString = qualifiedNameConverter.toString(qualifiedName); | ||
115 | var simpleName = getSimpleName(relation, qualifiedName, relationScope); | ||
116 | var simpleNameString = qualifiedNameConverter.toString(simpleName); | ||
117 | var arity = partialRelation.arity(); | ||
118 | var detail = getRelationDetail(relation, partialRelation); | ||
119 | return new RelationMetadata(qualifiedNameString, simpleNameString, arity, detail); | ||
120 | } | ||
121 | |||
122 | private RelationDetail getRelationDetail(Relation relation, PartialRelation partialRelation) { | ||
123 | if (ProblemUtil.isBuiltIn(relation) && !ProblemUtil.isError(relation)) { | ||
124 | return getBuiltInDetail(); | ||
125 | } | ||
126 | if (relation instanceof ClassDeclaration classDeclaration) { | ||
127 | return getClassDetail(classDeclaration); | ||
128 | } else if (relation instanceof ReferenceDeclaration) { | ||
129 | return getReferenceDetail(partialRelation); | ||
130 | } else if (relation instanceof EnumDeclaration) { | ||
131 | return getEnumDetail(); | ||
132 | } else if (relation instanceof PredicateDefinition predicateDefinition) { | ||
133 | return getPredicateDetail(predicateDefinition); | ||
134 | } else { | ||
135 | throw new TracedException(relation, "Unknown relation"); | ||
136 | } | ||
137 | } | ||
138 | |||
139 | private RelationDetail getBuiltInDetail() { | ||
140 | return BuiltInDetail.INSTANCE; | ||
141 | } | ||
142 | |||
143 | private RelationDetail getClassDetail(ClassDeclaration classDeclaration) { | ||
144 | return ClassDetail.ofAbstractClass(classDeclaration.isAbstract()); | ||
145 | } | ||
146 | |||
147 | private RelationDetail getReferenceDetail(PartialRelation partialRelation) { | ||
148 | var metamodel = problemTrace.getMetamodel(); | ||
149 | var opposite = metamodel.oppositeReferences().get(partialRelation); | ||
150 | if (opposite == null) { | ||
151 | boolean isContainment = metamodel.containmentHierarchy().containsKey(partialRelation); | ||
152 | return ReferenceDetail.ofContainment(isContainment); | ||
153 | } else { | ||
154 | boolean isContainer = metamodel.containmentHierarchy().containsKey(opposite); | ||
155 | return new OppositeReferenceDetail(isContainer, opposite.name()); | ||
156 | } | ||
157 | } | ||
158 | |||
159 | private RelationDetail getEnumDetail() { | ||
160 | return ClassDetail.CONCRETE_CLASS; | ||
161 | } | ||
162 | |||
163 | private RelationDetail getPredicateDetail(PredicateDefinition predicate) { | ||
164 | return PredicateDetail.ofError(predicate.isError()); | ||
165 | } | ||
166 | |||
167 | private QualifiedName getQualifiedName(EObject eObject) { | ||
168 | var qualifiedName = qualifiedNameProvider.getFullyQualifiedName(eObject); | ||
169 | if (qualifiedName == null) { | ||
170 | throw new TracedException(eObject, "Unknown qualified name"); | ||
171 | } | ||
172 | return qualifiedName; | ||
173 | } | ||
174 | |||
175 | private QualifiedName getSimpleName(EObject eObject, QualifiedName qualifiedName, IScope scope) { | ||
176 | var descriptions = scope.getElements(eObject); | ||
177 | var names = new ArrayList<QualifiedName>(); | ||
178 | for (var description : descriptions) { | ||
179 | // {@code getQualifiedName()} will refer to the full name for objects that are loaded from the global | ||
180 | // scope, but {@code getName()} returns the qualified name that we set in | ||
181 | // {@code ProblemResourceDescriptionStrategy}. | ||
182 | names.add(description.getName()); | ||
183 | } | ||
184 | names.sort(Comparator.comparingInt(QualifiedName::getSegmentCount)); | ||
185 | for (var simpleName : names) { | ||
186 | if (names.contains(simpleName) && isUnique(scope, simpleName)) { | ||
187 | return simpleName; | ||
188 | } | ||
189 | } | ||
190 | throw new TracedException(eObject, "Ambiguous qualified name: " + | ||
191 | qualifiedNameConverter.toString(qualifiedName)); | ||
192 | } | ||
193 | |||
194 | private boolean isUnique(IScope scope, QualifiedName name) { | ||
195 | var iterator = scope.getElements(name).iterator(); | ||
196 | if (!iterator.hasNext()) { | ||
197 | return false; | ||
198 | } | ||
199 | iterator.next(); | ||
200 | return !iterator.hasNext(); | ||
201 | } | ||
202 | } | ||
diff --git a/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/NodeKind.java b/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/NodeKind.java new file mode 100644 index 00000000..fa863bc2 --- /dev/null +++ b/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/NodeKind.java | |||
@@ -0,0 +1,12 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.language.web.semantics.metadata; | ||
7 | |||
8 | public enum NodeKind { | ||
9 | IMPLICIT, | ||
10 | INDIVIDUAL, | ||
11 | NEW | ||
12 | } | ||
diff --git a/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/NodeMetadata.java b/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/NodeMetadata.java new file mode 100644 index 00000000..5da28acf --- /dev/null +++ b/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/NodeMetadata.java | |||
@@ -0,0 +1,9 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.language.web.semantics.metadata; | ||
7 | |||
8 | public record NodeMetadata(String name, String simpleName, NodeKind kind) implements Metadata { | ||
9 | } | ||
diff --git a/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/OppositeReferenceDetail.java b/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/OppositeReferenceDetail.java new file mode 100644 index 00000000..98e7fec8 --- /dev/null +++ b/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/OppositeReferenceDetail.java | |||
@@ -0,0 +1,9 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.language.web.semantics.metadata; | ||
7 | |||
8 | public record OppositeReferenceDetail(boolean container, String opposite) implements RelationDetail { | ||
9 | } | ||
diff --git a/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/PredicateDetail.java b/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/PredicateDetail.java new file mode 100644 index 00000000..d4ac4b65 --- /dev/null +++ b/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/PredicateDetail.java | |||
@@ -0,0 +1,16 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.language.web.semantics.metadata; | ||
7 | |||
8 | public record PredicateDetail(boolean error) implements RelationDetail { | ||
9 | public static final PredicateDetail PREDICATE = new PredicateDetail(false); | ||
10 | |||
11 | public static final PredicateDetail ERROR_PREDICATE = new PredicateDetail(true); | ||
12 | |||
13 | public static PredicateDetail ofError(boolean error) { | ||
14 | return error ? ERROR_PREDICATE : PREDICATE; | ||
15 | } | ||
16 | } | ||
diff --git a/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/ReferenceDetail.java b/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/ReferenceDetail.java new file mode 100644 index 00000000..42799417 --- /dev/null +++ b/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/ReferenceDetail.java | |||
@@ -0,0 +1,16 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.language.web.semantics.metadata; | ||
7 | |||
8 | public record ReferenceDetail(boolean containment) implements RelationDetail { | ||
9 | public static final ReferenceDetail CROSS_REFERENCE = new ReferenceDetail(false); | ||
10 | |||
11 | public static final ReferenceDetail CONTAINMENT_REFERENCE = new ReferenceDetail(true); | ||
12 | |||
13 | public static ReferenceDetail ofContainment(boolean containment) { | ||
14 | return containment ? CONTAINMENT_REFERENCE : CROSS_REFERENCE; | ||
15 | } | ||
16 | } | ||
diff --git a/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/RelationDetail.java b/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/RelationDetail.java new file mode 100644 index 00000000..bbe563cd --- /dev/null +++ b/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/RelationDetail.java | |||
@@ -0,0 +1,10 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.language.web.semantics.metadata; | ||
7 | |||
8 | public sealed interface RelationDetail permits ClassDetail, ReferenceDetail, PredicateDetail, OppositeReferenceDetail, | ||
9 | BuiltInDetail { | ||
10 | } | ||
diff --git a/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/RelationMetadata.java b/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/RelationMetadata.java new file mode 100644 index 00000000..e5d3a091 --- /dev/null +++ b/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/RelationMetadata.java | |||
@@ -0,0 +1,9 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.language.web.semantics.metadata; | ||
7 | |||
8 | public record RelationMetadata(String name, String simpleName, int arity, RelationDetail detail) implements Metadata { | ||
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; | |||
17 | import org.eclipse.xtext.web.server.ISession; | 17 | import org.eclipse.xtext.web.server.ISession; |
18 | import org.slf4j.Logger; | 18 | import org.slf4j.Logger; |
19 | import org.slf4j.LoggerFactory; | 19 | import org.slf4j.LoggerFactory; |
20 | import tools.refinery.language.semantics.metadata.*; | 20 | import tools.refinery.language.web.semantics.metadata.*; |
21 | import tools.refinery.language.web.xtext.server.ResponseHandler; | 21 | import tools.refinery.language.web.xtext.server.ResponseHandler; |
22 | import tools.refinery.language.web.xtext.server.ResponseHandlerException; | 22 | import tools.refinery.language.web.xtext.server.ResponseHandlerException; |
23 | import tools.refinery.language.web.xtext.server.TransactionExecutor; | 23 | import tools.refinery.language.web.xtext.server.TransactionExecutor; |