From 115fa8a49771ad00e331612c413e6ef46350e834 Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Sat, 25 Jul 2020 08:38:13 +1000 Subject: [PATCH] add automatic loading of package dependencies by the context --- .../fhir/r5/context/BaseWorkerContext.java | 8 +++ .../hl7/fhir/r5/context/IWorkerContext.java | 56 ++++++++++++++++++- .../fhir/r5/context/SimpleWorkerContext.java | 48 +++++++++++++++- .../hl7/fhir/r5/context/TerminologyCache.java | 4 ++ .../cache/BasePackageCacheManager.java | 5 ++ .../utilities/cache/IPackageCacheManager.java | 9 +++ 6 files changed, 127 insertions(+), 3 deletions(-) diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/BaseWorkerContext.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/BaseWorkerContext.java index acdfe4022..4f388a5fc 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/BaseWorkerContext.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/BaseWorkerContext.java @@ -1603,4 +1603,12 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte return this; } + public String getTxCache() { + return txCache.getFolder(); + } + + public TerminologyClient getTxClient() { + return txClient; + } + } \ No newline at end of file diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/IWorkerContext.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/IWorkerContext.java index e9ec1cc7c..1e16c41ab 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/IWorkerContext.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/IWorkerContext.java @@ -64,10 +64,13 @@ import org.hl7.fhir.r5.terminologies.ValueSetExpander.TerminologyServiceErrorCla import org.hl7.fhir.r5.terminologies.ValueSetExpander.ValueSetExpansionOutcome; import org.hl7.fhir.r5.utils.IResourceValidator; import org.hl7.fhir.utilities.TranslationServices; +import org.hl7.fhir.utilities.cache.BasePackageCacheManager; import org.hl7.fhir.utilities.cache.NpmPackage; import org.hl7.fhir.utilities.validation.ValidationMessage.IssueSeverity; import org.hl7.fhir.utilities.validation.ValidationOptions; +import com.google.gson.JsonSyntaxException; + /** * This is the standard interface used for access to underlying FHIR @@ -150,7 +153,18 @@ public interface IWorkerContext { * @param resource * @return null if not tracking paths */ - String getResourcePath(Resource resource); + String getResourcePath(Resource resource); + + /** + * called when a mew package is being loaded + * + * this is called by loadPacakgeAndDependencies when a new package is loaded + * @param npm + * @return + * @throws IOException + * @throws JsonSyntaxException + */ + IContextResourceLoader getNewLoader(NpmPackage npm) throws JsonSyntaxException, IOException; } @@ -660,7 +674,45 @@ public interface IWorkerContext { public String getLinkForUrl(String corePath, String s); public Map getBinaries(); - void loadFromPackage(NpmPackage pi, IContextResourceLoader loader, String[] types) throws FileNotFoundException, IOException, FHIRException; + /** + * Load relevant resources of the appropriate types (as specified by the loader) from the nominated package + * + * note that the package system uses lazy loading; the loader will be called later when the classes that use the context need the relevant resource + * + * @param pi - the package to load + * @param loader - an implemenation of IContextResourceLoader that knows how to read the resources in the package (e.g. for the appropriate version). + * @return the number of resources loaded + */ + int loadFromPackage(NpmPackage pi, IContextResourceLoader loader) throws FileNotFoundException, IOException, FHIRException; + + /** + * Load relevant resources of the appropriate types (as specified by the loader) from the nominated package + * + * note that the package system uses lazy loading; the loader will be called later when the classes that use the context need the relevant resource + * + * Deprecated - use the simpler method where the types come from the loader. + * + * @param pi - the package to load + * @param loader - an implemenation of IContextResourceLoader that knows how to read the resources in the package (e.g. for the appropriate version). + * @param types - which types of resources to load + * @return the number of resources loaded + */ + @Deprecated + int loadFromPackage(NpmPackage pi, IContextResourceLoader loader, String[] types) throws FileNotFoundException, IOException, FHIRException; + + /** + * Load relevant resources of the appropriate types (as specified by the loader) from the nominated package + * + * note that the package system uses lazy loading; the loader will be called later when the classes that use the context need the relevant resource + * + * This method also loads all the packages that the package depends on (recursively) + * + * @param pi - the package to load + * @param loader - an implemenation of IContextResourceLoader that knows how to read the resources in the package (e.g. for the appropriate version). + * @param pcm - used to find and load additional dependencies + * @return the number of resources loaded + */ + int loadFromPackageAndDependencies(NpmPackage pi, IContextResourceLoader loader, BasePackageCacheManager pcm) throws FileNotFoundException, IOException, FHIRException; public boolean hasPackage(String id, String ver); diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/SimpleWorkerContext.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/SimpleWorkerContext.java index 4f165e63c..a04fb8a1f 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/SimpleWorkerContext.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/SimpleWorkerContext.java @@ -88,6 +88,8 @@ import org.hl7.fhir.utilities.validation.ValidationMessage; import org.hl7.fhir.utilities.validation.ValidationMessage.IssueType; import org.hl7.fhir.utilities.validation.ValidationMessage.Source; +import com.google.gson.JsonObject; + import ca.uhn.fhir.parser.DataFormatException; /* @@ -370,7 +372,46 @@ public class SimpleWorkerContext extends BaseWorkerContext implements IWorkerCon @Override - public void loadFromPackage(NpmPackage pi, IContextResourceLoader loader, String... types) throws FileNotFoundException, IOException, FHIRException { + public int loadFromPackage(NpmPackage pi, IContextResourceLoader loader) throws FileNotFoundException, IOException, FHIRException { + return loadFromPackageInt(pi, loader, loader == null ? defaultTypesToLoad() : loader.getTypes()); + } + + public static String[] defaultTypesToLoad() { + // there's no penalty for listing resources that don't exist, so we just all the relevant possibilities for all versions + return new String[] {"CodeSystem", "ValueSet", "ConceptMap", "NamingSystem", + "StructureDefinition", "StructureMap", + "SearchParameter", "OperationDefinition", "CapabilityStatement", "Conformance", + "Questionnaire", "ImplementationGuide" }; + } + + @Override + public int loadFromPackage(NpmPackage pi, IContextResourceLoader loader, String[] types) throws FileNotFoundException, IOException, FHIRException { + return loadFromPackageInt(pi, loader, types); + } + + @Override + public int loadFromPackageAndDependencies(NpmPackage pi, IContextResourceLoader loader, BasePackageCacheManager pcm) throws FileNotFoundException, IOException, FHIRException { + return loadFromPackageAndDependenciesInt(pi, loader, pcm, pi.name()+"#"+pi.version()); + } + public int loadFromPackageAndDependenciesInt(NpmPackage pi, IContextResourceLoader loader, BasePackageCacheManager pcm, String path) throws FileNotFoundException, IOException, FHIRException { + int t = 0; + + for (String e : pi.dependencies()) { + if (!loadedPackages.contains(e) && !VersionUtilities.isCorePackage(e)) { + NpmPackage npm = pcm.loadPackage(e); + if (!version.equals(npm.fhirVersion())) { + System.out.println(formatMessage(I18nConstants.PACKAGE_VERSION_MISMATCH, e, version, npm.fhirVersion(), path)); + } + t = t + loadFromPackageAndDependenciesInt(npm, loader.getNewLoader(npm), pcm, path+" -> "+npm.name()+"#"+npm.version()); + } + } + t = t + loadFromPackageInt(pi, loader, loader.getTypes()); + return t; + } + + + public int loadFromPackageInt(NpmPackage pi, IContextResourceLoader loader, String... types) throws FileNotFoundException, IOException, FHIRException { + int t = 0; if (progress) { System.out.println("Load Package "+pi.name()+"#"+pi.version()); } @@ -388,6 +429,7 @@ public class SimpleWorkerContext extends BaseWorkerContext implements IWorkerCon for (String s : pi.listResources(loader.getTypes())) { try { loadDefinitionItem(s, pi.load("package", s), loader, null, new PackageVersion(pi.id(), pi.version())); + t++; } catch (FHIRException e) { throw new FHIRException(formatMessage(I18nConstants.ERROR_READING__FROM_PACKAGE__, s, pi.name(), pi.version(), e.getMessage()), e); } @@ -399,6 +441,7 @@ public class SimpleWorkerContext extends BaseWorkerContext implements IWorkerCon for (PackageResourceInformation pri : pi.listIndexedResources(types)) { try { registerResourceFromPackage(new PackageResourceLoader(pri, loader), new PackageVersion(pi.id(), pi.version())); + t++; } catch (FHIRException e) { throw new FHIRException(formatMessage(I18nConstants.ERROR_READING__FROM_PACKAGE__, pri.getFilename(), pi.name(), pi.version(), e.getMessage()), e); } @@ -410,6 +453,7 @@ public class SimpleWorkerContext extends BaseWorkerContext implements IWorkerCon if (version == null) { version = pi.version(); } + return t; } public void loadFromFile(String file, IContextResourceLoader loader) throws IOException, FHIRException { @@ -757,5 +801,7 @@ public class SimpleWorkerContext extends BaseWorkerContext implements IWorkerCon + + } \ No newline at end of file diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/TerminologyCache.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/TerminologyCache.java index 536fd4995..f63fbce99 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/TerminologyCache.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/TerminologyCache.java @@ -469,6 +469,10 @@ public class TerminologyCache { } } } + + public String getFolder() { + return folder; + } } \ No newline at end of file diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/BasePackageCacheManager.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/BasePackageCacheManager.java index 07bdff1a7..549eb5b04 100644 --- a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/BasePackageCacheManager.java +++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/BasePackageCacheManager.java @@ -1,6 +1,7 @@ package org.hl7.fhir.utilities.cache; import org.apache.commons.lang3.Validate; +import org.hl7.fhir.exceptions.FHIRException; import org.hl7.fhir.utilities.Utilities; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -155,4 +156,8 @@ public abstract class BasePackageCacheManager implements IPackageCacheManager { } } + public NpmPackage loadPackage(String idAndVer) throws FHIRException, IOException { + return loadPackage(idAndVer, null); + } + } diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/IPackageCacheManager.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/IPackageCacheManager.java index 8dd49d98e..eaeeebc48 100644 --- a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/IPackageCacheManager.java +++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/IPackageCacheManager.java @@ -14,4 +14,13 @@ public interface IPackageCacheManager { String getPackageUrl(String packageId) throws IOException; NpmPackage loadPackage(String id, String version) throws FHIRException, IOException; + + /** + * + * @param idAndVer - use id#ver + * @return + * @throws FHIRException + * @throws IOException + */ + NpmPackage loadPackage(String idAndVer) throws FHIRException, IOException; }