aboutsummaryrefslogtreecommitdiffstats
path: root/language-model
diff options
context:
space:
mode:
authorLibravatar Kristóf Marussy <kristof@marussy.com>2021-10-19 03:36:26 +0200
committerLibravatar Kristóf Marussy <kristof@marussy.com>2021-10-19 03:36:26 +0200
commit663274763e56b228efe07363b8ede4ce7bebc251 (patch)
treeda6f8e0404cc03152cad84d8b9dfc8c63f7a6dbf /language-model
parentnodeIter moved from private field inside the method (diff)
downloadrefinery-663274763e56b228efe07363b8ede4ce7bebc251.tar.gz
refinery-663274763e56b228efe07363b8ede4ce7bebc251.tar.zst
refinery-663274763e56b228efe07363b8ede4ce7bebc251.zip
chore: remove builtin library xtext dependency
Diffstat (limited to 'language-model')
-rw-r--r--language-model/build.gradle2
-rw-r--r--language-model/plugin.xml7
-rw-r--r--language-model/src/main/java/tools/refinery/language/model/ProblemEMFSetup.java34
-rw-r--r--language-model/src/main/java/tools/refinery/language/model/ProblemUtil.java102
-rw-r--r--language-model/src/main/resources/model/builtin.problem_xmi67
-rw-r--r--language-model/src/main/resources/model/problem.ecore3
-rw-r--r--language-model/src/main/resources/model/problem.genmodel4
-rw-r--r--language-model/src/testFixtures/java/tools/refinery/language/model/tests/ProblemTestUtil.java154
8 files changed, 369 insertions, 4 deletions
diff --git a/language-model/build.gradle b/language-model/build.gradle
index d01f8dfc..46ae839b 100644
--- a/language-model/build.gradle
+++ b/language-model/build.gradle
@@ -1,9 +1,11 @@
1apply plugin: 'java-library' 1apply plugin: 'java-library'
2apply plugin: 'java-test-fixtures'
2apply from: "${rootDir}/gradle/java-common.gradle" 3apply from: "${rootDir}/gradle/java-common.gradle"
3apply from: "${rootDir}/gradle/mwe2.gradle" 4apply from: "${rootDir}/gradle/mwe2.gradle"
4 5
5dependencies { 6dependencies {
6 api "org.eclipse.emf:org.eclipse.emf.ecore:${ecoreVersion}" 7 api "org.eclipse.emf:org.eclipse.emf.ecore:${ecoreVersion}"
8 api "org.eclipse.emf:org.eclipse.emf.ecore.xmi:${ecoreXmiVersion}"
7 mwe2 "org.eclipse.emf:org.eclipse.emf.codegen.ecore:${ecoreCodegenVersion}" 9 mwe2 "org.eclipse.emf:org.eclipse.emf.codegen.ecore:${ecoreCodegenVersion}"
8 mwe2 "org.eclipse.emf:org.eclipse.emf.mwe.utils:${mweVersion}" 10 mwe2 "org.eclipse.emf:org.eclipse.emf.mwe.utils:${mweVersion}"
9 mwe2 "org.eclipse.emf:org.eclipse.emf.mwe2.lib:${mwe2Version}" 11 mwe2 "org.eclipse.emf:org.eclipse.emf.mwe2.lib:${mwe2Version}"
diff --git a/language-model/plugin.xml b/language-model/plugin.xml
index 1e1a246e..4ca005a8 100644
--- a/language-model/plugin.xml
+++ b/language-model/plugin.xml
@@ -14,4 +14,11 @@
14 genModel="src/main/resources/model/problem.genmodel"/> 14 genModel="src/main/resources/model/problem.genmodel"/>
15 </extension> 15 </extension>
16 16
17 <extension point="org.eclipse.emf.ecore.extension_parser">
18 <!-- @generated problem -->
19 <parser
20 type="problem_xmi"
21 class="tools.refinery.language.model.problem.util.ProblemResourceFactoryImpl"/>
22 </extension>
23
17</plugin> 24</plugin>
diff --git a/language-model/src/main/java/tools/refinery/language/model/ProblemEMFSetup.java b/language-model/src/main/java/tools/refinery/language/model/ProblemEMFSetup.java
new file mode 100644
index 00000000..9383098b
--- /dev/null
+++ b/language-model/src/main/java/tools/refinery/language/model/ProblemEMFSetup.java
@@ -0,0 +1,34 @@
1package tools.refinery.language.model;
2
3import org.eclipse.emf.ecore.EPackage;
4import org.eclipse.emf.ecore.resource.Resource;
5
6import tools.refinery.language.model.problem.ProblemPackage;
7import tools.refinery.language.model.problem.impl.ProblemFactoryImpl;
8
9public class ProblemEMFSetup {
10 public static final String XMI_RESOURCE_EXTENSION = "problem_xmi";
11
12 private ProblemEMFSetup() {
13 throw new IllegalStateException("This is a static utility class and should not be instantiated directly");
14 }
15
16 // Here we can't rely on java.util.HashMap#putIfAbsent, because
17 // org.eclipse.emf.ecore.impl.EPackageRegistryImpl#containsKey is overridden
18 // without also overriding putIfAbsent. We must make sure to call the
19 // overridden containsKey implementation.
20 @SuppressWarnings("squid:S3824")
21 public static void doEMFRegistration() {
22 if (!EPackage.Registry.INSTANCE.containsKey(ProblemPackage.eNS_URI)) {
23 EPackage.Registry.INSTANCE.put(ProblemPackage.eNS_URI, ProblemPackage.eINSTANCE);
24 }
25
26 // This Resource.Factory is not actually used once
27 // tools.refinery.language.ProblemStandaloneSetup.createInjectorAndDoEMFRegistration()
28 // is called, because if will be replaced by
29 // tools.refinery.language.resource.ProblemXmiResourceFactory, which implements
30 // org.eclipse.xtext.resource.IResourceFactory as required by Xtext.
31 Resource.Factory.Registry.INSTANCE.getExtensionToFactoryMap().putIfAbsent(XMI_RESOURCE_EXTENSION,
32 new ProblemFactoryImpl());
33 }
34}
diff --git a/language-model/src/main/java/tools/refinery/language/model/ProblemUtil.java b/language-model/src/main/java/tools/refinery/language/model/ProblemUtil.java
new file mode 100644
index 00000000..b6b199f8
--- /dev/null
+++ b/language-model/src/main/java/tools/refinery/language/model/ProblemUtil.java
@@ -0,0 +1,102 @@
1package tools.refinery.language.model;
2
3import java.util.ArrayDeque;
4import java.util.Collection;
5import java.util.Deque;
6import java.util.HashSet;
7import java.util.Optional;
8import java.util.Set;
9
10import org.eclipse.emf.common.util.URI;
11import org.eclipse.emf.ecore.EObject;
12import org.eclipse.emf.ecore.resource.Resource;
13
14import tools.refinery.language.model.problem.ClassDeclaration;
15import tools.refinery.language.model.problem.Node;
16import tools.refinery.language.model.problem.Problem;
17import tools.refinery.language.model.problem.ProblemPackage;
18import tools.refinery.language.model.problem.ReferenceDeclaration;
19import tools.refinery.language.model.problem.Relation;
20import tools.refinery.language.model.problem.Variable;
21
22public final class ProblemUtil {
23 public static final String BUILTIN_LIBRARY_NAME = "builtin";
24
25 public static final URI BUILTIN_LIBRARY_URI = getLibraryUri(BUILTIN_LIBRARY_NAME);
26
27 public static final String NODE_CLASS_NAME = "node";
28
29 private ProblemUtil() {
30 throw new IllegalStateException("This is a static utility class and should not be instantiated directly");
31 }
32
33 public static boolean isSingletonVariable(Variable variable) {
34 return variable.eContainingFeature() == ProblemPackage.Literals.VARIABLE_OR_NODE_ARGUMENT__SINGLETON_VARIABLE;
35 }
36
37 public static boolean isUniqueNode(Node node) {
38 var containingFeature = node.eContainingFeature();
39 return containingFeature == ProblemPackage.Literals.UNIQUE_DECLARATION__NODES
40 || containingFeature == ProblemPackage.Literals.ENUM_DECLARATION__LITERALS;
41 }
42
43 public static boolean isNewNode(Node node) {
44 return node.eContainingFeature() == ProblemPackage.Literals.CLASS_DECLARATION__NEW_NODE;
45 }
46
47 public static Optional<Problem> getBuiltInLibrary(EObject context) {
48 return Optional.ofNullable(context.eResource()).map(Resource::getResourceSet)
49 .map(resourceSet -> resourceSet.getResource(BUILTIN_LIBRARY_URI, true)).map(Resource::getContents)
50 .filter(contents -> !contents.isEmpty()).map(contents -> contents.get(0))
51 .filter(Problem.class::isInstance).map(Problem.class::cast);
52 }
53
54 public static boolean isBuiltIn(EObject eObject) {
55 if (eObject != null) {
56 var eResource = eObject.eResource();
57 if (eResource != null) {
58 return BUILTIN_LIBRARY_URI.equals(eResource.getURI());
59 }
60 }
61 return false;
62 }
63
64 public static Optional<ClassDeclaration> getNodeClassDeclaration(EObject context) {
65 return getBuiltInLibrary(context).flatMap(problem -> problem.getStatements().stream()
66 .filter(ClassDeclaration.class::isInstance).map(ClassDeclaration.class::cast)
67 .filter(declaration -> NODE_CLASS_NAME.equals(declaration.getName())).findFirst());
68 }
69
70 public static Collection<ClassDeclaration> getSuperclassesAndSelf(ClassDeclaration classDeclaration) {
71 Set<ClassDeclaration> found = new HashSet<>();
72 getNodeClassDeclaration(classDeclaration).ifPresent(found::add);
73 Deque<ClassDeclaration> queue = new ArrayDeque<>();
74 queue.addLast(classDeclaration);
75 while (!queue.isEmpty()) {
76 ClassDeclaration current = queue.removeFirst();
77 if (!found.contains(current)) {
78 found.add(current);
79 for (Relation superType : current.getSuperTypes()) {
80 if (superType instanceof ClassDeclaration superDeclaration) {
81 queue.addLast(superDeclaration);
82 }
83 }
84 }
85 }
86 return found;
87 }
88
89 public static Collection<ReferenceDeclaration> getAllReferenceDeclarations(ClassDeclaration classDeclaration) {
90 Set<ReferenceDeclaration> referenceDeclarations = new HashSet<>();
91 for (ClassDeclaration superclass : getSuperclassesAndSelf(classDeclaration)) {
92 referenceDeclarations.addAll(superclass.getReferenceDeclarations());
93 }
94 return referenceDeclarations;
95 }
96
97 private static URI getLibraryUri(String libraryName) {
98 return URI.createURI(ProblemUtil.class.getClassLoader()
99 .getResource("model/" + libraryName + "." + ProblemEMFSetup.XMI_RESOURCE_EXTENSION)
100 .toString());
101 }
102}
diff --git a/language-model/src/main/resources/model/builtin.problem_xmi b/language-model/src/main/resources/model/builtin.problem_xmi
new file mode 100644
index 00000000..9255ab66
--- /dev/null
+++ b/language-model/src/main/resources/model/builtin.problem_xmi
@@ -0,0 +1,67 @@
1<?xml version="1.0" encoding="UTF-8"?>
2<problem:Problem
3 xmi:version="2.0"
4 xmlns:xmi="http://www.omg.org/XMI"
5 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
6 xmlns:problem="https://refinery.tools/emf/2021/Problem"
7 xsi:schemaLocation="https://refinery.tools/emf/2021/Problem problem.ecore"
8 name="builtin">
9 <statements
10 xsi:type="problem:ClassDeclaration"
11 name="node"
12 abstract="true">
13 <referenceDeclarations
14 name="equals"
15 referenceType="//@statements.0"
16 opposite="//@statements.0/@referenceDeclarations.0">
17 <multiplicity
18 xsi:type="problem:UnboundedMultiplicity"/>
19 </referenceDeclarations>
20 </statements>
21 <statements
22 xsi:type="problem:PredicateDefinition"
23 name="exists">
24 <parameters
25 name="node"
26 parameterType="//@statements.0"/>
27 </statements>
28 <statements
29 xsi:type="problem:ClassDeclaration"
30 name="domain"
31 abstract="true"
32 superTypes="//@statements.0"/>
33 <statements
34 xsi:type="problem:ClassDeclaration"
35 name="data"
36 abstract="true"
37 superTypes="//@statements.0"/>
38 <statements
39 xsi:type="problem:EnumDeclaration"
40 name="bool">
41 <literals
42 name="false"/>
43 <literals
44 name="true"/>
45 </statements>
46 <statements
47 xsi:type="problem:ClassDeclaration"
48 name="real"
49 superTypes="//@statements.3">
50 <newNode
51 name="new"/>
52 </statements>
53 <statements
54 xsi:type="problem:ClassDeclaration"
55 name="int"
56 superTypes="//@statements.3">
57 <newNode
58 name="new"/>
59 </statements>
60 <statements
61 xsi:type="problem:ClassDeclaration"
62 name="string"
63 superTypes="//@statements.3">
64 <newNode
65 name="new"/>
66 </statements>
67</problem:Problem>
diff --git a/language-model/src/main/resources/model/problem.ecore b/language-model/src/main/resources/model/problem.ecore
index a62590ac..e86f0afd 100644
--- a/language-model/src/main/resources/model/problem.ecore
+++ b/language-model/src/main/resources/model/problem.ecore
@@ -1,7 +1,6 @@
1<?xml version="1.0" encoding="UTF-8"?> 1<?xml version="1.0" encoding="UTF-8"?>
2<ecore:EPackage xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 2<ecore:EPackage xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3 xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" name="problem" nsURI="https://refinery.tools/emf/2021/Problem" 3 xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" name="problem" nsURI="https://refinery.tools/emf/2021/Problem" nsPrefix="problem">
4 nsPrefix="problem">
5 <eClassifiers xsi:type="ecore:EClass" name="Problem" eSuperTypes="#//NamedElement"> 4 <eClassifiers xsi:type="ecore:EClass" name="Problem" eSuperTypes="#//NamedElement">
6 <eStructuralFeatures xsi:type="ecore:EReference" name="nodes" upperBound="-1" 5 <eStructuralFeatures xsi:type="ecore:EReference" name="nodes" upperBound="-1"
7 eType="#//Node" containment="true"/> 6 eType="#//Node" containment="true"/>
diff --git a/language-model/src/main/resources/model/problem.genmodel b/language-model/src/main/resources/model/problem.genmodel
index e529977f..057b4917 100644
--- a/language-model/src/main/resources/model/problem.genmodel
+++ b/language-model/src/main/resources/model/problem.genmodel
@@ -8,8 +8,8 @@
8 copyrightFields="false" operationReflection="true" importOrganizing="true"> 8 copyrightFields="false" operationReflection="true" importOrganizing="true">
9 <foreignModel>problem.ecore</foreignModel> 9 <foreignModel>problem.ecore</foreignModel>
10 <testsDirectory xsi:nil="true"/> 10 <testsDirectory xsi:nil="true"/>
11 <genPackages prefix="Problem" basePackage="tools.refinery.language.model" 11 <genPackages prefix="Problem" basePackage="tools.refinery.language.model" resource="XMI"
12 disposableProviderFactory="true" ecorePackage="problem.ecore#/"> 12 disposableProviderFactory="true" fileExtensions="problem_xmi" ecorePackage="problem.ecore#/">
13 <genEnums typeSafeEnumCompatible="false" ecoreEnum="problem.ecore#//LogicValue"> 13 <genEnums typeSafeEnumCompatible="false" ecoreEnum="problem.ecore#//LogicValue">
14 <genEnumLiterals ecoreEnumLiteral="problem.ecore#//LogicValue/TRUE"/> 14 <genEnumLiterals ecoreEnumLiteral="problem.ecore#//LogicValue/TRUE"/>
15 <genEnumLiterals ecoreEnumLiteral="problem.ecore#//LogicValue/FALSE"/> 15 <genEnumLiterals ecoreEnumLiteral="problem.ecore#//LogicValue/FALSE"/>
diff --git a/language-model/src/testFixtures/java/tools/refinery/language/model/tests/ProblemTestUtil.java b/language-model/src/testFixtures/java/tools/refinery/language/model/tests/ProblemTestUtil.java
new file mode 100644
index 00000000..b412ed1f
--- /dev/null
+++ b/language-model/src/testFixtures/java/tools/refinery/language/model/tests/ProblemTestUtil.java
@@ -0,0 +1,154 @@
1package tools.refinery.language.model.tests;
2
3import java.util.List;
4import java.util.stream.Stream;
5
6import org.eclipse.emf.ecore.resource.Resource.Diagnostic;
7import org.eclipse.emf.ecore.util.EcoreUtil;
8
9import tools.refinery.language.model.ProblemUtil;
10import tools.refinery.language.model.problem.Argument;
11import tools.refinery.language.model.problem.Assertion;
12import tools.refinery.language.model.problem.AssertionArgument;
13import tools.refinery.language.model.problem.Atom;
14import tools.refinery.language.model.problem.ClassDeclaration;
15import tools.refinery.language.model.problem.Conjunction;
16import tools.refinery.language.model.problem.EnumDeclaration;
17import tools.refinery.language.model.problem.Literal;
18import tools.refinery.language.model.problem.NamedElement;
19import tools.refinery.language.model.problem.NegativeLiteral;
20import tools.refinery.language.model.problem.Node;
21import tools.refinery.language.model.problem.NodeAssertionArgument;
22import tools.refinery.language.model.problem.NodeValueAssertion;
23import tools.refinery.language.model.problem.Parameter;
24import tools.refinery.language.model.problem.PredicateDefinition;
25import tools.refinery.language.model.problem.Problem;
26import tools.refinery.language.model.problem.ReferenceDeclaration;
27import tools.refinery.language.model.problem.Relation;
28import tools.refinery.language.model.problem.Statement;
29import tools.refinery.language.model.problem.UniqueDeclaration;
30import tools.refinery.language.model.problem.Variable;
31import tools.refinery.language.model.problem.VariableOrNode;
32import tools.refinery.language.model.problem.VariableOrNodeArgument;
33
34public class ProblemTestUtil {
35 public Problem builtin(Problem problem) {
36 return ProblemUtil.getBuiltInLibrary(problem).get();
37 }
38
39 public List<Diagnostic> errors(Problem problem) {
40 EcoreUtil.resolveAll(problem);
41 return problem.eResource().getErrors();
42 }
43
44 public List<String> nodeNames(Problem problem) {
45 return problem.getNodes().stream().map(node -> node.getName()).toList();
46 }
47
48 public PredicateDefinition pred(Problem problem, String name) {
49 return namedStatementOfType(problem, PredicateDefinition.class, name);
50 }
51
52 public Parameter param(PredicateDefinition definition, int i) {
53 return definition.getParameters().get(i);
54 }
55
56 public Conjunction conj(PredicateDefinition definition, int i) {
57 return definition.getBodies().get(i);
58 }
59
60 public Literal lit(Conjunction conjunction, int i) {
61 return conjunction.getLiterals().get(i);
62 }
63
64 public Atom negated(Literal literal) {
65 return ((NegativeLiteral) literal).getAtom();
66 }
67
68 public Relation relation(Literal literal) {
69 return ((Atom) literal).getRelation();
70 }
71
72 public Argument arg(Atom atom, int i) {
73 return atom.getArguments().get(i);
74 }
75
76 public Argument arg(Literal literal, int i) {
77 return arg((Atom) literal, i);
78 }
79
80 public VariableOrNode variableOrNode(Argument argument) {
81 return ((VariableOrNodeArgument) argument).getVariableOrNode();
82 }
83
84 public Variable variable(Argument argument) {
85 return (Variable) variableOrNode(argument);
86 }
87
88 public Node node(Argument argument) {
89 return (Node) variableOrNode(argument);
90 }
91
92 public Assertion assertion(Problem problem, int i) {
93 return nthStatementOfType(problem, Assertion.class, i);
94 }
95
96 public AssertionArgument arg(Assertion assertion, int i) {
97 return assertion.getArguments().get(i);
98 }
99
100 public Node node(AssertionArgument argument) {
101 return ((NodeAssertionArgument) argument).getNode();
102 }
103
104 public Node node(Problem problem, String name) {
105 return named(problem.getNodes(), name);
106 }
107
108 public Node uniqueNode(Problem problem, String name) {
109 var uniqueNodes = statementsOfType(problem, UniqueDeclaration.class)
110 .flatMap(declaration -> declaration.getNodes().stream());
111 return named(uniqueNodes, name);
112 }
113
114 public NodeValueAssertion nodeValueAssertion(Problem problem, int i) {
115 return nthStatementOfType(problem, NodeValueAssertion.class, i);
116 }
117
118 public ClassDeclaration findClass(Problem problem, String name) {
119 return namedStatementOfType(problem, ClassDeclaration.class, name);
120 }
121
122 public ReferenceDeclaration reference(ClassDeclaration declaration, String name) {
123 return named(declaration.getReferenceDeclarations(), name);
124 }
125
126 public EnumDeclaration findEnum(Problem problem, String name) {
127 return namedStatementOfType(problem, EnumDeclaration.class, name);
128 }
129
130 public Node literal(EnumDeclaration declaration, String name) {
131 return named(declaration.getLiterals(), name);
132 }
133
134 private <T extends NamedElement> T named(Stream<? extends T> stream, String name) {
135 return stream.filter(statement -> name.equals(statement.getName())).findAny().get();
136 }
137
138 private <T extends NamedElement> T named(List<? extends T> list, String name) {
139 return named(list.stream(), name);
140 }
141
142 private <T extends Statement> Stream<T> statementsOfType(Problem problem, Class<? extends T> type) {
143 return problem.getStatements().stream().filter(type::isInstance).map(type::cast);
144 }
145
146 private <T extends Statement & NamedElement> T namedStatementOfType(Problem problem, Class<? extends T> type,
147 String name) {
148 return named(statementsOfType(problem, type), name);
149 }
150
151 private <T extends Statement> T nthStatementOfType(Problem problem, Class<? extends T> type, int n) {
152 return statementsOfType(problem, type).skip(n).findFirst().get();
153 }
154}