From d720d6badf4e478fbf5fcd955275a7b93629f989 Mon Sep 17 00:00:00 2001 From: Jens Kristian Villadsen Date: Sun, 28 May 2023 22:25:28 +0200 Subject: [PATCH] Refactoring --- pom.xml | 5 +- src/main/java/dk/jkiddo/EmberApplication.java | 175 +++++++----------- 2 files changed, 67 insertions(+), 113 deletions(-) diff --git a/pom.xml b/pom.xml index 5689e73..1945421 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ org.springframework.boot spring-boot-starter-parent - 2.7.11 + 2.7.12 org.jkiddo @@ -26,7 +26,7 @@ 11 11 - 6.4.4 + 6.6.0 @@ -47,7 +47,6 @@ ${hapi_version} - ca.uhn.hapi.fhir hapi-fhir-jpaserver-base diff --git a/src/main/java/dk/jkiddo/EmberApplication.java b/src/main/java/dk/jkiddo/EmberApplication.java index cc1c118..53b5394 100644 --- a/src/main/java/dk/jkiddo/EmberApplication.java +++ b/src/main/java/dk/jkiddo/EmberApplication.java @@ -2,19 +2,12 @@ import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.context.FhirVersionEnum; -import ca.uhn.fhir.i18n.Msg; +import ca.uhn.fhir.jpa.packages.loader.PackageLoaderSvc; import ca.uhn.fhir.rest.client.api.IRestfulClientFactory; import ca.uhn.fhir.rest.client.api.ServerValidationModeEnum; -import ca.uhn.fhir.rest.server.exceptions.InternalErrorException; -import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException; import ca.uhn.fhir.util.BundleBuilder; import com.google.common.base.Strings; -import org.apache.commons.io.IOUtils; -import org.apache.http.client.methods.CloseableHttpResponse; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.conn.HttpClientConnectionManager; -import org.apache.http.impl.client.HttpClientBuilder; -import org.apache.http.impl.conn.BasicHttpClientConnectionManager; +import org.hl7.fhir.instance.model.api.IBaseBundle; import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.utilities.npm.FilesystemPackageCacheManager; import org.hl7.fhir.utilities.npm.IPackageCacheManager; @@ -34,15 +27,11 @@ import java.io.ByteArrayInputStream; import java.io.File; import java.io.IOException; -import java.net.URI; -import java.net.URISyntaxException; import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.Paths; import java.util.Collection; -import java.util.Collections; import java.util.List; -import java.util.Random; +import java.util.Objects; import java.util.concurrent.TimeUnit; import java.util.function.Function; import java.util.function.Predicate; @@ -51,7 +40,7 @@ import static org.awaitility.Awaitility.await; -@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class, SwaggerConfig.class, ElasticsearchRestClientAutoConfiguration.class }) +@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class, SwaggerConfig.class, ElasticsearchRestClientAutoConfiguration.class}) public class EmberApplication implements ApplicationRunner { public static final String PACKAGE_EXAMPLE = "package/example"; @@ -77,50 +66,64 @@ public class EmberApplication implements ApplicationRunner { public static void main(String[] args) { - LOG.info("STARTING THE APPLICATION"); + LOG.info("STARTING EMBER"); SpringApplication.run(EmberApplication.class, args); - LOG.info("APPLICATION FINISHED"); + LOG.info("ENDING EMBER"); } @Override public void run(ApplicationArguments args) throws Exception { - if (!Strings.isNullOrEmpty(directory)) { - loadFilesFromDirectory(directory); - System.exit(1); - } + IBaseBundle resultingExampleBundle; + + if (!Strings.isNullOrEmpty(directory)) + resultingExampleBundle = loadResourcesFromDirectory(new File(directory)); + else + resultingExampleBundle = loadResourcesFromNPM(); + + emitBundle(resultingExampleBundle); + System.exit(0); + } + + @NotNull + private IBaseBundle loadResourcesFromDirectory(File directory) { + + var fhirContext = FhirContext.forR5(); + List resources = Stream.of(Objects.requireNonNull(directory.listFiles())).filter(file -> !file.isDirectory()).filter(file -> file.getName().endsWith(".json")).filter(file -> file.getName().contains("mplementation")).map(f -> { + try { + return new String(Files.readAllBytes(Path.of(f.getPath()))); + } catch (IOException e) { + throw new RuntimeException(e.getMessage(), e); + } + }).map(fhirContext.newJsonParser().setSuppressNarratives(true)::parseResource).collect(Collectors.toList()); + + var bundleBuilder = new BundleBuilder(fhirContext); + resources.forEach(bundleBuilder::addTransactionCreateEntry); + return bundleBuilder.getBundle(); + + } + + @NotNull + private IBaseBundle loadResourcesFromNPM() throws IOException { if (Strings.isNullOrEmpty(packageId) && Strings.isNullOrEmpty(location)) { LOG.error("No packageId or location supplied ... - exiting"); System.exit(-1); } - packageManager = new FilesystemPackageCacheManager(true, new Random().nextInt()); + packageManager = new FilesystemPackageCacheManager(FilesystemPackageCacheManager.FilesystemPackageCacheMode.USER); if (!Strings.isNullOrEmpty(location)) { installPackage(); } - final NpmPackage npmPackage = loadPackage(); - + final NpmPackage npmPackage = packageManager.loadPackage(packageId); fhirContext = new FhirContext(FhirVersionEnum.forVersionString(npmPackage.fhirVersion())); - var clientFactory = fhirContext.getRestfulClientFactory(); - clientFactory.setServerValidationMode(ServerValidationModeEnum.NEVER); - - var bundleBuilder = new BundleBuilder(fhirContext); - loadResources(npmPackage).forEach(bundleBuilder::addTransactionCreateEntry); - - if(!Strings.isNullOrEmpty(serverBase)) { - if (!Strings.isNullOrEmpty(seconds)) { - await().atMost(Integer.parseInt(seconds), TimeUnit.MINUTES).until(() -> serverReady(fhirContext, clientFactory)); - } - } - - emitBundle(bundleBuilder, fhirContext, clientFactory); + return loadResources(npmPackage); } - private Boolean serverReady(FhirContext fhirContext, IRestfulClientFactory clientFactory) { + private Boolean serverReady(IRestfulClientFactory clientFactory) { try { clientFactory.newGenericClient(serverBase).search().forResource("StructureDefinition").execute(); @@ -130,8 +133,17 @@ private Boolean serverReady(FhirContext fhirContext, IRestfulClientFactory clien } } - private void emitBundle(BundleBuilder bundleBuilder, FhirContext fhirContext, IRestfulClientFactory clientFactory) { - var bundle = bundleBuilder.getBundle(); + private void emitBundle(IBaseBundle bundle) { + + var clientFactory = fhirContext.getRestfulClientFactory(); + clientFactory.setServerValidationMode(ServerValidationModeEnum.NEVER); + + + if (!Strings.isNullOrEmpty(serverBase)) { + if (!Strings.isNullOrEmpty(seconds)) { + await().atMost(Integer.parseInt(seconds), TimeUnit.MINUTES).until(() -> serverReady(clientFactory)); + } + } if (Strings.isNullOrEmpty(serverBase)) { LOG.info("Sending transaction bundle to console"); @@ -143,47 +155,18 @@ private void emitBundle(BundleBuilder bundleBuilder, FhirContext fhirContext, IR } } - private NpmPackage loadPackage() throws IOException { - try { - return packageManager.loadPackage(packageId); - } catch (NullPointerException npe) { - LOG.error("Could not load package: " + packageId); - LOG.info(npe.getMessage(), npe); - throw npe; - } - } - private void installPackage() throws IOException { - var npmAsBytes = loadPackageUrlContents(location); + + var npmAsBytes = new PackageLoaderSvc().loadPackageUrlContents(location); var npmPackage = NpmPackage.fromPackage(new ByteArrayInputStream(npmAsBytes)); packageManager.addPackageToCache(npmPackage.id(), npmPackage.version(), new ByteArrayInputStream(npmAsBytes), npmPackage.description()); LOG.warn("Overwriting parameterized packageId with packageId from location paramter. packageId was '" + packageId + "'. New packageId will be '" + npmPackage.id() + "#" + npmPackage.version() + "'"); packageId = npmPackage.id() + "#" + npmPackage.version(); } - private void loadFilesFromDirectory(String directory) { - - var fhirContext = FhirContext.forR5(); - - List resources = Stream.of(new File(directory).listFiles()).filter(file -> !file.isDirectory()).filter(file -> file.getName().endsWith(".json")).filter(file -> file.getName().contains("mplementation")).map(f -> { - try { - return new String(Files.readAllBytes(Path.of(f.getPath()))); - } catch (IOException e) { - throw new RuntimeException(e.getMessage(), e); - } - }).map(fhirContext.newJsonParser().setSuppressNarratives(true)::parseResource).collect(Collectors.toList()); - - var clientFactory = fhirContext.getRestfulClientFactory(); - clientFactory.setServerValidationMode(ServerValidationModeEnum.NEVER); - - var bundleBuilder = new BundleBuilder(fhirContext); - resources.forEach(bundleBuilder::addTransactionCreateEntry); - emitBundle(bundleBuilder, fhirContext, clientFactory); - - } @NotNull - private Collection loadResources(NpmPackage npmPackage) { + private IBaseBundle loadResources(NpmPackage npmPackage) { Collection resources; if (loadRecursively) { resources = loadExampleResourcesRecursively(npmPackage); @@ -194,7 +177,10 @@ private Collection loadResources(NpmPackage npmPackage) { if (!includeSearchBundles) { resources = resources.stream().filter(r -> !isSearchBundle.test(r)).collect(Collectors.toList()); } - return resources; + + var bundleBuilder = new BundleBuilder(fhirContext); + resources.forEach(bundleBuilder::addTransactionCreateEntry); + return bundleBuilder.getBundle(); } private @NotNull Collection loadExampleResourcesRecursively(NpmPackage npmPackage) { @@ -211,7 +197,7 @@ private List loadExampleResources(NpmPackage npmPackage) { if (exampleFolder == null) { LOG.info("Found no example resources in " + npmPackage.name()); - return Collections.EMPTY_LIST; + return List.of(); } var fileNames = exampleFolder.getTypes().values().stream().flatMap(Collection::stream).collect(Collectors.toList()); @@ -226,8 +212,6 @@ private List loadExampleResources(NpmPackage npmPackage) { }).map(fhirContext.newJsonParser().setSuppressNarratives(true)::parseResource).collect(Collectors.toList()); } - Function toContext = (fhirVersionAsString) -> new FhirContext(FhirVersionEnum.forVersionString(fhirVersionAsString)); - Function toNpmPackage = (nameAndVersion) -> { try { return packageManager.loadPackage(nameAndVersion); @@ -237,50 +221,21 @@ private List loadExampleResources(NpmPackage npmPackage) { }; Predicate isSearchBundle = (resource) -> { - if (org.hl7.fhir.dstu2.model.Bundle.class.isInstance(resource)) { + if (resource instanceof org.hl7.fhir.dstu2.model.Bundle) { return ((org.hl7.fhir.dstu2.model.Bundle) resource).getTypeElement().getValue() == org.hl7.fhir.dstu2.model.Bundle.BundleType.SEARCHSET; } - if (org.hl7.fhir.dstu3.model.Bundle.class.isInstance(resource)) { + if (resource instanceof org.hl7.fhir.dstu3.model.Bundle) { return ((org.hl7.fhir.dstu3.model.Bundle) resource).getTypeElement().getValue() == org.hl7.fhir.dstu3.model.Bundle.BundleType.SEARCHSET; } - if (org.hl7.fhir.r4.model.Bundle.class.isInstance(resource)) { + if (resource instanceof org.hl7.fhir.r4.model.Bundle) { return ((org.hl7.fhir.r4.model.Bundle) resource).getTypeElement().getValue() == org.hl7.fhir.r4.model.Bundle.BundleType.SEARCHSET; } - if (org.hl7.fhir.r4b.model.Bundle.class.isInstance(resource)) { + if (resource instanceof org.hl7.fhir.r4b.model.Bundle) { return ((org.hl7.fhir.r4b.model.Bundle) resource).getTypeElement().getValue() == org.hl7.fhir.r4b.model.Bundle.BundleType.SEARCHSET; } - if (org.hl7.fhir.r5.model.Bundle.class.isInstance(resource)) { + if (resource instanceof org.hl7.fhir.r5.model.Bundle) { return ((org.hl7.fhir.r5.model.Bundle) resource).getTypeElement().getValue() == org.hl7.fhir.r5.model.Bundle.BundleType.SEARCHSET; } return false; }; - - /** - * Copied and modified from ca.uhn.fhir.jpa.packages.JpaPackageCache in order to have some - * consistency - * - * @param thePackageUrl - * @return - */ - protected byte[] loadPackageUrlContents(String thePackageUrl) { - final byte[] bytes; - if (thePackageUrl.startsWith("file:")) { - try { - bytes = Files.readAllBytes(Paths.get(new URI(thePackageUrl))); - } catch (IOException | URISyntaxException e) { - throw new InternalErrorException(Msg.code(2024) + "Error loading \"" + thePackageUrl + "\": " + e.getMessage()); - } - } else { - HttpClientConnectionManager connManager = new BasicHttpClientConnectionManager(); - try (CloseableHttpResponse request = HttpClientBuilder.create().setConnectionManager(connManager).build().execute(new HttpGet(thePackageUrl))) { - if (request.getStatusLine().getStatusCode() != 200) { - throw new ResourceNotFoundException(Msg.code(1303) + "Received HTTP " + request.getStatusLine().getStatusCode() + " from URL: " + thePackageUrl); - } - bytes = IOUtils.toByteArray(request.getEntity().getContent()); - } catch (IOException e) { - throw new InternalErrorException(Msg.code(1304) + "Error loading \"" + thePackageUrl + "\": " + e.getMessage()); - } - } - return bytes; - } }