|
1 | 1 | package de.medizininformatikinitiative.torch.management;
|
2 | 2 |
|
| 3 | +import de.medizininformatikinitiative.torch.util.CompiledStructureDefinition; |
3 | 4 | import de.medizininformatikinitiative.torch.util.ResourceReader;
|
| 5 | +import jakarta.annotation.PostConstruct; |
4 | 6 | import org.hl7.fhir.r4.model.StructureDefinition;
|
5 |
| -import org.springframework.stereotype.Component; |
6 | 7 |
|
7 | 8 | import java.io.File;
|
8 | 9 | import java.io.IOException;
|
|
12 | 13 | import java.util.Optional;
|
13 | 14 | import java.util.Set;
|
14 | 15 |
|
| 16 | +import static java.util.Objects.requireNonNull; |
| 17 | + |
15 | 18 | /**
|
16 |
| - * Handler for loading and serving structure definitions. |
| 19 | + * Handler for loading and serving FHIR structure definitions. |
17 | 20 | */
|
18 |
| -@Component |
19 | 21 | public class StructureDefinitionHandler {
|
20 | 22 |
|
21 |
| - private final Map<String, StructureDefinition> definitions = new HashMap<>(); |
| 23 | + private final Map<String, CompiledStructureDefinition> definitions = new HashMap<>(); |
22 | 24 | private final ResourceReader resourceReader;
|
| 25 | + private final File directory; |
23 | 26 |
|
24 |
| - public StructureDefinitionHandler(String fileDirectory, ResourceReader resourceReader) { |
25 |
| - try { |
26 |
| - this.resourceReader = resourceReader; |
27 |
| - processDirectory(fileDirectory); |
28 |
| - } catch (IOException e) { |
29 |
| - throw new RuntimeException(e); |
30 |
| - } |
| 27 | + /** |
| 28 | + * Creates a new StructureDefinitionHandler. |
| 29 | + * |
| 30 | + * @param directory the directory containing JSON structure definition files |
| 31 | + * @param resourceReader utility for reading and parsing FHIR resources |
| 32 | + */ |
| 33 | + public StructureDefinitionHandler(File directory, ResourceReader resourceReader) { |
| 34 | + this.resourceReader = requireNonNull(resourceReader); |
| 35 | + this.directory = requireNonNull(directory); |
31 | 36 | }
|
32 | 37 |
|
33 | 38 | /**
|
34 |
| - * @param profile to check if known |
35 |
| - * @return returns if profile is known. |
| 39 | + * Reads all JSON files in a directory and stores their StructureDefinitions. |
| 40 | + * |
| 41 | + * @throws IOException if any file cannot be read or parsed |
36 | 42 | */
|
37 |
| - public Boolean known(String profile) { |
38 |
| - return definitions.containsKey(profile); |
| 43 | + @PostConstruct |
| 44 | + public void processDirectory() throws IOException { |
| 45 | + if (directory.isDirectory()) { |
| 46 | + File[] files = directory.listFiles((dir, name) -> name.toLowerCase().endsWith(".json")); |
| 47 | + if (files != null) { |
| 48 | + for (File file : files) { |
| 49 | + readStructureDefinition(file.getAbsolutePath()); |
| 50 | + } |
| 51 | + } |
| 52 | + } |
39 | 53 | }
|
40 | 54 |
|
41 | 55 | /**
|
42 |
| - * Reads a StructureDefinition from a file and stores it in the definitionsMap |
| 56 | + * Checks if a profile URL is known to this handler. |
| 57 | + * |
| 58 | + * @param profile the profile URL to check |
| 59 | + * @return true if the profile is known, false otherwise |
43 | 60 | */
|
44 |
| - public void readStructureDefinition(String filePath) throws IOException { |
45 |
| - StructureDefinition structureDefinition = (StructureDefinition) resourceReader.readResource(filePath); |
46 |
| - definitions.put(structureDefinition.getUrl(), structureDefinition); |
| 61 | + public boolean known(String profile) { |
| 62 | + return definitions.containsKey(stripVersion(profile)); |
47 | 63 | }
|
48 | 64 |
|
49 | 65 | /**
|
50 | 66 | * Returns the StructureDefinition with the given URL.
|
51 | 67 | * Handles versioned URLs by splitting on the '|' character.
|
52 | 68 | *
|
53 |
| - * @param url The URL of the StructureDefinition, possibly including a version. |
54 |
| - * @return The StructureDefinition corresponding to the base URL (ignores version). |
| 69 | + * @param url The URL of the StructureDefinition, possibly including a version |
| 70 | + * @return The StructureDefinition corresponding to the base URL (ignores version) |
55 | 71 | */
|
56 |
| - public StructureDefinition getDefinition(String url) { |
57 |
| - String[] versionSplit = url.split("\\|"); |
58 |
| - return definitions.get(versionSplit[0]); |
| 72 | + public Optional<CompiledStructureDefinition> getDefinition(String url) { |
| 73 | + return getDefinition(Set.of(url)); |
59 | 74 | }
|
60 | 75 |
|
61 | 76 | /**
|
62 |
| - * Returns the first non-null StructureDefinition from a list of URLs. |
63 |
| - * <p> |
| 77 | + * Returns the first found StructureDefinition from a list of URLs. |
64 | 78 | * Iterates over the list of URLs, returning the first valid StructureDefinition.
|
| 79 | + * Removes version flags making the handling version agnostic. |
65 | 80 | *
|
66 |
| - * @param urls a list of URLs for which to find the corresponding StructureDefinition. |
67 |
| - * @return The first non-null StructureDefinition found, or empty if none are found. |
| 81 | + * @param urls a list of URLs for which to find the corresponding StructureDefinition |
| 82 | + * @return the first StructureDefinition found, or empty if none are found |
68 | 83 | */
|
69 |
| - public Optional<StructureDefinition> getDefinition(Set<String> urls) { |
70 |
| - return urls.stream().map(definitions::get).filter(Objects::nonNull).findFirst(); |
| 84 | + public Optional<CompiledStructureDefinition> getDefinition(Set<String> urls) { |
| 85 | + return urls.stream() |
| 86 | + .map(this::stripVersion) |
| 87 | + .map(definitions::get) |
| 88 | + .filter(Objects::nonNull) |
| 89 | + .findFirst(); |
71 | 90 | }
|
72 | 91 |
|
73 |
| - public StructureDefinition.StructureDefinitionSnapshotComponent getSnapshot(String url) { |
74 |
| - if (definitions.get(url) != null) { |
75 |
| - return (definitions.get(url)).getSnapshot(); |
76 |
| - } else { |
77 |
| - throw new IllegalArgumentException("Unknown Profile: " + url); |
78 |
| - } |
79 |
| - } |
80 |
| - |
81 |
| - public String getResourceType(String url) { |
82 |
| - if (definitions.get(url) != null) { |
83 |
| - return (definitions.get(url)).getType(); |
84 |
| - } else { |
85 |
| - throw new IllegalArgumentException("Unknown Profile: " + url); |
86 |
| - } |
| 92 | + /** |
| 93 | + * Reads a StructureDefinition from a file and stores it in the definitions map. |
| 94 | + * |
| 95 | + * @param filePath the absolute path to the JSON file |
| 96 | + * @throws IOException if the file cannot be read or parsed |
| 97 | + */ |
| 98 | + private void readStructureDefinition(String filePath) throws IOException { |
| 99 | + StructureDefinition structureDefinition = (StructureDefinition) resourceReader.readResource(filePath); |
| 100 | + definitions.put(structureDefinition.getUrl(), CompiledStructureDefinition.fromStructureDefinition(structureDefinition)); |
87 | 101 | }
|
88 | 102 |
|
89 | 103 | /**
|
90 |
| - * Reads all JSON files in a directory and stores their StructureDefinitions in the definitionsMap |
| 104 | + * Strips version information from a FHIR canonical URL. |
| 105 | + * |
| 106 | + * @param url the potentially versioned URL |
| 107 | + * @return the URL with version information removed |
91 | 108 | */
|
92 |
| - private void processDirectory(String directoryPath) throws IOException { |
93 |
| - File directory = new File(directoryPath); |
94 |
| - if (directory.isDirectory()) { |
95 |
| - File[] files = directory.listFiles((dir, name) -> name.toLowerCase().endsWith(".json")); |
96 |
| - if (files != null) { |
97 |
| - for (File file : files) { |
98 |
| - readStructureDefinition(file.getAbsolutePath()); |
99 |
| - } |
100 |
| - } |
101 |
| - } |
| 109 | + private String stripVersion(String url) { |
| 110 | + int pipeIndex = url.indexOf('|'); |
| 111 | + return pipeIndex == -1 ? url : url.substring(0, pipeIndex); |
102 | 112 | }
|
103 | 113 | }
|
0 commit comments