aboutsummaryrefslogtreecommitdiffstats
path: root/subprojects/language/src/main/java/tools/refinery/language/scoping/NormalizedSelectable.java
diff options
context:
space:
mode:
Diffstat (limited to 'subprojects/language/src/main/java/tools/refinery/language/scoping/NormalizedSelectable.java')
-rw-r--r--subprojects/language/src/main/java/tools/refinery/language/scoping/NormalizedSelectable.java109
1 files changed, 109 insertions, 0 deletions
diff --git a/subprojects/language/src/main/java/tools/refinery/language/scoping/NormalizedSelectable.java b/subprojects/language/src/main/java/tools/refinery/language/scoping/NormalizedSelectable.java
new file mode 100644
index 00000000..09fe4716
--- /dev/null
+++ b/subprojects/language/src/main/java/tools/refinery/language/scoping/NormalizedSelectable.java
@@ -0,0 +1,109 @@
1/*
2 * SPDX-FileCopyrightText: 2024 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.language.scoping;
7
8import com.google.common.collect.Iterables;
9import org.eclipse.emf.ecore.EClass;
10import org.eclipse.emf.ecore.EObject;
11import org.eclipse.xtext.naming.QualifiedName;
12import org.eclipse.xtext.resource.IEObjectDescription;
13import org.eclipse.xtext.resource.ISelectable;
14import org.eclipse.xtext.resource.impl.AliasedEObjectDescription;
15
16import java.util.Iterator;
17import java.util.List;
18import java.util.NoSuchElementException;
19
20class NormalizedSelectable implements ISelectable {
21 private final ISelectable delegateSelectable;
22 private final QualifiedName originalPrefix;
23 private final QualifiedName normalizedPrefix;
24
25 public NormalizedSelectable(ISelectable delegateSelectable, QualifiedName originalPrefix,
26 QualifiedName normalizedPrefix) {
27 if (originalPrefix.equals(QualifiedName.EMPTY)) {
28 throw new IllegalArgumentException("Cannot normalize empty qualified name prefix");
29 }
30 this.delegateSelectable = delegateSelectable;
31 this.originalPrefix = originalPrefix;
32 this.normalizedPrefix = normalizedPrefix;
33 }
34
35 @Override
36 public boolean isEmpty() {
37 return delegateSelectable.isEmpty();
38 }
39
40 @Override
41 public Iterable<IEObjectDescription> getExportedObjects() {
42 var delegateIterable = delegateSelectable.getExportedObjects();
43 return getAliasedElements(delegateIterable);
44 }
45
46 @Override
47 public Iterable<IEObjectDescription> getExportedObjects(EClass type, QualifiedName name, boolean ignoreCase) {
48 boolean startsWith = ignoreCase ? name.startsWithIgnoreCase(normalizedPrefix) :
49 name.startsWith(normalizedPrefix);
50 if (startsWith && name.getSegmentCount() > normalizedPrefix.getSegmentCount()) {
51 var originalName = originalPrefix.append(name.skipFirst(normalizedPrefix.getSegmentCount()));
52 return Iterables.transform(
53 delegateSelectable.getExportedObjects(type, originalName, ignoreCase),
54 description -> {
55 var normalizedName = normalizedPrefix.append(
56 description.getName().skipFirst(originalPrefix.getSegmentCount()));
57 return new AliasedEObjectDescription(normalizedName, description);
58 });
59 }
60 return List.of();
61 }
62
63 @Override
64 public Iterable<IEObjectDescription> getExportedObjectsByType(EClass type) {
65 var delegateIterable = delegateSelectable.getExportedObjectsByType(type);
66 return getAliasedElements(delegateIterable);
67 }
68
69 @Override
70 public Iterable<IEObjectDescription> getExportedObjectsByObject(EObject object) {
71 var delegateIterable = delegateSelectable.getExportedObjectsByObject(object);
72 return getAliasedElements(delegateIterable);
73 }
74
75 private Iterable<IEObjectDescription> getAliasedElements(Iterable<IEObjectDescription> delegateIterable) {
76 return () -> new Iterator<>() {
77 private final Iterator<IEObjectDescription> delegateIterator = delegateIterable.iterator();
78 private IEObjectDescription next = computeNext();
79
80 @Override
81 public boolean hasNext() {
82 return next != null;
83 }
84
85 @Override
86 public IEObjectDescription next() {
87 if (!hasNext()) {
88 throw new NoSuchElementException();
89 }
90 var current = next;
91 next = computeNext();
92 return current;
93 }
94
95 private IEObjectDescription computeNext() {
96 while (delegateIterator.hasNext()) {
97 var description = delegateIterator.next();
98 var qualifiedName = description.getName();
99 if (qualifiedName.startsWith(originalPrefix) &&
100 qualifiedName.getSegmentCount() > originalPrefix.getSegmentCount()) {
101 var alias = normalizedPrefix.append(qualifiedName.skipFirst(originalPrefix.getSegmentCount()));
102 return new AliasedEObjectDescription(alias, description);
103 }
104 }
105 return null;
106 }
107 };
108 }
109}