aboutsummaryrefslogtreecommitdiffstats
path: root/subprojects/language/src/main/java/tools/refinery/language/library/ClasspathBasedLibrary.java
diff options
context:
space:
mode:
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.java92
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 */
6package tools.refinery.language.library;
7
8import org.eclipse.emf.common.util.URI;
9import org.eclipse.xtext.naming.QualifiedName;
10
11import java.nio.file.Path;
12import java.util.*;
13
14public 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}