diff options
Diffstat (limited to 'subprojects/language/src/main/java/tools/refinery/language/library/ClasspathBasedLibrary.java')
-rw-r--r-- | subprojects/language/src/main/java/tools/refinery/language/library/ClasspathBasedLibrary.java | 92 |
1 files changed, 92 insertions, 0 deletions
diff --git a/subprojects/language/src/main/java/tools/refinery/language/library/ClasspathBasedLibrary.java b/subprojects/language/src/main/java/tools/refinery/language/library/ClasspathBasedLibrary.java new file mode 100644 index 00000000..56bb8b96 --- /dev/null +++ b/subprojects/language/src/main/java/tools/refinery/language/library/ClasspathBasedLibrary.java | |||
@@ -0,0 +1,92 @@ | |||
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.library; | ||
7 | |||
8 | import org.eclipse.emf.common.util.URI; | ||
9 | import org.eclipse.xtext.naming.QualifiedName; | ||
10 | |||
11 | import java.nio.file.Path; | ||
12 | import java.util.*; | ||
13 | |||
14 | public abstract class ClasspathBasedLibrary implements RefineryLibrary { | ||
15 | private final Class<?> context; | ||
16 | private final QualifiedName prefix; | ||
17 | private final URI rootUri; | ||
18 | |||
19 | protected ClasspathBasedLibrary(Class<?> context, QualifiedName prefix) { | ||
20 | this.context = context == null ? getClass() : context; | ||
21 | this.prefix = prefix; | ||
22 | var contextPath = this.context.getCanonicalName().replace('.', '/') + ".class"; | ||
23 | var contextResource = this.context.getClassLoader().getResource(contextPath); | ||
24 | if (contextResource == null) { | ||
25 | throw new IllegalStateException("Failed to find library context"); | ||
26 | } | ||
27 | var contextUri = URI.createURI(contextResource.toString()); | ||
28 | var segments = Arrays.copyOf(contextUri.segments(), contextUri.segmentCount() - 1); | ||
29 | rootUri = URI.createHierarchicalURI(contextUri.scheme(), contextUri.authority(), contextUri.device(), | ||
30 | segments, null, null); | ||
31 | } | ||
32 | |||
33 | protected ClasspathBasedLibrary(QualifiedName prefix) { | ||
34 | this(null, prefix); | ||
35 | } | ||
36 | |||
37 | @Override | ||
38 | public Optional<URI> resolveQualifiedName(QualifiedName qualifiedName, List<Path> libraryPaths) { | ||
39 | if (qualifiedName.startsWith(prefix)) { | ||
40 | return getLibraryUri(context, qualifiedName); | ||
41 | } | ||
42 | return Optional.empty(); | ||
43 | } | ||
44 | |||
45 | @Override | ||
46 | public Optional<QualifiedName> getQualifiedName(URI uri, List<Path> libraryPaths) { | ||
47 | if (!uri.isHierarchical() || | ||
48 | !Objects.equals(rootUri.scheme(), uri.scheme()) || | ||
49 | !Objects.equals(rootUri.authority(), uri.authority()) || | ||
50 | !Objects.equals(rootUri.device(), uri.device()) || | ||
51 | rootUri.segmentCount() >= uri.segmentCount()) { | ||
52 | return Optional.empty(); | ||
53 | } | ||
54 | int rootSegmentCount = rootUri.segmentCount(); | ||
55 | int uriSegmentCount = uri.segmentCount(); | ||
56 | if (!uri.segment(uriSegmentCount - 1).endsWith(RefineryLibrary.FILE_NAME_SUFFIX)) { | ||
57 | return Optional.empty(); | ||
58 | } | ||
59 | var segments = new ArrayList<String>(); | ||
60 | int i = 0; | ||
61 | while (i < rootSegmentCount) { | ||
62 | if (!rootUri.segment(i).equals(uri.segment(i))) { | ||
63 | return Optional.empty(); | ||
64 | } | ||
65 | i++; | ||
66 | } | ||
67 | while (i < uriSegmentCount) { | ||
68 | var segment = uri.segment(i); | ||
69 | if (i == uriSegmentCount - 1) { | ||
70 | segment = segment.substring(0, segment.length() - RefineryLibrary.FILE_NAME_SUFFIX.length()); | ||
71 | } | ||
72 | segments.add(segment); | ||
73 | i++; | ||
74 | } | ||
75 | var qualifiedName = QualifiedName.create(segments); | ||
76 | if (!qualifiedName.startsWith(prefix)) { | ||
77 | return Optional.empty(); | ||
78 | } | ||
79 | return Optional.of(qualifiedName); | ||
80 | } | ||
81 | |||
82 | public static Optional<URI> getLibraryUri(Class<?> context, QualifiedName qualifiedName) { | ||
83 | var packagePath = context.getPackageName().replace('.', '/'); | ||
84 | var libraryPath = String.join("/", qualifiedName.getSegments()); | ||
85 | var resourceName = "%s/%s%s".formatted(packagePath, libraryPath, RefineryLibrary.FILE_NAME_SUFFIX); | ||
86 | var resource = context.getClassLoader().getResource(resourceName); | ||
87 | if (resource == null) { | ||
88 | return Optional.empty(); | ||
89 | } | ||
90 | return Optional.of(URI.createURI(resource.toString())); | ||
91 | } | ||
92 | } | ||