aboutsummaryrefslogtreecommitdiffstats
path: root/subprojects/language/src/main/java/tools/refinery/language/library/PathLibrary.java
diff options
context:
space:
mode:
Diffstat (limited to 'subprojects/language/src/main/java/tools/refinery/language/library/PathLibrary.java')
-rw-r--r--subprojects/language/src/main/java/tools/refinery/language/library/PathLibrary.java90
1 files changed, 90 insertions, 0 deletions
diff --git a/subprojects/language/src/main/java/tools/refinery/language/library/PathLibrary.java b/subprojects/language/src/main/java/tools/refinery/language/library/PathLibrary.java
new file mode 100644
index 00000000..8eaf8458
--- /dev/null
+++ b/subprojects/language/src/main/java/tools/refinery/language/library/PathLibrary.java
@@ -0,0 +1,90 @@
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.Files;
12import java.nio.file.Path;
13import java.util.ArrayList;
14import java.util.List;
15import java.util.Optional;
16
17public final class PathLibrary implements RefineryLibrary {
18 @Override
19 public Optional<URI> resolveQualifiedName(QualifiedName qualifiedName, List<Path> libraryPaths) {
20 if (libraryPaths.isEmpty()) {
21 return Optional.empty();
22 }
23 if (qualifiedName.getSegmentCount() == 0) {
24 return Optional.empty();
25 }
26 var relativePath = qualifiedNameToRelativePath(qualifiedName);
27 for (var library : libraryPaths) {
28 var absoluteResolvedPath = library.resolve(relativePath).toAbsolutePath().normalize();
29 if (absoluteResolvedPath.startsWith(library) && Files.exists(absoluteResolvedPath)) {
30 var uri = URI.createFileURI(absoluteResolvedPath.toString());
31 return Optional.of(uri);
32 }
33 }
34 return Optional.empty();
35 }
36
37 private static Path qualifiedNameToRelativePath(QualifiedName qualifiedName) {
38 int segmentCount = qualifiedName.getSegmentCount();
39 String first = null;
40 var rest = new String[segmentCount - 1];
41 for (var i = 0; i < segmentCount; i++) {
42 var segment = qualifiedName.getSegment(i);
43 if (i == segmentCount - 1) {
44 segment = segment + RefineryLibrary.FILE_NAME_SUFFIX;
45 }
46 if (i == 0) {
47 first = segment;
48 } else {
49 rest[i - 1] = segment;
50 }
51 }
52 if (first == null) {
53 throw new AssertionError("Expected qualified name to have non-null segments");
54 }
55 return Path.of(first, rest);
56 }
57
58 @Override
59 public Optional<QualifiedName> getQualifiedName(URI uri, List<Path> libraryPaths) {
60 if (libraryPaths.isEmpty()) {
61 return Optional.empty();
62 }
63 if (!uri.isFile() || !uri.hasAbsolutePath()) {
64 return Optional.empty();
65 }
66 var path = Path.of(uri.toFileString());
67 for (var library : libraryPaths) {
68 if (path.startsWith(library)) {
69 return getRelativeQualifiedName(library, path);
70 }
71 }
72 return Optional.empty();
73 }
74
75 private static Optional<QualifiedName> getRelativeQualifiedName(Path library, Path path) {
76 var relativePath = path.relativize(library);
77 var segments = new ArrayList<String>();
78 for (Path value : relativePath) {
79 segments.add(value.toString());
80 }
81 int lastIndex = segments.size() - 1;
82 var lastSegment = segments.get(lastIndex);
83 if (!lastSegment.endsWith(FILE_NAME_SUFFIX)) {
84 return Optional.empty();
85 }
86 lastSegment = lastSegment.substring(0, lastSegment.length() - RefineryLibrary.FILE_NAME_SUFFIX.length());
87 segments.set(lastIndex, lastSegment);
88 return Optional.of(QualifiedName.create(segments));
89 }
90}