From 32d469d0284d1ab1540423e705a5d3c8e7d99705 Mon Sep 17 00:00:00 2001 From: Kristóf Marussy Date: Fri, 3 Nov 2023 19:12:08 +0100 Subject: refactor: smenatics and facades Also moves model metadata into language-web, since we only use it on the frontent. --- .../generator/ModelGenerationSuccessResult.java | 4 +- .../web/generator/ModelGenerationWorker.java | 30 +-- .../web/semantics/PartialInterpretation2Json.java | 21 +-- .../web/semantics/SemanticsSuccessResult.java | 4 +- .../language/web/semantics/SemanticsWorker.java | 30 +-- .../web/semantics/metadata/BuiltInDetail.java | 10 + .../web/semantics/metadata/ClassDetail.java | 16 ++ .../language/web/semantics/metadata/Metadata.java | 12 ++ .../web/semantics/metadata/MetadataCreator.java | 202 +++++++++++++++++++++ .../language/web/semantics/metadata/NodeKind.java | 12 ++ .../web/semantics/metadata/NodeMetadata.java | 9 + .../metadata/OppositeReferenceDetail.java | 9 + .../web/semantics/metadata/PredicateDetail.java | 16 ++ .../web/semantics/metadata/ReferenceDetail.java | 16 ++ .../web/semantics/metadata/RelationDetail.java | 10 + .../web/semantics/metadata/RelationMetadata.java | 9 + .../language/web/xtext/servlet/XtextWebSocket.java | 2 +- 17 files changed, 368 insertions(+), 44 deletions(-) create mode 100644 subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/BuiltInDetail.java create mode 100644 subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/ClassDetail.java create mode 100644 subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/Metadata.java create mode 100644 subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/MetadataCreator.java create mode 100644 subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/NodeKind.java create mode 100644 subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/NodeMetadata.java create mode 100644 subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/OppositeReferenceDetail.java create mode 100644 subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/PredicateDetail.java create mode 100644 subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/ReferenceDetail.java create mode 100644 subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/RelationDetail.java create mode 100644 subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/RelationMetadata.java (limited to 'subprojects/language-web/src') 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 @@ package tools.refinery.language.web.generator; import com.google.gson.JsonObject; -import tools.refinery.language.semantics.metadata.NodeMetadata; -import tools.refinery.language.semantics.metadata.RelationMetadata; +import tools.refinery.language.web.semantics.metadata.NodeMetadata; +import tools.refinery.language.web.semantics.metadata.RelationMetadata; import java.util.List; 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; import org.eclipse.xtext.service.OperationCanceledManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import tools.refinery.generator.ModelGeneratorBuilder; +import tools.refinery.generator.ModelGenerator; +import tools.refinery.generator.ModelGeneratorFactory; +import tools.refinery.language.web.semantics.metadata.MetadataCreator; +import tools.refinery.generator.ProblemLoader; import tools.refinery.generator.ValidationErrorsException; import tools.refinery.language.web.semantics.PartialInterpretation2Json; import tools.refinery.language.web.xtext.server.ThreadPoolExecutorServiceProvider; import tools.refinery.language.web.xtext.server.push.PushWebDocument; -import tools.refinery.store.reasoning.literal.Concreteness; import tools.refinery.store.util.CancellationToken; import java.io.IOException; @@ -38,7 +40,13 @@ public class ModelGenerationWorker implements Runnable { private OperationCanceledManager operationCanceledManager; @Inject - private ModelGeneratorBuilder generatorBuilder; + private ProblemLoader problemLoader; + + @Inject + private ModelGeneratorFactory generatorFactory; + + @Inject + private MetadataCreator metadataCreator; @Inject private PartialInterpretation2Json partialInterpretation2Json; @@ -127,9 +135,10 @@ public class ModelGenerationWorker implements Runnable { public ModelGenerationResult doRun() throws IOException { cancellationToken.checkCancelled(); + var problem = problemLoader.cancellationToken(cancellationToken).loadString(text); + ModelGenerator generator; try { - generatorBuilder.cancellationToken(cancellationToken); - generatorBuilder.fromString(text); + generator = generatorFactory.cancellationToken(cancellationToken).createGenerator(problem); } catch (ValidationErrorsException e) { var errors = e.getErrors(); if (errors != null && !errors.isEmpty()) { @@ -137,20 +146,19 @@ public class ModelGenerationWorker implements Runnable { } throw e; } - var generator = generatorBuilder.build(); notifyResult(new ModelGenerationStatusResult(uuid, "Generating model")); generator.setRandomSeed(randomSeed); - if (!generator.tryRun()) { + if (!generator.tryGenerate()) { return new ModelGenerationErrorResult(uuid, "Problem is unsatisfiable"); } notifyResult(new ModelGenerationStatusResult(uuid, "Saving generated model")); cancellationToken.checkCancelled(); - var nodesMetadata = generator.getNodesMetadata(); + metadataCreator.setProblemTrace(generator.getProblemTrace()); + var nodesMetadata = metadataCreator.getNodesMetadata(generator.getModel(), false); cancellationToken.checkCancelled(); - var relationsMetadata = generator.getProblemTrace().getRelationsMetadata(); + var relationsMetadata = metadataCreator.getRelationsMetadata(); cancellationToken.checkCancelled(); - var partialInterpretation = partialInterpretation2Json.getPartialInterpretation(generator, - Concreteness.CANDIDATE, cancellationToken); + var partialInterpretation = partialInterpretation2Json.getPartialInterpretation(generator, cancellationToken); return new ModelGenerationSuccessResult(uuid, nodesMetadata, relationsMetadata, partialInterpretation); } 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; import com.google.gson.JsonObject; import com.google.inject.Inject; import com.google.inject.Singleton; -import tools.refinery.generator.AbstractRefinery; -import tools.refinery.language.semantics.model.SemanticsUtils; +import tools.refinery.generator.ModelFacade; +import tools.refinery.language.semantics.SemanticsUtils; import tools.refinery.store.map.Cursor; import tools.refinery.store.model.Model; -import tools.refinery.store.reasoning.ReasoningAdapter; -import tools.refinery.store.reasoning.literal.Concreteness; import tools.refinery.store.reasoning.representation.PartialRelation; import tools.refinery.store.reasoning.translator.multiobject.MultiObjectTranslator; import tools.refinery.store.tuple.Tuple; @@ -27,15 +25,13 @@ public class PartialInterpretation2Json { @Inject private SemanticsUtils semanticsUtils; - public JsonObject getPartialInterpretation(AbstractRefinery refinery, Concreteness concreteness, - CancellationToken cancellationToken) { - var model = refinery.getModel(); - var adapter = model.getAdapter(ReasoningAdapter.class); + public JsonObject getPartialInterpretation(ModelFacade facade, CancellationToken cancellationToken) { + var model = facade.getModel(); var json = new JsonObject(); - for (var entry : refinery.getProblemTrace().getRelationTrace().entrySet()) { + for (var entry : facade.getProblemTrace().getRelationTrace().entrySet()) { var relation = entry.getKey(); var partialSymbol = entry.getValue(); - var tuples = getTuplesJson(adapter, concreteness, partialSymbol); + var tuples = getTuplesJson(facade, partialSymbol); var name = semanticsUtils.getName(relation).orElse(partialSymbol.name()); json.add(name, tuples); cancellationToken.checkCancelled(); @@ -44,9 +40,8 @@ public class PartialInterpretation2Json { return json; } - private static JsonArray getTuplesJson(ReasoningAdapter adapter, Concreteness concreteness, - PartialRelation partialSymbol) { - var interpretation = adapter.getPartialInterpretation(concreteness, partialSymbol); + private static JsonArray getTuplesJson(ModelFacade facade, PartialRelation partialSymbol) { + var interpretation = facade.getPartialInterpretation(partialSymbol); var cursor = interpretation.getAll(); return getTuplesJson(cursor); } 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 @@ package tools.refinery.language.web.semantics; import com.google.gson.JsonObject; -import tools.refinery.language.semantics.metadata.NodeMetadata; -import tools.refinery.language.semantics.metadata.RelationMetadata; +import tools.refinery.language.web.semantics.metadata.NodeMetadata; +import tools.refinery.language.web.semantics.metadata.RelationMetadata; import java.util.List; 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; import org.eclipse.xtext.validation.Issue; import org.eclipse.xtext.web.server.validation.ValidationResult; import tools.refinery.generator.ModelSemantics; -import tools.refinery.generator.ModelSemanticsBuilder; +import tools.refinery.generator.ModelSemanticsFactory; import tools.refinery.language.model.problem.Problem; -import tools.refinery.language.semantics.model.TracedException; -import tools.refinery.store.reasoning.literal.Concreteness; +import tools.refinery.language.web.semantics.metadata.MetadataCreator; +import tools.refinery.language.semantics.TracedException; import tools.refinery.store.reasoning.translator.TranslationException; import tools.refinery.store.util.CancellationToken; @@ -29,9 +29,6 @@ import java.util.concurrent.Callable; class SemanticsWorker implements Callable { private static final String DIAGNOSTIC_ID = "tools.refinery.language.semantics.SemanticError"; - @Inject - private PartialInterpretation2Json partialInterpretation2Json; - @Inject private OperationCanceledManager operationCanceledManager; @@ -39,7 +36,13 @@ class SemanticsWorker implements Callable { private IDiagnosticConverter diagnosticConverter; @Inject - private ModelSemanticsBuilder semanticsBuilder; + private ModelSemanticsFactory semanticsFactory; + + @Inject + private MetadataCreator metadataCreator; + + @Inject + private PartialInterpretation2Json partialInterpretation2Json; private Problem problem; @@ -56,13 +59,10 @@ class SemanticsWorker implements Callable { @Override public SemanticsResult call() { - semanticsBuilder.cancellationToken(cancellationToken); cancellationToken.checkCancelled(); ModelSemantics semantics; try { - semanticsBuilder.problem(problem); - cancellationToken.checkCancelled(); - semantics = semanticsBuilder.build(); + semantics = semanticsFactory.cancellationToken(cancellationToken).createSemantics(problem); } catch (TranslationException e) { return new SemanticsInternalErrorResult(e.getMessage()); } catch (TracedException e) { @@ -72,12 +72,12 @@ class SemanticsWorker implements Callable { return getTracedErrorResult(e.getSourceElement(), message); } cancellationToken.checkCancelled(); - var nodesMetadata = semantics.getNodesMetadata(); + metadataCreator.setProblemTrace(semantics.getProblemTrace()); + var nodesMetadata = metadataCreator.getNodesMetadata(semantics.getModel(), true); cancellationToken.checkCancelled(); - var relationsMetadata = semantics.getProblemTrace().getRelationsMetadata(); + var relationsMetadata = metadataCreator.getRelationsMetadata(); cancellationToken.checkCancelled(); - var partialInterpretation = partialInterpretation2Json.getPartialInterpretation(semantics, - Concreteness.PARTIAL, cancellationToken); + var partialInterpretation = partialInterpretation2Json.getPartialInterpretation(semantics, cancellationToken); return new SemanticsSuccessResult(nodesMetadata, relationsMetadata, partialInterpretation); } 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 @@ +/* + * SPDX-FileCopyrightText: 2023 The Refinery Authors + * + * SPDX-License-Identifier: EPL-2.0 + */ +package tools.refinery.language.web.semantics.metadata; + +public record BuiltInDetail() implements RelationDetail { + public static final BuiltInDetail INSTANCE = new BuiltInDetail(); +} 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 @@ +/* + * SPDX-FileCopyrightText: 2023 The Refinery Authors + * + * SPDX-License-Identifier: EPL-2.0 + */ +package tools.refinery.language.web.semantics.metadata; + +public record ClassDetail(boolean abstractClass) implements RelationDetail { + public static final ClassDetail CONCRETE_CLASS = new ClassDetail(false); + + public static final ClassDetail ABSTRACT_CLASS = new ClassDetail(true); + + public static ClassDetail ofAbstractClass(boolean abstractClass) { + return abstractClass ? ABSTRACT_CLASS : CONCRETE_CLASS; + } +} 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 @@ +/* + * SPDX-FileCopyrightText: 2023 The Refinery Authors + * + * SPDX-License-Identifier: EPL-2.0 + */ +package tools.refinery.language.web.semantics.metadata; + +public sealed interface Metadata permits NodeMetadata, RelationMetadata { + String name(); + + String simpleName(); +} 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 @@ +/* + * SPDX-FileCopyrightText: 2023 The Refinery Authors + * + * SPDX-License-Identifier: EPL-2.0 + */ +package tools.refinery.language.web.semantics.metadata; + +import com.google.inject.Inject; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.xtext.naming.IQualifiedNameConverter; +import org.eclipse.xtext.naming.IQualifiedNameProvider; +import org.eclipse.xtext.naming.QualifiedName; +import org.eclipse.xtext.scoping.IScope; +import org.eclipse.xtext.scoping.IScopeProvider; +import tools.refinery.language.model.problem.*; +import tools.refinery.language.semantics.ProblemTrace; +import tools.refinery.language.semantics.TracedException; +import tools.refinery.language.utils.ProblemUtil; +import tools.refinery.store.model.Model; +import tools.refinery.store.reasoning.ReasoningAdapter; +import tools.refinery.store.reasoning.representation.PartialRelation; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +public class MetadataCreator { + @Inject + private IScopeProvider scopeProvider; + + @Inject + private IQualifiedNameProvider qualifiedNameProvider; + + @Inject + private IQualifiedNameConverter qualifiedNameConverter; + + private ProblemTrace problemTrace; + + private IScope nodeScope; + + private IScope relationScope; + + public void setProblemTrace(ProblemTrace problemTrace) { + if (this.problemTrace != null) { + throw new IllegalArgumentException("Problem trace was already set"); + } + this.problemTrace = problemTrace; + var problem = problemTrace.getProblem(); + nodeScope = scopeProvider.getScope(problem, ProblemPackage.Literals.NODE_ASSERTION_ARGUMENT__NODE); + relationScope = scopeProvider.getScope(problem, ProblemPackage.Literals.ASSERTION__RELATION); + } + + public static String unnamedNode(int nodeId) { + return "::" + nodeId; + } + + public List getNodesMetadata(Model model, boolean preserveNewNodes) { + int nodeCount = model.getAdapter(ReasoningAdapter.class).getNodeCount(); + var nodeTrace = problemTrace.getNodeTrace(); + var nodes = new NodeMetadata[Math.max(nodeTrace.size(), nodeCount)]; + for (var entry : nodeTrace.keyValuesView()) { + var node = entry.getOne(); + var id = entry.getTwo(); + nodes[id] = getNodeMetadata(id, node, preserveNewNodes); + } + for (int i = 0; i < nodes.length; i++) { + if (nodes[i] == null) { + var nodeName = unnamedNode(i); + nodes[i] = new NodeMetadata(nodeName, nodeName, NodeKind.IMPLICIT); + } + } + return List.of(nodes); + } + + private NodeMetadata getNodeMetadata(int nodeId, Node node, boolean preserveNewNodes) { + var kind = getNodeKind(node); + if (!preserveNewNodes && kind == NodeKind.NEW) { + var nodeName = unnamedNode(nodeId); + return new NodeMetadata(nodeName, nodeName, NodeKind.IMPLICIT); + } + var qualifiedName = getQualifiedName(node); + var simpleName = getSimpleName(node, qualifiedName, nodeScope); + return new NodeMetadata(qualifiedNameConverter.toString(qualifiedName), + qualifiedNameConverter.toString(simpleName), getNodeKind(node)); + } + + private NodeKind getNodeKind(Node node) { + if (ProblemUtil.isImplicitNode(node)) { + return NodeKind.IMPLICIT; + } else if (ProblemUtil.isIndividualNode(node)) { + return NodeKind.INDIVIDUAL; + } else if (ProblemUtil.isNewNode(node)) { + return NodeKind.NEW; + } else { + throw new TracedException(node, "Unknown node type"); + } + } + + public List getRelationsMetadata() { + var relationTrace = problemTrace.getRelationTrace(); + var relations = new ArrayList(relationTrace.size()); + for (var entry : relationTrace.entrySet()) { + var relation = entry.getKey(); + var partialRelation = entry.getValue(); + var metadata = getRelationMetadata(relation, partialRelation); + relations.add(metadata); + } + return Collections.unmodifiableList(relations); + } + + private RelationMetadata getRelationMetadata(Relation relation, PartialRelation partialRelation) { + var qualifiedName = getQualifiedName(relation); + var qualifiedNameString = qualifiedNameConverter.toString(qualifiedName); + var simpleName = getSimpleName(relation, qualifiedName, relationScope); + var simpleNameString = qualifiedNameConverter.toString(simpleName); + var arity = partialRelation.arity(); + var detail = getRelationDetail(relation, partialRelation); + return new RelationMetadata(qualifiedNameString, simpleNameString, arity, detail); + } + + private RelationDetail getRelationDetail(Relation relation, PartialRelation partialRelation) { + if (ProblemUtil.isBuiltIn(relation) && !ProblemUtil.isError(relation)) { + return getBuiltInDetail(); + } + if (relation instanceof ClassDeclaration classDeclaration) { + return getClassDetail(classDeclaration); + } else if (relation instanceof ReferenceDeclaration) { + return getReferenceDetail(partialRelation); + } else if (relation instanceof EnumDeclaration) { + return getEnumDetail(); + } else if (relation instanceof PredicateDefinition predicateDefinition) { + return getPredicateDetail(predicateDefinition); + } else { + throw new TracedException(relation, "Unknown relation"); + } + } + + private RelationDetail getBuiltInDetail() { + return BuiltInDetail.INSTANCE; + } + + private RelationDetail getClassDetail(ClassDeclaration classDeclaration) { + return ClassDetail.ofAbstractClass(classDeclaration.isAbstract()); + } + + private RelationDetail getReferenceDetail(PartialRelation partialRelation) { + var metamodel = problemTrace.getMetamodel(); + var opposite = metamodel.oppositeReferences().get(partialRelation); + if (opposite == null) { + boolean isContainment = metamodel.containmentHierarchy().containsKey(partialRelation); + return ReferenceDetail.ofContainment(isContainment); + } else { + boolean isContainer = metamodel.containmentHierarchy().containsKey(opposite); + return new OppositeReferenceDetail(isContainer, opposite.name()); + } + } + + private RelationDetail getEnumDetail() { + return ClassDetail.CONCRETE_CLASS; + } + + private RelationDetail getPredicateDetail(PredicateDefinition predicate) { + return PredicateDetail.ofError(predicate.isError()); + } + + private QualifiedName getQualifiedName(EObject eObject) { + var qualifiedName = qualifiedNameProvider.getFullyQualifiedName(eObject); + if (qualifiedName == null) { + throw new TracedException(eObject, "Unknown qualified name"); + } + return qualifiedName; + } + + private QualifiedName getSimpleName(EObject eObject, QualifiedName qualifiedName, IScope scope) { + var descriptions = scope.getElements(eObject); + var names = new ArrayList(); + for (var description : descriptions) { + // {@code getQualifiedName()} will refer to the full name for objects that are loaded from the global + // scope, but {@code getName()} returns the qualified name that we set in + // {@code ProblemResourceDescriptionStrategy}. + names.add(description.getName()); + } + names.sort(Comparator.comparingInt(QualifiedName::getSegmentCount)); + for (var simpleName : names) { + if (names.contains(simpleName) && isUnique(scope, simpleName)) { + return simpleName; + } + } + throw new TracedException(eObject, "Ambiguous qualified name: " + + qualifiedNameConverter.toString(qualifiedName)); + } + + private boolean isUnique(IScope scope, QualifiedName name) { + var iterator = scope.getElements(name).iterator(); + if (!iterator.hasNext()) { + return false; + } + iterator.next(); + return !iterator.hasNext(); + } +} 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 @@ +/* + * SPDX-FileCopyrightText: 2023 The Refinery Authors + * + * SPDX-License-Identifier: EPL-2.0 + */ +package tools.refinery.language.web.semantics.metadata; + +public enum NodeKind { + IMPLICIT, + INDIVIDUAL, + NEW +} 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 @@ +/* + * SPDX-FileCopyrightText: 2023 The Refinery Authors + * + * SPDX-License-Identifier: EPL-2.0 + */ +package tools.refinery.language.web.semantics.metadata; + +public record NodeMetadata(String name, String simpleName, NodeKind kind) implements Metadata { +} 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 @@ +/* + * SPDX-FileCopyrightText: 2023 The Refinery Authors + * + * SPDX-License-Identifier: EPL-2.0 + */ +package tools.refinery.language.web.semantics.metadata; + +public record OppositeReferenceDetail(boolean container, String opposite) implements RelationDetail { +} 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 @@ +/* + * SPDX-FileCopyrightText: 2023 The Refinery Authors + * + * SPDX-License-Identifier: EPL-2.0 + */ +package tools.refinery.language.web.semantics.metadata; + +public record PredicateDetail(boolean error) implements RelationDetail { + public static final PredicateDetail PREDICATE = new PredicateDetail(false); + + public static final PredicateDetail ERROR_PREDICATE = new PredicateDetail(true); + + public static PredicateDetail ofError(boolean error) { + return error ? ERROR_PREDICATE : PREDICATE; + } +} 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 @@ +/* + * SPDX-FileCopyrightText: 2023 The Refinery Authors + * + * SPDX-License-Identifier: EPL-2.0 + */ +package tools.refinery.language.web.semantics.metadata; + +public record ReferenceDetail(boolean containment) implements RelationDetail { + public static final ReferenceDetail CROSS_REFERENCE = new ReferenceDetail(false); + + public static final ReferenceDetail CONTAINMENT_REFERENCE = new ReferenceDetail(true); + + public static ReferenceDetail ofContainment(boolean containment) { + return containment ? CONTAINMENT_REFERENCE : CROSS_REFERENCE; + } +} 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 @@ +/* + * SPDX-FileCopyrightText: 2023 The Refinery Authors + * + * SPDX-License-Identifier: EPL-2.0 + */ +package tools.refinery.language.web.semantics.metadata; + +public sealed interface RelationDetail permits ClassDetail, ReferenceDetail, PredicateDetail, OppositeReferenceDetail, + BuiltInDetail { +} 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 @@ +/* + * SPDX-FileCopyrightText: 2023 The Refinery Authors + * + * SPDX-License-Identifier: EPL-2.0 + */ +package tools.refinery.language.web.semantics.metadata; + +public record RelationMetadata(String name, String simpleName, int arity, RelationDetail detail) implements Metadata { +} 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; import org.eclipse.xtext.web.server.ISession; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import tools.refinery.language.semantics.metadata.*; +import tools.refinery.language.web.semantics.metadata.*; import tools.refinery.language.web.xtext.server.ResponseHandler; import tools.refinery.language.web.xtext.server.ResponseHandlerException; import tools.refinery.language.web.xtext.server.TransactionExecutor; -- cgit v1.2.3-54-g00ecf