diff options
Diffstat (limited to 'subprojects/language-semantics/src/main/java/tools')
2 files changed, 71 insertions, 29 deletions
diff --git a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/NodeNameProvider.java b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/NodeNameProvider.java new file mode 100644 index 00000000..517b8604 --- /dev/null +++ b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/NodeNameProvider.java | |||
@@ -0,0 +1,62 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2024 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.language.semantics; | ||
7 | |||
8 | import com.google.inject.Inject; | ||
9 | import org.eclipse.collections.api.factory.primitive.ObjectIntMaps; | ||
10 | import org.eclipse.collections.api.map.primitive.MutableObjectIntMap; | ||
11 | import org.eclipse.xtext.naming.IQualifiedNameConverter; | ||
12 | import org.eclipse.xtext.naming.QualifiedName; | ||
13 | import org.eclipse.xtext.scoping.IScopeProvider; | ||
14 | import tools.refinery.language.model.problem.Node; | ||
15 | import tools.refinery.language.model.problem.Problem; | ||
16 | import tools.refinery.language.model.problem.ProblemPackage; | ||
17 | |||
18 | import java.util.Locale; | ||
19 | |||
20 | public class NodeNameProvider { | ||
21 | @Inject | ||
22 | private IQualifiedNameConverter qualifiedNameConverter; | ||
23 | |||
24 | @Inject | ||
25 | private SemanticsUtils semanticsUtils; | ||
26 | |||
27 | @Inject | ||
28 | private IScopeProvider scopeProvider; | ||
29 | |||
30 | private Problem problem; | ||
31 | private final MutableObjectIntMap<String> indexMap = ObjectIntMaps.mutable.empty(); | ||
32 | |||
33 | public void setProblem(Problem problem) { | ||
34 | if (this.problem != null) { | ||
35 | throw new IllegalStateException("Problem was already set"); | ||
36 | } | ||
37 | this.problem = problem; | ||
38 | } | ||
39 | |||
40 | public String getNextName(String typeName) { | ||
41 | if (problem == null) { | ||
42 | throw new IllegalStateException("Problem was not set"); | ||
43 | } | ||
44 | String namePrefix; | ||
45 | if (typeName == null || typeName.isEmpty()) { | ||
46 | namePrefix = "node"; | ||
47 | } else { | ||
48 | namePrefix = typeName.substring(0, 1).toLowerCase(Locale.ROOT) + typeName.substring(1); | ||
49 | } | ||
50 | int index = indexMap.getIfAbsent(namePrefix, 0); | ||
51 | String nodeName; | ||
52 | QualifiedName qualifiedName; | ||
53 | var scope = scopeProvider.getScope(problem, ProblemPackage.Literals.NODE_ASSERTION_ARGUMENT__NODE); | ||
54 | do { | ||
55 | index++; | ||
56 | nodeName = namePrefix + index; | ||
57 | qualifiedName = qualifiedNameConverter.toQualifiedName(nodeName); | ||
58 | } while (semanticsUtils.maybeGetElement(problem, scope, qualifiedName, Node.class) != null); | ||
59 | indexMap.put(namePrefix, index); | ||
60 | return nodeName; | ||
61 | } | ||
62 | } | ||
diff --git a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/SolutionSerializer.java b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/SolutionSerializer.java index 57af599e..09ba34fc 100644 --- a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/SolutionSerializer.java +++ b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/SolutionSerializer.java | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/> | 2 | * SPDX-FileCopyrightText: 2023-2024 The Refinery Authors <https://refinery.tools/> |
3 | * | 3 | * |
4 | * SPDX-License-Identifier: EPL-2.0 | 4 | * SPDX-License-Identifier: EPL-2.0 |
5 | */ | 5 | */ |
@@ -8,12 +8,9 @@ package tools.refinery.language.semantics; | |||
8 | import com.google.inject.Inject; | 8 | import com.google.inject.Inject; |
9 | import com.google.inject.Provider; | 9 | import com.google.inject.Provider; |
10 | import org.eclipse.collections.api.factory.primitive.IntObjectMaps; | 10 | import org.eclipse.collections.api.factory.primitive.IntObjectMaps; |
11 | import org.eclipse.collections.api.factory.primitive.ObjectIntMaps; | ||
12 | import org.eclipse.collections.api.map.primitive.MutableIntObjectMap; | 11 | import org.eclipse.collections.api.map.primitive.MutableIntObjectMap; |
13 | import org.eclipse.collections.api.map.primitive.MutableObjectIntMap; | ||
14 | import org.eclipse.emf.common.util.URI; | 12 | import org.eclipse.emf.common.util.URI; |
15 | import org.eclipse.emf.ecore.util.EcoreUtil; | 13 | import org.eclipse.emf.ecore.util.EcoreUtil; |
16 | import org.eclipse.xtext.naming.IQualifiedNameConverter; | ||
17 | import org.eclipse.xtext.naming.IQualifiedNameProvider; | 14 | import org.eclipse.xtext.naming.IQualifiedNameProvider; |
18 | import org.eclipse.xtext.naming.QualifiedName; | 15 | import org.eclipse.xtext.naming.QualifiedName; |
19 | import org.eclipse.xtext.resource.FileExtensionProvider; | 16 | import org.eclipse.xtext.resource.FileExtensionProvider; |
@@ -37,7 +34,6 @@ import tools.refinery.store.tuple.Tuple; | |||
37 | import java.io.ByteArrayInputStream; | 34 | import java.io.ByteArrayInputStream; |
38 | import java.io.ByteArrayOutputStream; | 35 | import java.io.ByteArrayOutputStream; |
39 | import java.io.IOException; | 36 | import java.io.IOException; |
40 | import java.util.Locale; | ||
41 | import java.util.Map; | 37 | import java.util.Map; |
42 | import java.util.TreeMap; | 38 | import java.util.TreeMap; |
43 | import java.util.TreeSet; | 39 | import java.util.TreeSet; |
@@ -57,9 +53,6 @@ public class SolutionSerializer { | |||
57 | private IQualifiedNameProvider qualifiedNameProvider; | 53 | private IQualifiedNameProvider qualifiedNameProvider; |
58 | 54 | ||
59 | @Inject | 55 | @Inject |
60 | private IQualifiedNameConverter qualifiedNameConverter; | ||
61 | |||
62 | @Inject | ||
63 | private SemanticsUtils semanticsUtils; | 56 | private SemanticsUtils semanticsUtils; |
64 | 57 | ||
65 | @Inject | 58 | @Inject |
@@ -68,6 +61,9 @@ public class SolutionSerializer { | |||
68 | @Inject | 61 | @Inject |
69 | private ProblemDesugarer desugarer; | 62 | private ProblemDesugarer desugarer; |
70 | 63 | ||
64 | @Inject | ||
65 | private NodeNameProvider nameProvider; | ||
66 | |||
71 | private ProblemTrace trace; | 67 | private ProblemTrace trace; |
72 | private Model model; | 68 | private Model model; |
73 | private ReasoningAdapter reasoningAdapter; | 69 | private ReasoningAdapter reasoningAdapter; |
@@ -95,6 +91,7 @@ public class SolutionSerializer { | |||
95 | problem = copyProblem(originalProblem, uri); | 91 | problem = copyProblem(originalProblem, uri); |
96 | problem.getStatements().removeIf(SolutionSerializer::shouldRemoveStatement); | 92 | problem.getStatements().removeIf(SolutionSerializer::shouldRemoveStatement); |
97 | problem.getNodes().removeIf(this::shouldRemoveNode); | 93 | problem.getNodes().removeIf(this::shouldRemoveNode); |
94 | nameProvider.setProblem(problem); | ||
98 | addExistsAssertions(); | 95 | addExistsAssertions(); |
99 | addClassAssertions(); | 96 | addClassAssertions(); |
100 | addReferenceAssertions(); | 97 | addReferenceAssertions(); |
@@ -172,11 +169,6 @@ public class SolutionSerializer { | |||
172 | return findNode(qualifiedName); | 169 | return findNode(qualifiedName); |
173 | } | 170 | } |
174 | 171 | ||
175 | private Node findNode(String name) { | ||
176 | var qualifiedName = qualifiedNameConverter.toQualifiedName(name); | ||
177 | return findNode(qualifiedName); | ||
178 | } | ||
179 | |||
180 | private Node findNode(QualifiedName qualifiedName) { | 172 | private Node findNode(QualifiedName qualifiedName) { |
181 | var scope = scopeProvider.getScope(problem, ProblemPackage.Literals.NODE_ASSERTION_ARGUMENT__NODE); | 173 | var scope = scopeProvider.getScope(problem, ProblemPackage.Literals.NODE_ASSERTION_ARGUMENT__NODE); |
182 | return semanticsUtils.maybeGetElement(problem, scope, qualifiedName, Node.class); | 174 | return semanticsUtils.maybeGetElement(problem, scope, qualifiedName, Node.class); |
@@ -222,19 +214,17 @@ public class SolutionSerializer { | |||
222 | private void addClassAssertions() { | 214 | private void addClassAssertions() { |
223 | var types = trace.getMetamodel().typeHierarchy().getPreservedTypes().keySet().stream() | 215 | var types = trace.getMetamodel().typeHierarchy().getPreservedTypes().keySet().stream() |
224 | .collect(Collectors.toMap(Function.identity(), this::findPartialRelation)); | 216 | .collect(Collectors.toMap(Function.identity(), this::findPartialRelation)); |
225 | var indexMap = ObjectIntMaps.mutable.empty(); | ||
226 | var cursor = model.getInterpretation(TypeHierarchyTranslator.TYPE_SYMBOL).getAll(); | 217 | var cursor = model.getInterpretation(TypeHierarchyTranslator.TYPE_SYMBOL).getAll(); |
227 | while (cursor.move()) { | 218 | while (cursor.move()) { |
228 | var key = cursor.getKey(); | 219 | var key = cursor.getKey(); |
229 | var nodeId = key.get(0); | 220 | var nodeId = key.get(0); |
230 | if (isExistingNode(nodeId)) { | 221 | if (isExistingNode(nodeId)) { |
231 | createNodeAndAssertType(nodeId, cursor.getValue(), types, indexMap); | 222 | createNodeAndAssertType(nodeId, cursor.getValue(), types); |
232 | } | 223 | } |
233 | } | 224 | } |
234 | } | 225 | } |
235 | 226 | ||
236 | private void createNodeAndAssertType(int nodeId, InferredType inferredType, Map<PartialRelation, Relation> types, | 227 | private void createNodeAndAssertType(int nodeId, InferredType inferredType, Map<PartialRelation, Relation> types) { |
237 | MutableObjectIntMap<Object> indexMap) { | ||
238 | var candidateTypeSymbol = inferredType.candidateType(); | 228 | var candidateTypeSymbol = inferredType.candidateType(); |
239 | var candidateRelation = types.get(candidateTypeSymbol); | 229 | var candidateRelation = types.get(candidateTypeSymbol); |
240 | if (candidateRelation instanceof EnumDeclaration) { | 230 | if (candidateRelation instanceof EnumDeclaration) { |
@@ -243,18 +233,8 @@ public class SolutionSerializer { | |||
243 | } | 233 | } |
244 | Node node = nodes.get(nodeId); | 234 | Node node = nodes.get(nodeId); |
245 | if (node == null) { | 235 | if (node == null) { |
246 | String typeName = candidateRelation.getName(); | 236 | var typeName = candidateRelation.getName(); |
247 | if (typeName == null || typeName.isEmpty()) { | 237 | var nodeName = nameProvider.getNextName(typeName); |
248 | typeName = "node"; | ||
249 | } else { | ||
250 | typeName = typeName.substring(0, 1).toLowerCase(Locale.ROOT) + typeName.substring(1); | ||
251 | } | ||
252 | int index = indexMap.getIfAbsent(typeName, 0); | ||
253 | String nodeName; | ||
254 | do { | ||
255 | index++; | ||
256 | nodeName = typeName + index; | ||
257 | } while (findNode(nodeName) != null); | ||
258 | node = ProblemFactory.eINSTANCE.createNode(); | 238 | node = ProblemFactory.eINSTANCE.createNode(); |
259 | node.setName(nodeName); | 239 | node.setName(nodeName); |
260 | problem.getNodes().add(node); | 240 | problem.getNodes().add(node); |