diff --git a/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/loaders/R2016MayToR5Loader.java b/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/loaders/R2016MayToR5Loader.java index e257b3c3d..2ee771e1b 100644 --- a/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/loaders/R2016MayToR5Loader.java +++ b/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/loaders/R2016MayToR5Loader.java @@ -48,8 +48,11 @@ import org.hl7.fhir.r5.context.IWorkerContext.IContextResourceLoader; import org.hl7.fhir.r5.model.Bundle; import org.hl7.fhir.r5.model.Bundle.BundleEntryComponent; import org.hl7.fhir.r5.model.Bundle.BundleType; +import org.hl7.fhir.r5.model.ElementDefinition.TypeRefComponent; import org.hl7.fhir.r5.model.CanonicalResource; +import org.hl7.fhir.r5.model.CanonicalType; import org.hl7.fhir.r5.model.CodeSystem; +import org.hl7.fhir.r5.model.ElementDefinition; import org.hl7.fhir.r5.model.StructureDefinition; import org.hl7.fhir.r5.model.StructureDefinition.StructureDefinitionKind; import org.hl7.fhir.r5.model.UriType; @@ -112,7 +115,46 @@ public class R2016MayToR5Loader extends BaseLoader implements IContextResourceLo } return b; } + + @Override + public org.hl7.fhir.r5.model.Resource loadResource(InputStream stream, boolean isJson) throws FHIRException, IOException { + Resource r2016may = null; + if (isJson) + r2016may = new JsonParser().parse(stream); + else + r2016may = new XmlParser().parse(stream); + org.hl7.fhir.r5.model.Resource r5 = VersionConvertor_14_50.convertResource(r2016may); + if (!cslist.isEmpty()) { + throw new FHIRException("Error: Cannot have included code systems"); + } + if (killPrimitives) { + throw new FHIRException("Cannot kill primitives when using deferred loading"); + } + if (patchUrls) { + if (r5 instanceof StructureDefinition) { + StructureDefinition sd = (StructureDefinition) r5; + sd.setUrl(sd.getUrl().replace("http://hl7.org/fhir/", "http://hl7.org/fhir/4.0/")); + sd.addExtension().setUrl("http://hl7.org/fhir/StructureDefinition/elementdefinition-namespace").setValue(new UriType("http://hl7.org/fhir")); + for (ElementDefinition ed : sd.getSnapshot().getElement()) + patchUrl(ed); + for (ElementDefinition ed : sd.getDifferential().getElement()) + patchUrl(ed); + } + } + return r5; + } + private void patchUrl(ElementDefinition ed) { + for (TypeRefComponent tr : ed.getType()) { + for (CanonicalType s : tr.getTargetProfile()) { + s.setValue(s.getValue().replace("http://hl7.org/fhir/", "http://hl7.org/fhir/1.4/")); + } + for (CanonicalType s : tr.getProfile()) { + s.setValue(s.getValue().replace("http://hl7.org/fhir/", "http://hl7.org/fhir/1.4/")); + } + } + } + @Override public boolean ignoreEntry(BundleEntryComponent src) { return false; diff --git a/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/loaders/R2ToR5Loader.java b/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/loaders/R2ToR5Loader.java index 34e060e70..5bdb040c8 100644 --- a/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/loaders/R2ToR5Loader.java +++ b/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/loaders/R2ToR5Loader.java @@ -47,8 +47,11 @@ import org.hl7.fhir.r5.context.IWorkerContext.IContextResourceLoader; import org.hl7.fhir.r5.model.Bundle; import org.hl7.fhir.r5.model.Bundle.BundleEntryComponent; import org.hl7.fhir.r5.model.Bundle.BundleType; +import org.hl7.fhir.r5.model.ElementDefinition.TypeRefComponent; import org.hl7.fhir.r5.model.CanonicalResource; +import org.hl7.fhir.r5.model.CanonicalType; import org.hl7.fhir.r5.model.CodeSystem; +import org.hl7.fhir.r5.model.ElementDefinition; import org.hl7.fhir.r5.model.StructureDefinition; import org.hl7.fhir.r5.model.StructureDefinition.StructureDefinitionKind; import org.hl7.fhir.r5.model.UriType; @@ -112,6 +115,46 @@ public class R2ToR5Loader extends BaseLoader implements IContextResourceLoader, return b; } + + @Override + public org.hl7.fhir.r5.model.Resource loadResource(InputStream stream, boolean isJson) throws FHIRException, IOException { + Resource r2 = null; + if (isJson) + r2 = new JsonParser().parse(stream); + else + r2 = new XmlParser().parse(stream); + org.hl7.fhir.r5.model.Resource r5 = VersionConvertor_10_50.convertResource(r2, this); + if (!cslist.isEmpty()) { + throw new FHIRException("Error: Cannot have included code systems"); + } + if (killPrimitives) { + throw new FHIRException("Cannot kill primitives when using deferred loading"); + } + if (patchUrls) { + if (r5 instanceof StructureDefinition) { + StructureDefinition sd = (StructureDefinition) r5; + sd.setUrl(sd.getUrl().replace("http://hl7.org/fhir/", "http://hl7.org/fhir/4.0/")); + sd.addExtension().setUrl("http://hl7.org/fhir/StructureDefinition/elementdefinition-namespace").setValue(new UriType("http://hl7.org/fhir")); + for (ElementDefinition ed : sd.getSnapshot().getElement()) + patchUrl(ed); + for (ElementDefinition ed : sd.getDifferential().getElement()) + patchUrl(ed); + } + } + return r5; + } + + private void patchUrl(ElementDefinition ed) { + for (TypeRefComponent tr : ed.getType()) { + for (CanonicalType s : tr.getTargetProfile()) { + s.setValue(s.getValue().replace("http://hl7.org/fhir/", "http://hl7.org/fhir/1.0/")); + } + for (CanonicalType s : tr.getProfile()) { + s.setValue(s.getValue().replace("http://hl7.org/fhir/", "http://hl7.org/fhir/1.0/")); + } + } + } + @Override public boolean ignoreEntry(BundleEntryComponent src) { return false; diff --git a/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/loaders/R3ToR5Loader.java b/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/loaders/R3ToR5Loader.java index 517802c26..fb23a379a 100644 --- a/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/loaders/R3ToR5Loader.java +++ b/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/loaders/R3ToR5Loader.java @@ -116,6 +116,34 @@ public class R3ToR5Loader extends BaseLoader implements IContextResourceLoader, } return b; } + + @Override + public org.hl7.fhir.r5.model.Resource loadResource(InputStream stream, boolean isJson) throws FHIRException, IOException { + Resource r3 = null; + if (isJson) + r3 = new JsonParser().parse(stream); + else + r3 = new XmlParser().parse(stream); + org.hl7.fhir.r5.model.Resource r5 = VersionConvertor_30_50.convertResource(r3, false); + if (!cslist.isEmpty()) { + throw new FHIRException("Error: Cannot have included code systems"); + } + if (killPrimitives) { + throw new FHIRException("Cannot kill primitives when using deferred loading"); + } + if (patchUrls) { + if (r5 instanceof StructureDefinition) { + StructureDefinition sd = (StructureDefinition) r5; + sd.setUrl(sd.getUrl().replace("http://hl7.org/fhir/", "http://hl7.org/fhir/4.0/")); + sd.addExtension().setUrl("http://hl7.org/fhir/StructureDefinition/elementdefinition-namespace").setValue(new UriType("http://hl7.org/fhir")); + for (ElementDefinition ed : sd.getSnapshot().getElement()) + patchUrl(ed); + for (ElementDefinition ed : sd.getDifferential().getElement()) + patchUrl(ed); + } + } + return r5; + } private void patchUrl(ElementDefinition ed) { for (TypeRefComponent tr : ed.getType()) { diff --git a/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/loaders/R4ToR5Loader.java b/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/loaders/R4ToR5Loader.java index 6ce212d8b..b584214bf 100644 --- a/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/loaders/R4ToR5Loader.java +++ b/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/loaders/R4ToR5Loader.java @@ -117,6 +117,35 @@ public class R4ToR5Loader extends BaseLoader implements IContextResourceLoader, return b; } + + @Override + public org.hl7.fhir.r5.model.Resource loadResource(InputStream stream, boolean isJson) throws FHIRException, IOException { + Resource r4 = null; + if (isJson) + r4 = new JsonParser().parse(stream); + else + r4 = new XmlParser().parse(stream); + org.hl7.fhir.r5.model.Resource r5 = VersionConvertor_40_50.convertResource(r4); + if (!cslist.isEmpty()) { + throw new FHIRException("Error: Cannot have included code systems"); + } + if (killPrimitives) { + throw new FHIRException("Cannot kill primitives when using deferred loading"); + } + if (patchUrls) { + if (r5 instanceof StructureDefinition) { + StructureDefinition sd = (StructureDefinition) r5; + sd.setUrl(sd.getUrl().replace("http://hl7.org/fhir/", "http://hl7.org/fhir/4.0/")); + sd.addExtension().setUrl("http://hl7.org/fhir/StructureDefinition/elementdefinition-namespace").setValue(new UriType("http://hl7.org/fhir")); + for (ElementDefinition ed : sd.getSnapshot().getElement()) + patchUrl(ed); + for (ElementDefinition ed : sd.getDifferential().getElement()) + patchUrl(ed); + } + } + return r5; + } + private void patchUrl(ElementDefinition ed) { for (TypeRefComponent tr : ed.getType()) { for (CanonicalType s : tr.getTargetProfile()) { diff --git a/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/loaders/R5ToR5Loader.java b/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/loaders/R5ToR5Loader.java index d101430ca..b22ed296f 100644 --- a/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/loaders/R5ToR5Loader.java +++ b/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/loaders/R5ToR5Loader.java @@ -115,6 +115,35 @@ public class R5ToR5Loader extends BaseLoader implements IContextResourceLoader, return b; } + @Override + public Resource loadResource(InputStream stream, boolean isJson) throws FHIRException, IOException { + Resource r5 = null; + if (isJson) + r5 = new JsonParser().parse(stream); + else + r5 = new XmlParser().parse(stream); + + if (!cslist.isEmpty()) { + throw new FHIRException("Error: Cannot have included code systems"); + } + if (killPrimitives) { + throw new FHIRException("Cannot kill primitives when using deferred loading"); + } + if (patchUrls) { + if (r5 instanceof StructureDefinition) { + StructureDefinition sd = (StructureDefinition) r5; + sd.setUrl(sd.getUrl().replace("http://hl7.org/fhir/", "http://hl7.org/fhir/4.0/")); + sd.addExtension().setUrl("http://hl7.org/fhir/StructureDefinition/elementdefinition-namespace").setValue(new UriType("http://hl7.org/fhir")); + for (ElementDefinition ed : sd.getSnapshot().getElement()) + patchUrl(ed); + for (ElementDefinition ed : sd.getDifferential().getElement()) + patchUrl(ed); + } + } + return r5; + } + + private void patchUrl(ElementDefinition ed) { for (TypeRefComponent tr : ed.getType()) { for (CanonicalType s : tr.getTargetProfile()) { 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 589a369ba..bc88d2009 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 @@ -49,6 +49,7 @@ import org.hl7.fhir.exceptions.DefinitionException; import org.hl7.fhir.exceptions.FHIRException; import org.hl7.fhir.exceptions.TerminologyServiceException; import org.hl7.fhir.r5.conformance.ProfileUtilities; +import org.hl7.fhir.r5.context.CanonicalResourceManager.CanonicalResourceProxy; import org.hl7.fhir.r5.context.IWorkerContext.ILoggingService.LogCategory; import org.hl7.fhir.r5.context.TerminologyCache.CacheToken; import org.hl7.fhir.r5.model.BooleanType; @@ -160,7 +161,8 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte private CanonicalResourceManager questionnaires = new CanonicalResourceManager(false); private CanonicalResourceManager operations = new CanonicalResourceManager(false); private CanonicalResourceManager plans = new CanonicalResourceManager(false); - private List systems = new ArrayList(); + private CanonicalResourceManager systems = new CanonicalResourceManager(false); + private UcumService ucumService; protected Map binaries = new HashMap(); @@ -216,7 +218,7 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte plans.copy(other.plans); questionnaires.copy(other.questionnaires); operations.copy(other.operations); - systems.addAll(other.systems); + systems.copy(other.systems); guides.copy(other.guides); capstmts.copy(other.capstmts); measures.copy(other.measures); @@ -246,6 +248,55 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte cacheResourceFromPackage(r, null); } + + public void registerResourceFromPackage(CanonicalResourceProxy r, PackageVersion packageInfo) throws FHIRException { + synchronized (lock) { + + String url = r.getUrl(); + if (!allowLoadingDuplicates && hasResource(r.getType(), url)) { + // spcial workaround for known problems with existing packages + if (Utilities.existsInList(url, "http://hl7.org/fhir/SearchParameter/example")) { + return; + } + throw new DefinitionException(formatMessage(I18nConstants.DUPLICATE_RESOURCE_, url)); + } + if ("StructureDefinition".equals(r.getType())) { + StructureDefinition sd = (StructureDefinition) r.getResource(); + if ("1.4.0".equals(version)) { + fixOldSD(sd); + } + structures.register(r, packageInfo); + } else if ("ValueSet".equals(r.getType())) { + valueSets.register(r, packageInfo); + } else if ("CodeSystem".equals(r.getType())) { + codeSystems.register(r, packageInfo); + } else if ("ImplementationGuide".equals(r.getType())) { + guides.register(r, packageInfo); + } else if ("CapabilityStatement".equals(r.getType())) { + capstmts.register(r, packageInfo); + } else if ("Measure".equals(r.getType())) { + measures.register(r, packageInfo); + } else if ("Library".equals(r.getType())) { + libraries.register(r, packageInfo); + } else if ("SearchParameter".equals(r.getType())) { + searchParameters.register(r, packageInfo); + } else if ("PlanDefinition".equals(r.getType())) { + plans.register(r, packageInfo); + } else if ("OperationDefinition".equals(r.getType())) { + operations.register(r, packageInfo); + } else if ("Questionnaire".equals(r.getType())) { + questionnaires.register(r, packageInfo); + } else if ("ConceptMap".equals(r.getType())) { + maps.register(r, packageInfo); + } else if ("StructureMap".equals(r.getType())) { + transforms.register(r, packageInfo); + } else if ("NamingSystem".equals(r.getType())) { + systems.register(r, packageInfo); + } + + } + } + public void cacheResourceFromPackage(Resource r, PackageVersion packageInfo) throws FHIRException { synchronized (lock) { Map map = allResourcesById.get(r.fhirType()); @@ -297,7 +348,7 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte else if (r instanceof StructureMap) transforms.see((StructureMap) m, packageInfo); else if (r instanceof NamingSystem) - systems.add((NamingSystem) r); + systems.see((NamingSystem) m, packageInfo); } } } @@ -842,6 +893,10 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte return fetchResourceWithException(class_, uri, null); } + public T fetchResourceWithException(String cls, String uri) throws FHIRException { + return fetchResourceWithException(cls, uri, null); + } + @SuppressWarnings("unchecked") public T fetchResourceWithException(Class class_, String uri, CanonicalResource source) throws FHIRException { if (uri == null) { @@ -950,6 +1005,114 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte } } + @SuppressWarnings("unchecked") + public T fetchResourceWithException(String cls, String uri, CanonicalResource source) throws FHIRException { + if (uri == null) { + return null; + } + + if ("StructureDefinition".equals(cls)) { + uri = ProfileUtilities.sdNs(uri, getOverrideVersionNs()); + } + synchronized (lock) { + + String version = null; + if (uri.contains("|")) { + version = uri.substring(uri.lastIndexOf("|")+1); + uri = uri.substring(0, uri.lastIndexOf("|")); + } + if (uri.contains("#")) + uri = uri.substring(0, uri.indexOf("#")); + if (cls == null || "Resource".equals(cls)) { + if (structures.has(uri)) + return (T) structures.get(uri, version); + if (guides.has(uri)) + return (T) guides.get(uri, version); + if (capstmts.has(uri)) + return (T) capstmts.get(uri, version); + if (measures.has(uri)) + return (T) measures.get(uri, version); + if (libraries.has(uri)) + return (T) libraries.get(uri, version); + if (valueSets.has(uri)) + return (T) valueSets.get(uri, version); + if (codeSystems.has(uri)) + return (T) codeSystems.get(uri, version); + if (operations.has(uri)) + return (T) operations.get(uri, version); + if (searchParameters.has(uri)) + return (T) searchParameters.get(uri, version); + if (plans.has(uri)) + return (T) plans.get(uri, version); + if (maps.has(uri)) + return (T) maps.get(uri, version); + if (transforms.has(uri)) + return (T) transforms.get(uri, version); + if (questionnaires.has(uri)) + return (T) questionnaires.get(uri, version); + for (Map rt : allResourcesById.values()) { + for (Resource r : rt.values()) { + if (r instanceof CanonicalResource) { + CanonicalResource mr = (CanonicalResource) r; + if (uri.equals(mr.getUrl())) + return (T) mr; + } + } + } + } else if ("ImplementationGuide".equals(cls)) { + return (T) guides.get(uri, version); + } else if ("CapabilityStatement".equals(cls)) { + return (T) capstmts.get(uri, version); + } else if ("Measure".equals(cls)) { + return (T) measures.get(uri, version); + } else if ("Library".equals(cls)) { + return (T) libraries.get(uri, version); + } else if ("StructureDefinition".equals(cls)) { + return (T) structures.get(uri, version); + } else if ("StructureMap".equals(cls)) { + return (T) transforms.get(uri, version); + } else if ("ValueSet".equals(cls)) { + return (T) valueSets.get(uri, version); + } else if ("CodeSystem".equals(cls)) { + return (T) codeSystems.get(uri, version); + } else if ("ConceptMap".equals(cls)) { + return (T) maps.get(uri, version); + } else if ("PlanDefinition".equals(cls)) { + return (T) plans.get(uri, version); + } else if ("OperationDefinition".equals(cls)) { + OperationDefinition od = operations.get(uri, version); + return (T) od; + } else if ("Questionnaire.class".equals(cls)) { + return (T) questionnaires.get(uri, version); + } else if ("SearchParameter.class".equals(cls)) { + SearchParameter res = searchParameters.get(uri, version); + return (T) res; + } + if ("CodeSystem".equals(cls) && codeSystems.has(uri)) + return (T) codeSystems.get(uri, version); + if ("ValueSet".equals(cls) && valueSets.has(uri)) + return (T) valueSets.get(uri, version); + + if ("Questionnaire".equals(cls)) + return (T) questionnaires.get(uri, version); + if (cls == null) { + if (uri.matches(Constants.URI_REGEX) && !uri.contains("ValueSet")) + return null; + + // it might be a special URL. + if (Utilities.isAbsoluteUrl(uri) || uri.startsWith("ValueSet/")) { + Resource res = null; // findTxValueSet(uri); + if (res != null) + return (T) res; + } + return null; + } + if (supportedCodeSystems.contains(uri)) + return null; + throw new FHIRException(formatMessage(I18nConstants.NOT_DONE_YET_CANT_FETCH_, uri)); + } + } + private Set notCanonical = new HashSet(); private String overrideVersionNs; @@ -1024,6 +1187,14 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte } } + public boolean hasResource(String cls, String uri) { + try { + return fetchResourceWithException(cls, uri) != null; + } catch (Exception e) { + return false; + } + } + public TranslationServices translator() { return translator; @@ -1104,33 +1275,31 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte if (map.containsKey(id)) map.remove(id); - if (fhirType.equals("StructureDefinition")) + if (fhirType.equals("StructureDefinition")) { structures.drop(id); - else if (fhirType.equals("ImplementationGuide")) + } else if (fhirType.equals("ImplementationGuide")) { guides.drop(id); - else if (fhirType.equals("CapabilityStatement")) + } else if (fhirType.equals("CapabilityStatement")) { capstmts.drop(id); - else if (fhirType.equals("Measure")) + } else if (fhirType.equals("Measure")) { measures.drop(id); - else if (fhirType.equals("Library")) + } else if (fhirType.equals("Library")) { libraries.drop(id); - else if (fhirType.equals("ValueSet")) + } else if (fhirType.equals("ValueSet")) { valueSets.drop(id); - else if (fhirType.equals("CodeSystem")) + } else if (fhirType.equals("CodeSystem")) { codeSystems.drop(id); - else if (fhirType.equals("OperationDefinition")) + } else if (fhirType.equals("OperationDefinition")) { operations.drop(id); - else if (fhirType.equals("Questionnaire")) + } else if (fhirType.equals("Questionnaire")) { questionnaires.drop(id); - else if (fhirType.equals("ConceptMap")) + } else if (fhirType.equals("ConceptMap")) { maps.drop(id); - else if (fhirType.equals("StructureMap")) + } else if (fhirType.equals("StructureMap")) { transforms.drop(id); - else if (fhirType.equals("NamingSystem")) - for (int i = systems.size()-1; i >= 0; i--) { - if (systems.get(i).getId().equals(id)) - systems.remove(i); - } + } else if (fhirType.equals("NamingSystem")) { + systems.drop(id); + } } } @@ -1227,7 +1396,7 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte String uri = OIDUtils.getUriForOid(oid); if (uri != null) return uri; - for (NamingSystem ns : systems) { + for (NamingSystem ns : systems.getList()) { if (hasOid(ns, oid)) { uri = getUri(ns); if (uri != null) diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/CanonicalResourceManager.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/CanonicalResourceManager.java index 89acfc37a..465bffcee 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/CanonicalResourceManager.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/CanonicalResourceManager.java @@ -9,8 +9,12 @@ import java.util.Map; import java.util.Set; import java.util.UUID; +import org.hl7.fhir.exceptions.FHIRException; +import org.hl7.fhir.r5.context.CanonicalResourceManager.CanonicalResourceProxy; import org.hl7.fhir.r5.context.IWorkerContext.PackageVersion; import org.hl7.fhir.r5.model.CanonicalResource; +import org.hl7.fhir.r5.model.CodeSystem; +import org.hl7.fhir.r5.terminologies.CodeSystemUtilities; import org.hl7.fhir.utilities.VersionUtilities; /** @@ -23,6 +27,66 @@ import org.hl7.fhir.utilities.VersionUtilities; public class CanonicalResourceManager { + public static abstract class CanonicalResourceProxy { + private String type; + private String id; + private String url; + private String version; + private CanonicalResource resource; + + public CanonicalResourceProxy(String type, String id, String url, String version) { + super(); + this.type = type; + this.id = id; + this.url = url; + this.version = version; + } + + public String getType() { + return type; + } + + public String getId() { + return id; + } + + public String getUrl() { + return url; + } + + public String getVersion() { + return version; + } + + public boolean hasId() { + return id != null; + } + + public boolean hasUrl() { + return url != null; + } + + public boolean hasVersion() { + return version != null; + } + + public CanonicalResource getResource() throws FHIRException { + if (resource == null) { + resource = loadResource(); + if (resource instanceof CodeSystem) { + CodeSystemUtilities.crossLinkCodeSystem((CodeSystem) resource); + } + } + return resource; + } + + public void setResource(CanonicalResource resource) { + this.resource = resource; + } + + public abstract CanonicalResource loadResource() throws FHIRException; + } + public class CanonicalListSorter implements Comparator { @Override @@ -35,37 +99,54 @@ public class CanonicalResourceManager { private class CachedCanonicalResource { private T1 resource; + private CanonicalResourceProxy proxy; private PackageVersion packageInfo; + public CachedCanonicalResource(T1 resource, PackageVersion packageInfo) { super(); this.resource = resource; this.packageInfo = packageInfo; } + + public CachedCanonicalResource(CanonicalResourceProxy proxy, PackageVersion packageInfo) { + super(); + this.proxy = proxy; + this.packageInfo = packageInfo; + } + public T1 getResource() { + if (resource == null) { + @SuppressWarnings("unchecked") + T1 res = (T1) proxy.getResource(); + synchronized (this) { + resource = res; + } + } return resource; } + public PackageVersion getPackageInfo() { return packageInfo; } public String getUrl() { - return resource.getUrl(); + return resource != null ? resource.getUrl() : proxy.getUrl(); } public String getId() { - return resource.getId(); + return resource != null ? resource.getId() : proxy.getId(); } public String getVersion() { - return resource.getVersion(); + return resource != null ? resource.getVersion() : proxy.getVersion(); } public boolean hasVersion() { - return resource.hasVersion(); + return resource != null ? resource.hasVersion() : proxy.getVersion() != null; } } public class MetadataResourceVersionComparator> implements Comparator { @Override public int compare(T1 arg1, T1 arg2) { - String v1 = arg1.getResource().getVersion(); - String v2 = arg2.getResource().getVersion(); + String v1 = arg1.getVersion(); + String v2 = arg2.getVersion(); if (v1 == null && v2 == null) { return Integer.compare(list.indexOf(arg1), list.indexOf(arg2)); // retain original order } else if (v1 == null) { @@ -86,7 +167,7 @@ public class CanonicalResourceManager { private boolean enforceUniqueId; private List> list = new ArrayList<>(); - private Map map = new HashMap<>(); + private Map> map = new HashMap<>(); public CanonicalResourceManager(boolean enforceUniqueId) { @@ -101,18 +182,31 @@ public class CanonicalResourceManager { map.putAll(source.map); } + public void register(CanonicalResourceProxy r, PackageVersion packgeInfo) { + if (!r.hasId()) { + throw new FHIRException("An id is required for a deferred load resource"); + } + CanonicalResourceManager.CachedCanonicalResource cr = new CachedCanonicalResource(r, packgeInfo); + see(cr); + } + public void see(T r, PackageVersion packgeInfo) { if (!r.hasId()) { r.setId(UUID.randomUUID().toString()); } - if (enforceUniqueId && map.containsKey(r.getId())) { - drop(r.getId()); + CanonicalResourceManager.CachedCanonicalResource cr = new CachedCanonicalResource(r, packgeInfo); + see(cr); + } + + public void see(CachedCanonicalResource cr) { + if (enforceUniqueId && map.containsKey(cr.getId())) { + drop(cr.getId()); } // special case logic for UTG support prior to version 5 - if (packgeInfo != null && packgeInfo.getId().startsWith("hl7.terminology")) { + if (cr.getPackageInfo() != null && cr.getPackageInfo().getId().startsWith("hl7.terminology")) { List> toDrop = new ArrayList<>(); for (CachedCanonicalResource n : list) { - if (n.getResource().getUrl().equals(r.getUrl()) && isBasePackage(n.getPackageInfo())) { + if (n.getUrl().equals(cr.getUrl()) && isBasePackage(n.getPackageInfo())) { toDrop.add(n); } } @@ -120,15 +214,15 @@ public class CanonicalResourceManager { drop(n.getId()); } } - list.add(new CachedCanonicalResource(r, packgeInfo)); - map.put(r.getId(), r); // we do this so we can drop by id + list.add(cr); + map.put(cr.getId(), cr); // we do this so we can drop by id - if (r.hasUrl()) { + if (cr.getUrl() != null) { // first, this is the correct reosurce for this version (if it has a version) - if (r.hasVersion()) { - map.put(r.getUrl()+"|"+r.getVersion(), r); + if (cr.hasVersion()) { + map.put(cr.getUrl()+"|"+cr.getVersion(), cr); } - updateList(r.getUrl(), r.getVersion()); + updateList(cr.getUrl(), cr.getVersion()); } } @@ -147,19 +241,19 @@ public class CanonicalResourceManager { // sort by version as much as we are able Collections.sort(rl, new MetadataResourceVersionComparator>()); // the current is the latest - map.put(url, rl.get(rl.size()-1).getResource()); + map.put(url, rl.get(rl.size()-1)); // now, also, the latest for major/minor if (version != null) { - T latest = null; + CachedCanonicalResource latest = null; for (CachedCanonicalResource t : rl) { - if (VersionUtilities.versionsCompatible(t.getResource().getVersion(), version)) { - latest = t.getResource(); + if (VersionUtilities.versionsCompatible(t.getVersion(), version)) { + latest = t; } } if (latest != null) { // might be null if it's not using semver String lv = VersionUtilities.getMajMin(latest.getVersion()); if (lv != null && !lv.equals(version)) - map.put(url+"|"+lv, rl.get(rl.size()-1).getResource()); + map.put(url+"|"+lv, rl.get(rl.size()-1)); } } } @@ -167,7 +261,7 @@ public class CanonicalResourceManager { public T get(String url) { - return map.get(url); + return map.containsKey(url) ? map.get(url).getResource() : null; } public boolean has(String url) { @@ -179,10 +273,10 @@ public class CanonicalResourceManager { return get(system); } else { if (map.containsKey(system+"|"+version)) - return map.get(system+"|"+version); + return map.get(system+"|"+version).getResource(); String mm = VersionUtilities.getMajMin(version); - if (mm != null) - return map.get(system+"|"+mm); + if (mm != null && map.containsKey(system+"|"+mm)) + return map.get(system+"|"+mm).getResource(); else return null; } 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 6ad572941..20ee06e40 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 @@ -119,7 +119,7 @@ public interface IWorkerContext { public interface IContextResourceLoader { Bundle loadBundle(InputStream stream, boolean isJson) throws FHIRException, IOException; - + Resource loadResource(InputStream stream, boolean isJson) throws FHIRException, IOException; String[] getTypes(); } 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 28be4fb2c..5fb764b9b 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 @@ -53,7 +53,9 @@ import org.hl7.fhir.exceptions.FHIRException; import org.hl7.fhir.exceptions.FHIRFormatError; import org.hl7.fhir.r5.conformance.ProfileUtilities; import org.hl7.fhir.r5.conformance.ProfileUtilities.ProfileKnowledgeProvider; +import org.hl7.fhir.r5.context.CanonicalResourceManager.CanonicalResourceProxy; import org.hl7.fhir.r5.context.IWorkerContext.ILoggingService.LogCategory; +import org.hl7.fhir.r5.context.SimpleWorkerContext.PackageResourceLoader; import org.hl7.fhir.r5.formats.IParser; import org.hl7.fhir.r5.formats.JsonParser; import org.hl7.fhir.r5.formats.ParserType; @@ -77,6 +79,7 @@ import org.hl7.fhir.utilities.CSFileInputStream; import org.hl7.fhir.utilities.TextFile; import org.hl7.fhir.utilities.Utilities; import org.hl7.fhir.utilities.cache.NpmPackage; +import org.hl7.fhir.utilities.cache.NpmPackage.PackageResourceInformation; import org.hl7.fhir.utilities.i18n.I18nConstants; import org.hl7.fhir.utilities.validation.ValidationMessage; import org.hl7.fhir.utilities.validation.ValidationMessage.IssueType; @@ -92,10 +95,39 @@ import ca.uhn.fhir.parser.DataFormatException; public class SimpleWorkerContext extends BaseWorkerContext implements IWorkerContext, ProfileKnowledgeProvider { + public class PackageResourceLoader extends CanonicalResourceProxy { + + private String filename; + private IContextResourceLoader loader; + + public PackageResourceLoader(PackageResourceInformation pri, IContextResourceLoader loader) { + super(pri.getType(), pri.getId(), pri.getUrl(),pri.getVersion()); + this.filename = pri.getFilename(); + this.loader = loader; + } + + @Override + public CanonicalResource loadResource() { + try { + FileInputStream f = new FileInputStream(filename); + try { + if (loader != null) { + return (CanonicalResource) loader.loadResource(f, true); + } else { + return (CanonicalResource) new JsonParser().parse(f); + } + } finally { + f.close(); + } + } catch (FHIRFormatError | IOException e) { + throw new FHIRException("Error loading "+filename+": "+e.getMessage(), e); + } + } + } + public interface ILoadFilter { - boolean isOkToLoad(Resource resource); - + boolean isOkToLoad(String resourceType); } public interface IValidatorFactory { @@ -159,6 +191,7 @@ public class SimpleWorkerContext extends BaseWorkerContext implements IWorkerCon public static SimpleWorkerContext fromPackage(NpmPackage pi, boolean allowDuplicates) throws FileNotFoundException, IOException, FHIRException { return fromPackage(pi, allowDuplicates, null); } + public static SimpleWorkerContext fromPackage(NpmPackage pi, boolean allowDuplicates, ILoadFilter filter) throws FileNotFoundException, IOException, FHIRException { SimpleWorkerContext res = new SimpleWorkerContext(); res.setAllowLoadingDuplicates(allowDuplicates); @@ -328,11 +361,12 @@ public class SimpleWorkerContext extends BaseWorkerContext implements IWorkerCon System.out.println("Load Package "+pi.name()+"#"+pi.version()); } loadedPackages.add(pi.id()+"#"+pi.version()); - for (String s : pi.listResources(loader.getTypes())) { + String [] types = loader != null ? loader.getTypes() : new String[] { "StructureDefinition", "ValueSet", "CodeSystem", "SearchParameter", "OperationDefinition", "Questionnaire", "ConceptMap", "StructureMap", "NamingSystem" }; + for (PackageResourceInformation pri : pi.listIndexedResources(types)) { try { - loadDefinitionItem(s, pi.load("package", s), loader, filter, new PackageVersion(pi.id(), pi.version())); - } catch (FHIRException | IOException e) { - throw new FHIRException(formatMessage(I18nConstants.ERROR_READING__FROM_PACKAGE__, s, pi.name(), pi.version(), e.getMessage()), e); + registerResourceFromPackage(new PackageResourceLoader(pri, loader), new PackageVersion(pi.id(), pi.version())); + } catch (FHIRException e) { + throw new FHIRException(formatMessage(I18nConstants.ERROR_READING__FROM_PACKAGE__, pri.getFilename(), pi.name(), pi.version(), e.getMessage()), e); } } for (String s : pi.list("other")) { @@ -349,10 +383,18 @@ public class SimpleWorkerContext extends BaseWorkerContext implements IWorkerCon System.out.println("Load Package "+pi.name()+"#"+pi.version()); } loadedPackages.add(pi.id()+"#"+pi.version()); - if (types.length == 0) + if (types.length == 0 && loader != null) { + types = loader.getTypes(); + } + if (types.length == 0) { types = new String[] { "StructureDefinition", "ValueSet", "CodeSystem", "SearchParameter", "OperationDefinition", "Questionnaire", "ConceptMap", "StructureMap", "NamingSystem" }; - for (String s : pi.listResources(types)) { - loadDefinitionItem(s, pi.load("package", s), loader, null, new PackageVersion(pi.id(), pi.version())); + } + for (PackageResourceInformation pri : pi.listIndexedResources(types)) { + try { + registerResourceFromPackage(new PackageResourceLoader(pri, loader), new PackageVersion(pi.id(), pi.version())); + } catch (FHIRException e) { + throw new FHIRException(formatMessage(I18nConstants.ERROR_READING__FROM_PACKAGE__, pri.getFilename(), pi.name(), pi.version(), e.getMessage()), e); + } } for (String s : pi.list("other")) { binaries.put(s, TextFile.streamToBytes(pi.load("other", s))); diff --git a/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/CanonicalResourceManagerTester.java b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/CanonicalResourceManagerTester.java index de13c9137..4fa9422ba 100644 --- a/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/CanonicalResourceManagerTester.java +++ b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/CanonicalResourceManagerTester.java @@ -1,13 +1,30 @@ package org.hl7.fhir.r5.test; import org.hl7.fhir.r5.context.CanonicalResourceManager; +import org.hl7.fhir.r5.context.CanonicalResourceManager.CanonicalResourceProxy; import org.hl7.fhir.r5.context.IWorkerContext.PackageVersion; +import org.hl7.fhir.r5.model.CanonicalResource; import org.hl7.fhir.r5.model.ValueSet; +import org.hl7.fhir.r5.test.CanonicalResourceManagerTester.DeferredLoadTestResource; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; public class CanonicalResourceManagerTester { + public class DeferredLoadTestResource extends CanonicalResourceProxy { + private CanonicalResource resource; + + public DeferredLoadTestResource(CanonicalResource resource) { + super(resource.fhirType(), resource.getId(), resource.getUrl(), resource.getVersion()); + this.resource = resource; + } + + @Override + public CanonicalResource loadResource() { + return resource; + } + } + @Test public void testSingleNoVersion() { CanonicalResourceManager mrm = new CanonicalResourceManager<>(true); @@ -157,8 +174,7 @@ public class CanonicalResourceManagerTester { Assertions.assertNull(mrm.get("http://url/ValueSet/234", "4.0.1")); Assertions.assertNull(mrm.get("http://url/ValueSet/234", "4.0.2")); Assertions.assertNull(mrm.get("http://url/ValueSet/234", "4.0")); - Assertions.assertNull(mrm.get("http://url/ValueSet/234", "4.1")); - + Assertions.assertNull(mrm.get("http://url/ValueSet/234", "4.1")); } @Test @@ -422,4 +438,376 @@ public class CanonicalResourceManagerTester { Assertions.assertTrue(mrm.get("http://terminology.hl7.org/ValueSet/234").getName().equals("2")); Assertions.assertNull(mrm.get("http://terminology.hl7.org/ValueSet/234", "2.0.0")); // this will get dropped completely because of UTG rules } + + @Test + public void testSingleNoVersionDeferredLoad() { + CanonicalResourceManager mrm = new CanonicalResourceManager<>(true); + ValueSet vs = new ValueSet(); + vs.setId("2345"); + vs.setUrl("http://url/ValueSet/234"); + // no version + DeferredLoadTestResource vsd = new DeferredLoadTestResource(vs); + + mrm.clear(); + mrm.register(vsd, null); + + Assertions.assertEquals(mrm.size(), 1); + Assertions.assertNotNull(mrm.get("http://url/ValueSet/234")); + Assertions.assertNotNull(mrm.get("2345")); + Assertions.assertNull(mrm.get("http://url/ValueSet/234", "4.0.0")); + mrm.register(vsd, null); + Assertions.assertEquals(mrm.size(), 1); + Assertions.assertNotNull(mrm.get("http://url/ValueSet/234")); + Assertions.assertNotNull(mrm.get("2345")); + Assertions.assertNull(mrm.get("http://url/ValueSet/234", "4.0.0")); + + mrm.drop("2344"); + Assertions.assertEquals(mrm.size(), 1); + Assertions.assertNotNull(mrm.get("http://url/ValueSet/234")); + Assertions.assertNotNull(mrm.get("2345")); + Assertions.assertNull(mrm.get("http://url/ValueSet/234", "4.0.0")); + + mrm.drop("2345"); + Assertions.assertEquals(mrm.size(), 0); + Assertions.assertNull(mrm.get("http://url/ValueSet/234")); + Assertions.assertNull(mrm.get("2345")); + Assertions.assertNull(mrm.get("http://url/ValueSet/234", "4.0.0")); + } + + @Test + public void testSingleWithVersionDeferredLoad() { + CanonicalResourceManager mrm = new CanonicalResourceManager<>(true); + ValueSet vs = new ValueSet(); + vs.setId("2345"); + vs.setUrl("http://url/ValueSet/234"); + vs.setVersion("4.0.1"); + DeferredLoadTestResource vsd = new DeferredLoadTestResource(vs); + + mrm.clear(); + mrm.register(vsd, null); + + Assertions.assertNotNull(mrm.get("2345")); + Assertions.assertNotNull(mrm.get("http://url/ValueSet/234")); + Assertions.assertNotNull(mrm.get("http://url/ValueSet/234", "4.0.0")); + Assertions.assertNotNull(mrm.get("http://url/ValueSet/234", "4.0.1")); + Assertions.assertNotNull(mrm.get("http://url/ValueSet/234", "4.0.2")); + Assertions.assertNotNull(mrm.get("http://url/ValueSet/234", "4.0")); + Assertions.assertNull(mrm.get("http://url/ValueSet/234", "4.1")); + } + + @Test + public void testSingleWithVersionNotSemVerDeferredLoad() { + CanonicalResourceManager mrm = new CanonicalResourceManager<>(true); + ValueSet vs = new ValueSet(); + vs.setId("2345"); + vs.setUrl("http://url/ValueSet/234"); + vs.setVersion("20140403"); + DeferredLoadTestResource vsd = new DeferredLoadTestResource(vs); + + mrm.clear(); + mrm.register(vsd, null); + + Assertions.assertNotNull(mrm.get("2345")); + Assertions.assertNotNull(mrm.get("http://url/ValueSet/234")); + Assertions.assertNotNull(mrm.get("http://url/ValueSet/234", "20140403")); + Assertions.assertNull(mrm.get("http://url/ValueSet/234", "20140402")); + Assertions.assertNull(mrm.get("http://url/ValueSet/234", "2014")); + } + + @Test + public void testSingleWithDuplicateIds1DeferredLoad() { + CanonicalResourceManager mrm = new CanonicalResourceManager<>(false); + ValueSet vs1 = new ValueSet(); + vs1.setId("2345"); + vs1.setUrl("http://url/ValueSet/234"); + vs1.setVersion("4.0.1"); + vs1.setName("1"); + DeferredLoadTestResource vs1d = new DeferredLoadTestResource(vs1); + + ValueSet vs2 = new ValueSet(); + vs2.setId("2345"); + vs2.setUrl("http://url/ValueSet/234"); + vs2.setVersion("4.0.2"); + vs2.setName("2"); + DeferredLoadTestResource vs2d = new DeferredLoadTestResource(vs2); + + mrm.clear(); + mrm.register(vs1d, null); + + Assertions.assertEquals(mrm.size(), 1); + Assertions.assertNotNull(mrm.get("2345")); + Assertions.assertEquals(mrm.get("2345").getName(), "1"); + Assertions.assertNotNull(mrm.get("http://url/ValueSet/234")); + Assertions.assertEquals(mrm.get("http://url/ValueSet/234").getName(), "1"); + Assertions.assertNotNull(mrm.get("http://url/ValueSet/234", "4.0.0")); + Assertions.assertEquals(mrm.get("http://url/ValueSet/234", "4.0.0").getName(), "1"); + Assertions.assertNotNull(mrm.get("http://url/ValueSet/234", "4.0.1")); + Assertions.assertEquals(mrm.get("http://url/ValueSet/234", "4.0.1").getName(), "1"); + Assertions.assertNotNull(mrm.get("http://url/ValueSet/234", "4.0.2")); + Assertions.assertEquals(mrm.get("http://url/ValueSet/234", "4.0.2").getName(), "1"); + Assertions.assertNotNull(mrm.get("http://url/ValueSet/234", "4.0")); + Assertions.assertEquals(mrm.get("http://url/ValueSet/234", "4.0").getName(), "1"); + Assertions.assertNull(mrm.get("http://url/ValueSet/234", "4.1")); + + mrm.register(vs2d, null); + + Assertions.assertEquals(mrm.size(), 2); + Assertions.assertNotNull(mrm.get("2345")); + Assertions.assertEquals(mrm.get("2345").getName(), "2"); + + Assertions.assertNotNull(mrm.get("http://url/ValueSet/234")); + Assertions.assertEquals(mrm.get("http://url/ValueSet/234").getName(), "2"); + Assertions.assertNotNull(mrm.get("http://url/ValueSet/234", "4.0.0")); + Assertions.assertEquals(mrm.get("http://url/ValueSet/234", "4.0.0").getName(), "2"); + Assertions.assertNotNull(mrm.get("http://url/ValueSet/234", "4.0.1")); + Assertions.assertEquals(mrm.get("http://url/ValueSet/234", "4.0.1").getName(), "1"); + Assertions.assertNotNull(mrm.get("http://url/ValueSet/234", "4.0.2")); + Assertions.assertEquals(mrm.get("http://url/ValueSet/234", "4.0.2").getName(), "2"); + Assertions.assertNotNull(mrm.get("http://url/ValueSet/234", "4.0")); + Assertions.assertEquals(mrm.get("http://url/ValueSet/234", "4.0").getName(), "2"); + Assertions.assertNull(mrm.get("http://url/ValueSet/234", "4.1")); + + mrm.drop("2346"); // doesn't exist; + Assertions.assertEquals(mrm.size(), 2); + Assertions.assertNotNull(mrm.get("2345")); + Assertions.assertNull(mrm.get("2346")); + Assertions.assertEquals(mrm.get("2345").getName(), "2"); + Assertions.assertNotNull(mrm.get("http://url/ValueSet/234")); + Assertions.assertEquals(mrm.get("http://url/ValueSet/234").getName(), "2"); + Assertions.assertNotNull(mrm.get("http://url/ValueSet/234", "4.0.0")); + Assertions.assertEquals(mrm.get("http://url/ValueSet/234", "4.0.0").getName(), "2"); + Assertions.assertNotNull(mrm.get("http://url/ValueSet/234", "4.0.1")); + Assertions.assertEquals(mrm.get("http://url/ValueSet/234", "4.0.1").getName(), "1"); + Assertions.assertNotNull(mrm.get("http://url/ValueSet/234", "4.0.2")); + Assertions.assertEquals(mrm.get("http://url/ValueSet/234", "4.0.2").getName(), "2"); + Assertions.assertNotNull(mrm.get("http://url/ValueSet/234", "4.0")); + Assertions.assertEquals(mrm.get("http://url/ValueSet/234", "4.0").getName(), "2"); + Assertions.assertNull(mrm.get("http://url/ValueSet/234", "4.1")); + + mrm.drop("2345"); // vs2; + Assertions.assertEquals(mrm.size(), 0); + Assertions.assertNull(mrm.get("2345")); + Assertions.assertNull(mrm.get("2346")); + Assertions.assertNull(mrm.get("http://url/ValueSet/234")); + Assertions.assertNull(mrm.get("http://url/ValueSet/234", "4.0.0")); + Assertions.assertNull(mrm.get("http://url/ValueSet/234", "4.0.1")); + Assertions.assertNull(mrm.get("http://url/ValueSet/234", "4.0.2")); + Assertions.assertNull(mrm.get("http://url/ValueSet/234", "4.0")); + Assertions.assertNull(mrm.get("http://url/ValueSet/234", "4.1")); + } + + @Test + public void testSingleWithDuplicateIds2DeferredLoad() { + CanonicalResourceManager mrm = new CanonicalResourceManager<>(true); + ValueSet vs1 = new ValueSet(); + vs1.setId("2345"); + vs1.setUrl("http://url/ValueSet/234"); + vs1.setVersion("4.0.1"); + vs1.setName("1"); + DeferredLoadTestResource vs1d = new DeferredLoadTestResource(vs1); + + ValueSet vs2 = new ValueSet(); + vs2.setId("2345"); + vs2.setUrl("http://url/ValueSet/234"); + vs2.setVersion("4.0.2"); + vs2.setName("2"); + DeferredLoadTestResource vs2d = new DeferredLoadTestResource(vs2); + + mrm.clear(); + mrm.register(vs1d, null); + + Assertions.assertEquals(mrm.size(), 1); + Assertions.assertNotNull(mrm.get("2345")); + Assertions.assertEquals(mrm.get("2345").getName(), "1"); + Assertions.assertNotNull(mrm.get("http://url/ValueSet/234")); + Assertions.assertEquals(mrm.get("http://url/ValueSet/234").getName(), "1"); + Assertions.assertNotNull(mrm.get("http://url/ValueSet/234", "4.0.0")); + Assertions.assertEquals(mrm.get("http://url/ValueSet/234", "4.0.0").getName(), "1"); + Assertions.assertNotNull(mrm.get("http://url/ValueSet/234", "4.0.1")); + Assertions.assertEquals(mrm.get("http://url/ValueSet/234", "4.0.1").getName(), "1"); + Assertions.assertNotNull(mrm.get("http://url/ValueSet/234", "4.0.2")); + Assertions.assertEquals(mrm.get("http://url/ValueSet/234", "4.0.2").getName(), "1"); + Assertions.assertNotNull(mrm.get("http://url/ValueSet/234", "4.0")); + Assertions.assertEquals(mrm.get("http://url/ValueSet/234", "4.0").getName(), "1"); + Assertions.assertNull(mrm.get("http://url/ValueSet/234", "4.1")); + + mrm.register(vs2d, null); + + Assertions.assertEquals(mrm.size(), 1); + Assertions.assertNotNull(mrm.get("2345")); + Assertions.assertEquals(mrm.get("2345").getName(), "2"); + + Assertions.assertNotNull(mrm.get("http://url/ValueSet/234")); + Assertions.assertEquals(mrm.get("http://url/ValueSet/234").getName(), "2"); + Assertions.assertNotNull(mrm.get("http://url/ValueSet/234", "4.0.0")); + Assertions.assertEquals(mrm.get("http://url/ValueSet/234", "4.0.0").getName(), "2"); + Assertions.assertNotNull(mrm.get("http://url/ValueSet/234", "4.0.1")); + Assertions.assertEquals(mrm.get("http://url/ValueSet/234", "4.0.1").getName(), "2"); + Assertions.assertNotNull(mrm.get("http://url/ValueSet/234", "4.0.2")); + Assertions.assertEquals(mrm.get("http://url/ValueSet/234", "4.0.2").getName(), "2"); + Assertions.assertNotNull(mrm.get("http://url/ValueSet/234", "4.0")); + Assertions.assertEquals(mrm.get("http://url/ValueSet/234", "4.0").getName(), "2"); + Assertions.assertNull(mrm.get("http://url/ValueSet/234", "4.1")); + + mrm.drop("2345"); // vs2; + Assertions.assertEquals(mrm.size(), 0); + Assertions.assertNull(mrm.get("2345")); + Assertions.assertNull(mrm.get("2346")); + Assertions.assertNull(mrm.get("http://url/ValueSet/234")); + Assertions.assertNull(mrm.get("http://url/ValueSet/234", "4.0.0")); + Assertions.assertNull(mrm.get("http://url/ValueSet/234", "4.0.1")); + Assertions.assertNull(mrm.get("http://url/ValueSet/234", "4.0.2")); + Assertions.assertNull(mrm.get("http://url/ValueSet/234", "4.0")); + Assertions.assertNull(mrm.get("http://url/ValueSet/234", "4.1")); + } + + @Test + public void testSingleWithVersions1DeferredLoad() { + CanonicalResourceManager mrm = new CanonicalResourceManager<>(true); + ValueSet vs1 = new ValueSet(); + vs1.setId("2345"); + vs1.setUrl("http://url/ValueSet/234"); + vs1.setVersion("4.0.1"); + vs1.setName("1"); + DeferredLoadTestResource vs1d = new DeferredLoadTestResource(vs1); + + ValueSet vs2 = new ValueSet(); + vs2.setId("2346"); + vs2.setUrl("http://url/ValueSet/234"); + vs2.setVersion("4.0.2"); + vs2.setName("2"); + DeferredLoadTestResource vs2d = new DeferredLoadTestResource(vs2); + + mrm.clear(); + mrm.register(vs1d, null); + + Assertions.assertEquals(mrm.size(), 1); + Assertions.assertNotNull(mrm.get("2345")); + Assertions.assertEquals(mrm.get("2345").getName(), "1"); + Assertions.assertNotNull(mrm.get("http://url/ValueSet/234")); + Assertions.assertEquals(mrm.get("http://url/ValueSet/234").getName(), "1"); + Assertions.assertNotNull(mrm.get("http://url/ValueSet/234", "4.0.0")); + Assertions.assertEquals(mrm.get("http://url/ValueSet/234", "4.0.0").getName(), "1"); + Assertions.assertNotNull(mrm.get("http://url/ValueSet/234", "4.0.1")); + Assertions.assertEquals(mrm.get("http://url/ValueSet/234", "4.0.1").getName(), "1"); + Assertions.assertNotNull(mrm.get("http://url/ValueSet/234", "4.0.2")); + Assertions.assertEquals(mrm.get("http://url/ValueSet/234", "4.0.2").getName(), "1"); + Assertions.assertNotNull(mrm.get("http://url/ValueSet/234", "4.0")); + Assertions.assertEquals(mrm.get("http://url/ValueSet/234", "4.0").getName(), "1"); + Assertions.assertNull(mrm.get("http://url/ValueSet/234", "4.1")); + + mrm.register(vs2d, null); + + Assertions.assertEquals(mrm.size(), 2); + Assertions.assertNotNull(mrm.get("2345")); + Assertions.assertEquals(mrm.get("2345").getName(), "1"); + Assertions.assertNotNull(mrm.get("2346")); + Assertions.assertEquals(mrm.get("2346").getName(), "2"); + + Assertions.assertNotNull(mrm.get("http://url/ValueSet/234")); + Assertions.assertEquals(mrm.get("http://url/ValueSet/234").getName(), "2"); + Assertions.assertNotNull(mrm.get("http://url/ValueSet/234", "4.0.0")); + Assertions.assertEquals(mrm.get("http://url/ValueSet/234", "4.0.0").getName(), "2"); + Assertions.assertNotNull(mrm.get("http://url/ValueSet/234", "4.0.1")); + Assertions.assertEquals(mrm.get("http://url/ValueSet/234", "4.0.1").getName(), "1"); + Assertions.assertNotNull(mrm.get("http://url/ValueSet/234", "4.0.2")); + Assertions.assertEquals(mrm.get("http://url/ValueSet/234", "4.0.2").getName(), "2"); + Assertions.assertNotNull(mrm.get("http://url/ValueSet/234", "4.0")); + Assertions.assertEquals(mrm.get("http://url/ValueSet/234", "4.0").getName(), "2"); + Assertions.assertNull(mrm.get("http://url/ValueSet/234", "4.1")); + + mrm.drop("2346"); // vs2; + Assertions.assertEquals(mrm.size(), 1); + Assertions.assertNotNull(mrm.get("2345")); + Assertions.assertNull(mrm.get("2346")); + Assertions.assertEquals(mrm.get("2345").getName(), "1"); + Assertions.assertNotNull(mrm.get("http://url/ValueSet/234")); + Assertions.assertEquals(mrm.get("http://url/ValueSet/234").getName(), "1"); + Assertions.assertNotNull(mrm.get("http://url/ValueSet/234", "4.0.0")); + Assertions.assertEquals(mrm.get("http://url/ValueSet/234", "4.0.0").getName(), "1"); + Assertions.assertNotNull(mrm.get("http://url/ValueSet/234", "4.0.1")); + Assertions.assertEquals(mrm.get("http://url/ValueSet/234", "4.0.1").getName(), "1"); + Assertions.assertNotNull(mrm.get("http://url/ValueSet/234", "4.0.2")); + Assertions.assertEquals(mrm.get("http://url/ValueSet/234", "4.0.2").getName(), "1"); + Assertions.assertNotNull(mrm.get("http://url/ValueSet/234", "4.0")); + Assertions.assertEquals(mrm.get("http://url/ValueSet/234", "4.0").getName(), "1"); + Assertions.assertNull(mrm.get("http://url/ValueSet/234", "4.1")); + + } + + @Test + public void testSingleWithVersions2DeferredLoad() { + CanonicalResourceManager mrm = new CanonicalResourceManager<>(true); + ValueSet vs1 = new ValueSet(); + vs1.setId("2345"); + vs1.setUrl("http://url/ValueSet/234"); + vs1.setVersion("4.0.1"); + vs1.setName("1"); + DeferredLoadTestResource vs1d = new DeferredLoadTestResource(vs1); + + ValueSet vs2 = new ValueSet(); + vs2.setId("2346"); + vs2.setUrl("http://url/ValueSet/234"); + vs2.setVersion("4.0.2"); + vs2.setName("2"); + DeferredLoadTestResource vs2d = new DeferredLoadTestResource(vs2); + + mrm.clear(); + mrm.register(vs1d, null); + + Assertions.assertEquals(mrm.size(), 1); + Assertions.assertNotNull(mrm.get("2345")); + Assertions.assertEquals(mrm.get("2345").getName(), "1"); + Assertions.assertNotNull(mrm.get("http://url/ValueSet/234")); + Assertions.assertEquals(mrm.get("http://url/ValueSet/234").getName(), "1"); + Assertions.assertNotNull(mrm.get("http://url/ValueSet/234", "4.0.0")); + Assertions.assertEquals(mrm.get("http://url/ValueSet/234", "4.0.0").getName(), "1"); + Assertions.assertNotNull(mrm.get("http://url/ValueSet/234", "4.0.1")); + Assertions.assertEquals(mrm.get("http://url/ValueSet/234", "4.0.1").getName(), "1"); + Assertions.assertNotNull(mrm.get("http://url/ValueSet/234", "4.0.2")); + Assertions.assertEquals(mrm.get("http://url/ValueSet/234", "4.0.2").getName(), "1"); + Assertions.assertNotNull(mrm.get("http://url/ValueSet/234", "4.0")); + Assertions.assertEquals(mrm.get("http://url/ValueSet/234", "4.0").getName(), "1"); + Assertions.assertNull(mrm.get("http://url/ValueSet/234", "4.1")); + + mrm.register(vs2d, null); + + Assertions.assertEquals(mrm.size(), 2); + Assertions.assertNotNull(mrm.get("2345")); + Assertions.assertEquals(mrm.get("2345").getName(), "1"); + Assertions.assertNotNull(mrm.get("2346")); + Assertions.assertEquals(mrm.get("2346").getName(), "2"); + + Assertions.assertNotNull(mrm.get("http://url/ValueSet/234")); + Assertions.assertEquals(mrm.get("http://url/ValueSet/234").getName(), "2"); + Assertions.assertNotNull(mrm.get("http://url/ValueSet/234", "4.0.0")); + Assertions.assertEquals(mrm.get("http://url/ValueSet/234", "4.0.0").getName(), "2"); + Assertions.assertNotNull(mrm.get("http://url/ValueSet/234", "4.0.1")); + Assertions.assertEquals(mrm.get("http://url/ValueSet/234", "4.0.1").getName(), "1"); + Assertions.assertNotNull(mrm.get("http://url/ValueSet/234", "4.0.2")); + Assertions.assertEquals(mrm.get("http://url/ValueSet/234", "4.0.2").getName(), "2"); + Assertions.assertNotNull(mrm.get("http://url/ValueSet/234", "4.0")); + Assertions.assertEquals(mrm.get("http://url/ValueSet/234", "4.0").getName(), "2"); + Assertions.assertNull(mrm.get("http://url/ValueSet/234", "4.1")); + + mrm.drop("2345"); // vs1; + Assertions.assertEquals(mrm.size(), 1); + Assertions.assertNull(mrm.get("2345")); + Assertions.assertNotNull(mrm.get("2346")); + Assertions.assertEquals(mrm.get("2346").getName(), "2"); + + Assertions.assertNotNull(mrm.get("http://url/ValueSet/234")); + Assertions.assertEquals(mrm.get("http://url/ValueSet/234").getName(), "2"); + Assertions.assertNotNull(mrm.get("http://url/ValueSet/234", "4.0.0")); + Assertions.assertEquals(mrm.get("http://url/ValueSet/234", "4.0.0").getName(), "2"); + Assertions.assertNotNull(mrm.get("http://url/ValueSet/234", "4.0.1")); + Assertions.assertEquals(mrm.get("http://url/ValueSet/234", "4.0.1").getName(), "2"); + Assertions.assertNotNull(mrm.get("http://url/ValueSet/234", "4.0.2")); + Assertions.assertEquals(mrm.get("http://url/ValueSet/234", "4.0.2").getName(), "2"); + Assertions.assertNotNull(mrm.get("http://url/ValueSet/234", "4.0")); + Assertions.assertEquals(mrm.get("http://url/ValueSet/234", "4.0").getName(), "2"); + Assertions.assertNull(mrm.get("http://url/ValueSet/234", "4.1")); + } + + } \ No newline at end of file diff --git a/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/SnapShotGenerationTests.java b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/SnapShotGenerationTests.java index 7c63a9b8c..95075cc23 100644 --- a/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/SnapShotGenerationTests.java +++ b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/SnapShotGenerationTests.java @@ -72,6 +72,11 @@ public class SnapShotGenerationTests { return null; } + @Override + public Resource loadResource(InputStream stream, boolean isJson) throws FHIRException, IOException { + return null; + } + @Override public String[] getTypes() { return types; diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/FilesystemPackageCacheManager.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/FilesystemPackageCacheManager.java index f102eeb22..13baa282a 100644 --- a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/FilesystemPackageCacheManager.java +++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/FilesystemPackageCacheManager.java @@ -447,6 +447,10 @@ public class FilesystemPackageCacheManager extends BasePackageCacheManager imple return loadPackageFromFile(id, version.substring(5)); } + if (version == null && id.contains("#")) { + version = id.substring(id.indexOf("#")+1); + id = id.substring(0, id.indexOf("#")); + } NpmPackage p = loadPackageFromCacheOnly(id, version); if (p != null) { if ("current".equals(version)) { diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/NpmPackage.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/NpmPackage.java index 499dbf9a0..b8c6cfc72 100644 --- a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/NpmPackage.java +++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/NpmPackage.java @@ -61,6 +61,7 @@ import org.hl7.fhir.exceptions.FHIRException; import org.hl7.fhir.utilities.CommaSeparatedStringBuilder; import org.hl7.fhir.utilities.TextFile; import org.hl7.fhir.utilities.Utilities; +import org.hl7.fhir.utilities.cache.NpmPackage.PackageResourceInformationSorter; import org.hl7.fhir.utilities.cache.PackageGenerator.PackageType; import org.hl7.fhir.utilities.json.JSONUtil; import org.hl7.fhir.utilities.json.JsonTrackingParser; @@ -82,6 +83,50 @@ import com.google.gson.JsonObject; */ public class NpmPackage { + public class PackageResourceInformationSorter implements Comparator { + @Override + public int compare(PackageResourceInformation o1, PackageResourceInformation o2) { + return o1.filename.compareTo(o2.filename); + } + } + + public class PackageResourceInformation { + private String id; + private String type; + private String url; + private String version; + private String filename; + private String supplements; + + public PackageResourceInformation(String root, JsonObject fi) throws IOException { + super(); + id = JSONUtil.str(fi, "id"); + type = JSONUtil.str(fi, "resourceType"); + url = JSONUtil.str(fi, "url"); + version = JSONUtil.str(fi, "version"); + filename = Utilities.path(root, JSONUtil.str(fi, "filename")); + supplements = JSONUtil.str(fi, "supplements"); + } + public String getId() { + return id; + } + public String getType() { + return type; + } + public String getUrl() { + return url; + } + public String getVersion() { + return version; + } + public String getFilename() { + return filename; + } + public String getSupplements() { + return supplements; + } + + } public class IndexVersionSorter implements Comparator { @Override @@ -489,6 +534,19 @@ public class NpmPackage { return res; } + public List listIndexedResources(String... types) throws IOException { + List res = new ArrayList(); + NpmPackageFolder folder = folders.get("package"); + for (JsonElement e : folder.index.getAsJsonArray("files")) { + JsonObject fi = e.getAsJsonObject(); + if (Utilities.existsInList(JSONUtil.str(fi, "resourceType"), types)) { + res.add(new PackageResourceInformation(folder.folder.getAbsolutePath(), fi)); + } + } +// Collections.sort(res, new PackageResourceInformationSorter()); + return res; + } + /** * use the name from listResources() * diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/NpmPackageIndexBuilder.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/NpmPackageIndexBuilder.java index e26d5c765..5ae42d265 100644 --- a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/NpmPackageIndexBuilder.java +++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/NpmPackageIndexBuilder.java @@ -44,16 +44,24 @@ public class NpmPackageIndexBuilder { files.add(fi); fi.addProperty("filename", name); fi.addProperty("resourceType", json.get("resourceType").getAsString()); - if (json.has("id") && json.get("id").isJsonPrimitive()) + if (json.has("id") && json.get("id").isJsonPrimitive()) { fi.addProperty("id", json.get("id").getAsString()); - if (json.has("url") && json.get("url").isJsonPrimitive()) + } + if (json.has("url") && json.get("url").isJsonPrimitive()) { fi.addProperty("url", json.get("url").getAsString()); - if (json.has("version") && json.get("version").isJsonPrimitive()) + } + if (json.has("version") && json.get("version").isJsonPrimitive()) { fi.addProperty("version", json.get("version").getAsString()); - if (json.has("kind") && json.get("kind").isJsonPrimitive()) + } + if (json.has("kind") && json.get("kind").isJsonPrimitive()) { fi.addProperty("kind", json.get("kind").getAsString()); - if (json.has("type") && json.get("type").isJsonPrimitive()) + } + if (json.has("type") && json.get("type").isJsonPrimitive()) { fi.addProperty("type", json.get("type").getAsString()); + } + if (json.has("supplements") && json.get("supplements").isJsonPrimitive()) { + fi.addProperty("supplements", json.get("supplements").getAsString()); + } } } catch (Exception e) { System.out.println("Error parsing "+name+": "+e.getMessage()); diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/ValidationEngine.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/ValidationEngine.java index da7687f64..098fc4d89 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/ValidationEngine.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/ValidationEngine.java @@ -6,6 +6,7 @@ import org.hl7.fhir.convertors.loaders.R2016MayToR5Loader; import org.hl7.fhir.convertors.loaders.R2ToR5Loader; import org.hl7.fhir.convertors.loaders.R3ToR5Loader; import org.hl7.fhir.convertors.loaders.R4ToR5Loader; +import org.hl7.fhir.convertors.loaders.R5ToR5Loader; import org.hl7.fhir.convertors.txClient.TerminologyClientFactory; import org.hl7.fhir.exceptions.DefinitionException; import org.hl7.fhir.exceptions.FHIRException; @@ -38,6 +39,7 @@ import org.hl7.fhir.utilities.TextFile; import org.hl7.fhir.utilities.Utilities; import org.hl7.fhir.utilities.VersionUtilities; import org.hl7.fhir.utilities.cache.NpmPackage; +import org.hl7.fhir.utilities.cache.PackageClient; import org.hl7.fhir.utilities.cache.FilesystemPackageCacheManager; import org.hl7.fhir.utilities.cache.ToolsVersion; import org.hl7.fhir.utilities.i18n.I18nBase; @@ -368,18 +370,32 @@ public class ValidationEngine implements IValidatorResourceFetcher { } private void loadCoreDefinitions(String src, boolean recursive) throws Exception { - Map source = loadIgSource(src, recursive, true); - if (version == null) - version = getVersionFromPack(source); - context = SimpleWorkerContext.fromDefinitions(source, loaderForVersion(), new PackageVersion(src)); + if (pcm == null) { + pcm = new FilesystemPackageCacheManager(true, ToolsVersion.TOOLS_VERSION); + } + NpmPackage npm = pcm.loadPackage(src, null); + if (npm != null) { + version = npm.fhirVersion(); + context = SimpleWorkerContext.fromPackage(npm, loaderForVersion()); + } else { + Map source = loadIgSource(src, recursive, true); + if (version == null) { + version = getVersionFromPack(source); + } + context = SimpleWorkerContext.fromDefinitions(source, loaderForVersion(), new PackageVersion(src)); + grabNatives(source, "http://hl7.org/fhir"); + } context.setAllowLoadingDuplicates(true); // because of Forge context.setExpansionProfile(makeExpProfile()); - NpmPackage npm = pcm.loadPackage("hl7.fhir.xver-extensions", "0.0.4"); - context.loadFromPackage(npm, null); - grabNatives(source, "http://hl7.org/fhir"); + NpmPackage npmX = pcm.loadPackage("hl7.fhir.xver-extensions", "0.0.4"); + context.loadFromPackage(npmX, null); } private IContextResourceLoader loaderForVersion() { + return loaderForVersion(version); + } + + private IContextResourceLoader loaderForVersion(String version) { if (Utilities.noString(version)) return null; if (version.startsWith("1.0")) @@ -390,6 +406,8 @@ public class ValidationEngine implements IValidatorResourceFetcher { return new R3ToR5Loader(new String[] { "CapabilityStatement", "StructureDefinition", "ValueSet", "CodeSystem", "SearchParameter", "OperationDefinition", "Questionnaire","ConceptMap","StructureMap", "NamingSystem"}); if (version.startsWith("4.0")) return new R4ToR5Loader(new String[] { "CapabilityStatement", "StructureDefinition", "ValueSet", "CodeSystem", "SearchParameter", "OperationDefinition", "Questionnaire","ConceptMap","StructureMap", "NamingSystem"}); + if (version.startsWith("5.0")) + return new R5ToR5Loader(new String[] { "CapabilityStatement", "StructureDefinition", "ValueSet", "CodeSystem", "SearchParameter", "OperationDefinition", "Questionnaire","ConceptMap","StructureMap", "NamingSystem"}); return null; } @@ -752,34 +770,39 @@ public class ValidationEngine implements IValidatorResourceFetcher { } public void loadIg(String src, boolean recursive) throws IOException, FHIRException, Exception { - String canonical = null; - Map source = loadIgSource(src, recursive, true); - String version = Constants.VERSION; - if (this.version != null) - version = this.version; - if (source.containsKey("version.info")) - version = readInfoVersion(source.get("version.info")); - - for (Entry t : source.entrySet()) { - String fn = t.getKey(); - if (!exemptFile(fn)) { - Resource r = loadFileWithErrorChecking(version, t, fn); - if (r != null) { - context.cacheResource(r); - if (r instanceof ImplementationGuide) { - canonical = ((ImplementationGuide) r).getUrl(); - igs.add((ImplementationGuide) r); - if (canonical.contains("/ImplementationGuide/")) { - Resource r2 = r.copy(); - ((ImplementationGuide) r2).setUrl(canonical.substring(0, canonical.indexOf("/ImplementationGuide/"))); - context.cacheResource(r2); + NpmPackage npm = pcm.loadPackage(src, null); + if (npm != null) { + context.loadFromPackage(npm, loaderForVersion(npm.fhirVersion())); + } else { + String canonical = null; + Map source = loadIgSource(src, recursive, true); + String version = Constants.VERSION; + if (this.version != null) + version = this.version; + if (source.containsKey("version.info")) + version = readInfoVersion(source.get("version.info")); + + for (Entry t : source.entrySet()) { + String fn = t.getKey(); + if (!exemptFile(fn)) { + Resource r = loadFileWithErrorChecking(version, t, fn); + if (r != null) { + context.cacheResource(r); + if (r instanceof ImplementationGuide) { + canonical = ((ImplementationGuide) r).getUrl(); + igs.add((ImplementationGuide) r); + if (canonical.contains("/ImplementationGuide/")) { + Resource r2 = r.copy(); + ((ImplementationGuide) r2).setUrl(canonical.substring(0, canonical.indexOf("/ImplementationGuide/"))); + context.cacheResource(r2); + } } } } } - } - if (canonical != null) { - grabNatives(source, canonical); + if (canonical != null) { + grabNatives(source, canonical); + } } }