001package org.hl7.fhir.common.hapi.validation.support; 002 003import ca.uhn.fhir.context.FhirContext; 004import ca.uhn.fhir.rest.server.exceptions.InternalErrorException; 005import ca.uhn.fhir.util.ClasspathUtil; 006import org.hl7.fhir.instance.model.api.IBaseResource; 007import org.hl7.fhir.utilities.TextFile; 008import org.hl7.fhir.utilities.npm.NpmPackage; 009 010import javax.annotation.Nonnull; 011import java.io.IOException; 012import java.io.InputStream; 013import java.nio.charset.StandardCharsets; 014import java.util.List; 015import java.util.Locale; 016 017/** 018 * This interceptor loads and parses FHIR NPM Conformance Packages, and makes the 019 * artifacts foudn within them available to the FHIR validator. 020 * 021 * @since 5.5.0 022 */ 023public class NpmPackageValidationSupport extends PrePopulatedValidationSupport { 024 025 /** 026 * Constructor 027 */ 028 public NpmPackageValidationSupport(@Nonnull FhirContext theFhirContext) { 029 super(theFhirContext); 030 } 031 032 /** 033 * Load an NPM package using a classpath specification, e.g. <code>/path/to/resource/my_package.tgz</code>. The 034 * classpath spec can optionally be prefixed with the string <code>classpath:</code> 035 * 036 * @throws InternalErrorException If the classpath file can't be found 037 */ 038 public void loadPackageFromClasspath(String theClasspath) throws IOException { 039 try (InputStream is = ClasspathUtil.loadResourceAsStream(theClasspath)) { 040 NpmPackage pkg = NpmPackage.fromPackage(is); 041 if (pkg.getFolders().containsKey("package")) { 042 loadResourcesFromPackage(pkg); 043 loadBinariesFromPackage(pkg); 044 } 045 } 046 } 047 048 private void loadResourcesFromPackage(NpmPackage thePackage) { 049 NpmPackage.NpmPackageFolder packageFolder = thePackage.getFolders().get("package"); 050 051 for (String nextFile : packageFolder.listFiles()) { 052 if (nextFile.toLowerCase(Locale.US).endsWith(".json")) { 053 String input = new String(packageFolder.getContent().get(nextFile), StandardCharsets.UTF_8); 054 IBaseResource resource = getFhirContext().newJsonParser().parseResource(input); 055 super.addResource(resource); 056 } 057 } 058 } 059 060 private void loadBinariesFromPackage(NpmPackage thePackage) throws IOException { 061 List<String> binaries = thePackage.list("other"); 062 for (String binaryName : binaries) { 063 addBinary(TextFile.streamToBytes(thePackage.load("other", binaryName)), binaryName); 064 } 065 } 066}