From e1657c66b0208a1fd6672593422690b12f9f63ed Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Fri, 7 Oct 2022 21:50:59 +1100 Subject: [PATCH] refactor IWorkerContext --- .../convertors/misc/PhinVadsImporter.java | 3 +- .../fhir/r5/comparison/ProfileComparer.java | 3 +- .../fhir/r5/conformance/ProfileUtilities.java | 6 +- .../r5/conformance/R5ExtensionsLoader.java | 3 +- .../fhir/r5/context/BaseWorkerContext.java | 237 +++------ .../hl7/fhir/r5/context/ContextUtilities.java | 344 +++++++++++++ .../hl7/fhir/r5/context/IWorkerContext.java | 454 ++++++++---------- .../r5/context/IWorkerContextManager.java | 13 + .../fhir/r5/context/SimpleWorkerContext.java | 209 +------- .../org/hl7/fhir/r5/elementmodel/Element.java | 5 +- .../hl7/fhir/r5/elementmodel/JsonParser.java | 2 +- .../fhir/r5/elementmodel/ObjectConverter.java | 2 +- .../hl7/fhir/r5/elementmodel/ParserBase.java | 11 +- .../hl7/fhir/r5/elementmodel/Property.java | 4 +- .../hl7/fhir/r5/elementmodel/XmlParser.java | 2 +- .../r5/renderers/ProfileDrivenRenderer.java | 3 +- .../r5/renderers/QuestionnaireRenderer.java | 3 +- .../fhir/r5/renderers/ValueSetRenderer.java | 38 +- .../hl7/fhir/r5/renderers/utils/Resolver.java | 2 +- .../terminologies/ValueSetExpansionCache.java | 7 +- .../org/hl7/fhir/r5/utils/FHIRPathEngine.java | 19 +- .../fhir/r5/utils/GraphQLSchemaGenerator.java | 3 +- .../hl7/fhir/r5/utils/PublicationHacker.java | 3 +- .../structuremap/StructureMapUtilities.java | 9 +- .../hl7/fhir/r5/test/CDARoundTripTests.java | 5 +- .../org/hl7/fhir/r5/test/XmlParserTests.java | 5 +- .../hl7/fhir/utilities/VersionUtilities.java | 13 + .../src/main/resources/Messages.properties | 4 +- .../hl7/fhir/validation/BaseValidator.java | 5 +- .../java/org/hl7/fhir/validation/Scanner.java | 5 +- .../hl7/fhir/validation/ValidationEngine.java | 20 +- .../services/StandAloneValidatorFetcher.java | 5 +- .../cli/services/ValidationService.java | 15 +- .../instance/InstanceValidator.java | 7 +- .../fhir/r5/test/StructureMappingTests.java | 5 +- .../validation/tests/ValidationTests.java | 3 +- pom.xml | 2 +- 37 files changed, 769 insertions(+), 710 deletions(-) create mode 100644 org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/ContextUtilities.java create mode 100644 org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/IWorkerContextManager.java diff --git a/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/misc/PhinVadsImporter.java b/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/misc/PhinVadsImporter.java index 0f8226746..efe447258 100644 --- a/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/misc/PhinVadsImporter.java +++ b/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/misc/PhinVadsImporter.java @@ -9,6 +9,7 @@ import java.text.SimpleDateFormat; import java.util.List; import org.hl7.fhir.exceptions.FHIRException; +import org.hl7.fhir.r5.context.ContextUtilities; import org.hl7.fhir.r5.formats.IParser.OutputStyle; import org.hl7.fhir.r5.formats.JsonParser; import org.hl7.fhir.r5.model.Enumerations.PublicationStatus; @@ -84,7 +85,7 @@ public class PhinVadsImporter extends OIDBasedValueSetImporter { String display = rdr.cell("Preferred Concept Name"); String csoid = rdr.cell("Code System OID"); String csver = rdr.cell("Code System Version"); - String url = context.oid2Uri(csoid); + String url = new ContextUtilities(context).oid2Uri(csoid); if (url == null) { url = "urn:oid:" + csoid; } diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/comparison/ProfileComparer.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/comparison/ProfileComparer.java index 990bb72b5..30fdf10cc 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/comparison/ProfileComparer.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/comparison/ProfileComparer.java @@ -15,6 +15,7 @@ import org.hl7.fhir.r5.conformance.ProfileUtilities; import org.hl7.fhir.r5.conformance.ProfileUtilities.UnusedTracker; import org.hl7.fhir.r5.context.IWorkerContext; import org.hl7.fhir.r5.formats.IParser; +import org.hl7.fhir.r5.formats.JsonParser; import org.hl7.fhir.r5.model.Base; import org.hl7.fhir.r5.model.Coding; import org.hl7.fhir.r5.model.DataType; @@ -362,7 +363,7 @@ public class ProfileComparer extends CanonicalResourceComparer { if (val instanceof PrimitiveType) return "'" + ((PrimitiveType) val).getValueAsString()+"'"; - IParser jp = left ? session.getContextLeft().newJsonParser() : session.getContextRight().newJsonParser(); + IParser jp = new JsonParser(); return jp.composeString(val, "value"); } diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/conformance/ProfileUtilities.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/conformance/ProfileUtilities.java index b79e31157..6a39db7f8 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/conformance/ProfileUtilities.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/conformance/ProfileUtilities.java @@ -3309,7 +3309,7 @@ public class ProfileUtilities extends TranslatingUtilities { String url = u.getValue(); boolean tgtOk = !td.hasTargetProfile() || td.hasTargetProfile(url); while (url != null && !tgtOk) { - StructureDefinition sd = context.fetchRawProfile(url); + StructureDefinition sd = context.fetchResource(StructureDefinition.class, url); if (sd == null) { if (messages != null) { messages.add(new ValidationMessage(Source.InstanceValidator, IssueType.BUSINESSRULE, purl+"#"+derived.getPath(), "Cannot check whether the target profile "+url+" is valid constraint on the base because it is not known", IssueSeverity.WARNING)); @@ -4396,7 +4396,7 @@ public class ProfileUtilities extends TranslatingUtilities { Piece p = gc.addText(ProfileUtilities.CONSTRAINT_CHAR); p.setHint(translate("sd.table", "This element has or is affected by some invariants ("+listConstraintsAndConditions(element)+")")); p.addStyle(CONSTRAINT_STYLE); - p.setReference(context.getSpecUrl()+"conformance-rules.html#constraints"); + p.setReference(VersionUtilities.getSpecUrl(context.getVersion())+"conformance-rules.html#constraints"); } ExtensionContext extDefn = null; @@ -5321,7 +5321,7 @@ public class ProfileUtilities extends TranslatingUtilities { if (value instanceof PrimitiveType) return ((PrimitiveType) value).asStringValue(); - IParser json = context.newJsonParser(); + IParser json = new JsonParser(); return json.composeString(value, null); } diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/conformance/R5ExtensionsLoader.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/conformance/R5ExtensionsLoader.java index 60cf761d2..84bea544b 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/conformance/R5ExtensionsLoader.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/conformance/R5ExtensionsLoader.java @@ -7,6 +7,7 @@ import java.util.List; import java.util.Map; import org.hl7.fhir.exceptions.FHIRException; +import org.hl7.fhir.r5.context.ContextUtilities; import org.hl7.fhir.r5.context.IWorkerContext; import org.hl7.fhir.r5.context.IWorkerContext.PackageVersion; import org.hl7.fhir.r5.formats.JsonParser; @@ -56,7 +57,7 @@ public class R5ExtensionsLoader { } PackageVersion pd = new PackageVersion(pck.name(), pck.version(), pck.dateAsDate()); count = 0; - List typeNames = context.getTypeNames(); + List typeNames = new ContextUtilities(context).getTypeNames(); for (StructureDefinition sd : extensions) { if (sd.getType().equals("Extension") && sd.getDerivation() == TypeDerivationRule.CONSTRAINT && !context.hasResource(StructureDefinition.class, sd.getUrl())) { 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 a407664a0..94fcc1ef4 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 @@ -54,8 +54,8 @@ import org.hl7.fhir.exceptions.NoTerminologyServiceException; 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.IPackageLoadingTracker; import org.hl7.fhir.r5.context.IWorkerContext.ILoggingService.LogCategory; +import org.hl7.fhir.r5.context.IWorkerContextManager.IPackageLoadingTracker; import org.hl7.fhir.r5.context.TerminologyCache.CacheToken; import org.hl7.fhir.r5.model.BooleanType; import org.hl7.fhir.r5.model.Bundle; @@ -70,6 +70,7 @@ import org.hl7.fhir.r5.model.CodeableConcept; import org.hl7.fhir.r5.model.Coding; import org.hl7.fhir.r5.model.ConceptMap; import org.hl7.fhir.r5.model.Constants; +import org.hl7.fhir.r5.model.DomainResource; import org.hl7.fhir.r5.model.ElementDefinition; import org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionBindingComponent; import org.hl7.fhir.r5.model.Enumerations.PublicationStatus; @@ -246,7 +247,7 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte protected TerminologyCache txCache; protected TimeTracker clock; private boolean tlogging = true; - private ICanonicalResourceLocator locator; + private IWorkerContextManager.ICanonicalResourceLocator locator; protected String userAgent; protected BaseWorkerContext() throws FileNotFoundException, IOException, FHIRException { @@ -1297,20 +1298,6 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte txCache.clear(); } - - @Override - public List findMapsForSource(String url) throws FHIRException { - synchronized (lock) { - List res = new ArrayList(); - for (ConceptMap map : maps.getList()) { - if (((Reference) map.getSourceScope()).getReference().equals(url)) { - res.add(map); - } - } - return res; - } - } - public boolean isCanRunWithoutTerminology() { return canRunWithoutTerminology; } @@ -1383,7 +1370,7 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte } if (class_ == StructureDefinition.class) { - uri = ProfileUtilities.sdNs(uri, getOverrideVersionNs()); + uri = ProfileUtilities.sdNs(uri, null); } synchronized (lock) { @@ -1509,7 +1496,7 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte if (uri == null) { return null; } - uri = ProfileUtilities.sdNs(uri, getOverrideVersionNs()); + uri = ProfileUtilities.sdNs(uri, null); synchronized (lock) { @@ -1571,7 +1558,7 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte } if ("StructureDefinition".equals(cls)) { - uri = ProfileUtilities.sdNs(uri, getOverrideVersionNs()); + uri = ProfileUtilities.sdNs(uri, null); } synchronized (lock) { @@ -1693,11 +1680,65 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte throw new FHIRException(formatMessage(I18nConstants.NOT_DONE_YET_CANT_FETCH_, uri)); } } + + @SuppressWarnings("unchecked") + public List fetchResourcesByType(Class class_) { + + List res = new ArrayList<>(); + + synchronized (lock) { + + if (class_ == Resource.class || class_ == DomainResource.class || class_ == CanonicalResource.class || class_ == null) { + res.addAll((List) structures.getList()); + res.addAll((List) guides.getList()); + res.addAll((List) capstmts.getList()); + res.addAll((List) measures.getList()); + res.addAll((List) libraries.getList()); + res.addAll((List) valueSets.getList()); + res.addAll((List) codeSystems.getList()); + res.addAll((List) operations.getList()); + res.addAll((List) searchParameters.getList()); + res.addAll((List) plans.getList()); + res.addAll((List) maps.getList()); + res.addAll((List) transforms.getList()); + res.addAll((List) questionnaires.getList()); + res.addAll((List) systems.getList()); + } else if (class_ == ImplementationGuide.class) { + res.addAll((List) guides.getList()); + } else if (class_ == CapabilityStatement.class) { + res.addAll((List) capstmts.getList()); + } else if (class_ == Measure.class) { + res.addAll((List) measures.getList()); + } else if (class_ == Library.class) { + res.addAll((List) libraries.getList()); + } else if (class_ == StructureDefinition.class) { + res.addAll((List) structures.getList()); + } else if (class_ == StructureMap.class) { + res.addAll((List) transforms.getList()); + } else if (class_ == ValueSet.class) { + res.addAll((List) valueSets.getList()); + } else if (class_ == CodeSystem.class) { + res.addAll((List) codeSystems.getList()); + } else if (class_ == NamingSystem.class) { + res.addAll((List) systems.getList()); + } else if (class_ == ConceptMap.class) { + res.addAll((List) maps.getList()); + } else if (class_ == PlanDefinition.class) { + res.addAll((List) plans.getList()); + } else if (class_ == OperationDefinition.class) { + res.addAll((List) operations.getList()); + } else if (class_ == Questionnaire.class) { + res.addAll((List) questionnaires.getList()); + } else if (class_ == SearchParameter.class) { + res.addAll((List) searchParameters.getList()); + } + } + return res; + } private Set notCanonical = new HashSet(); - private String overrideVersionNs; - protected IPackageLoadingTracker packageTracker; + protected IWorkerContextManager.IPackageLoadingTracker packageTracker; @Override public Resource fetchResourceById(String type, String uri) { @@ -1905,25 +1946,6 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte } } - @Override - public List allConformanceResources() { - synchronized (lock) { - List result = new ArrayList(); - structures.listAllM(result); - guides.listAllM(result); - capstmts.listAllM(result); - measures.listAllM(result); - libraries.listAllM(result); - codeSystems.listAllM(result); - valueSets.listAllM(result); - maps.listAllM(result); - transforms.listAllM(result); - plans.listAllM(result); - questionnaires.listAllM(result); - systems.listAllM(result); - return result; - } - } public String listSupportedSystems() { synchronized (lock) { @@ -1950,20 +1972,6 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte return m; } - public List listTransforms() { - List m = new ArrayList(); - synchronized (lock) { - transforms.listAll(m); - } - return m; - } - - public StructureMap getTransform(String code) { - synchronized (lock) { - return transforms.get(code); - } - } - public List listStructures() { List m = new ArrayList(); synchronized (lock) { @@ -1978,63 +1986,6 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte } } - @Override - public String oid2Uri(String oid) { - synchronized (lock) { - if (oid != null && oid.startsWith("urn:oid:")) { - oid = oid.substring(8); - } - if (oidCache.containsKey(oid)) { - return oidCache.get(oid); - } - - String uri = OIDUtils.getUriForOid(oid); - if (uri != null) { - oidCache.put(oid, uri); - return uri; - } - CodeSystem cs = fetchCodeSystem("http://terminology.hl7.org/CodeSystem/v2-tables"); - if (cs != null) { - for (ConceptDefinitionComponent cc : cs.getConcept()) { - for (ConceptPropertyComponent cp : cc.getProperty()) { - if (Utilities.existsInList(cp.getCode(), "v2-table-oid", "v2-cs-oid") && oid.equals(cp.getValue().primitiveValue())) { - for (ConceptPropertyComponent cp2 : cc.getProperty()) { - if ("v2-cs-uri".equals(cp2.getCode())) { - oidCache.put(oid, cp2.getValue().primitiveValue()); - return cp2.getValue().primitiveValue(); - } - } - } - } - } - } - for (CodeSystem css : codeSystems.getList()) { - if (("urn:oid:"+oid).equals(css.getUrl())) { - oidCache.put(oid, css.getUrl()); - return css.getUrl(); - } - for (Identifier id : css.getIdentifier()) { - if ("urn:ietf:rfc:3986".equals(id.getSystem()) && ("urn:oid:"+oid).equals(id.getValue())) { - oidCache.put(oid, css.getUrl()); - return css.getUrl(); - } - } - } - for (NamingSystem ns : systems.getList()) { - if (hasOid(ns, oid)) { - uri = getUri(ns); - if (uri != null) { - oidCache.put(oid, null); - return null; - } - } - } - } - oidCache.put(oid, null); - return null; - } - - private String getUri(NamingSystem ns) { for (NamingSystemUniqueIdComponent id : ns.getUniqueId()) { if (id.getType() == NamingSystemIdentifierType.URI) { @@ -2065,16 +2016,6 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte } } - @Override - public String getOverrideVersionNs() { - return overrideVersionNs; - } - - @Override - public void setOverrideVersionNs(String value) { - overrideVersionNs = value; - } - @Override public ILoggingService getLogger() { return logger; @@ -2105,15 +2046,6 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte this.ucumService = ucumService; } - @Override - public List getStructures() { - List res = new ArrayList<>(); - synchronized (lock) { // tricky, because you need to lock this as well, but it's really not in use yet - structures.listAll(res); - } - return res; - } - public String getLinkForUrl(String corePath, String url) { if (url == null) { return null; @@ -2206,11 +2138,11 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte for (StructureDefinition sd : listStructures()) { try { if (sd.getSnapshot().isEmpty()) { - generateSnapshot(sd); + new ContextUtilities(this).generateSnapshot(sd); // new XmlParser().setOutputStyle(OutputStyle.PRETTY).compose(new FileOutputStream(Utilities.path("[tmp]", "snapshot", tail(sd.getUrl())+".xml")), sd); } } catch (Exception e) { -// System.out.println("Unable to generate snapshot for "+tail(sd.getUrl()) +" from "+tail(sd.getBaseDefinition())+" because "+e.getMessage()); + System.out.println("Unable to generate snapshot for "+tail(sd.getUrl()) +" from "+tail(sd.getBaseDefinition())+" because "+e.getMessage()); } } } @@ -2280,25 +2212,11 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte return codeSystemsUsed ; } - public String getSpecUrl() { - String v = getVersion(); - switch (VersionUtilities.getMajMin(v)) { - case "1.0" : return "http://hl7.org/fhir/DSTU1"; - case "1.4" : return "http://hl7.org/fhir/DSTU2"; - case "3.0" : return "http://hl7.org/fhir/STU3"; - case "4.0" : return "http://hl7.org/fhir/R4"; - case "4.5" : return "http://build.fhir.org"; - case "5.0" : return "http://build.fhir.org"; - default: - return "http://hl7.org/fhir"; - } - } - - public ICanonicalResourceLocator getLocator() { + public IWorkerContextManager.ICanonicalResourceLocator getLocator() { return locator; } - public void setLocator(ICanonicalResourceLocator locator) { + public void setLocator(IWorkerContextManager.ICanonicalResourceLocator locator) { this.locator = locator; } @@ -2312,31 +2230,14 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte txClient.setUserAgent(userAgent); } - public List getCanonicalResourceNames() { - List names = new ArrayList<>(); - for (StructureDefinition sd : allStructures()) { - if (sd.getKind() == StructureDefinitionKind.RESOURCE && !sd.getAbstract() && hasUrlProperty(sd)) { - names.add(sd.getType()); - } - } - return names; - } - private boolean hasUrlProperty(StructureDefinition sd) { - for (ElementDefinition ed : sd.getSnapshot().getElement()) { - if (ed.getPath().equals(sd.getType()+".url")) { - return true; - } - } - return false; - } - - public IPackageLoadingTracker getPackageTracker() { + public IWorkerContextManager.IPackageLoadingTracker getPackageTracker() { return packageTracker; } - public IWorkerContext setPackageTracker(IPackageLoadingTracker packageTracker) { + public IWorkerContext setPackageTracker(IWorkerContextManager.IPackageLoadingTracker packageTracker) { this.packageTracker = packageTracker; return this; } + } \ No newline at end of file diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/ContextUtilities.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/ContextUtilities.java new file mode 100644 index 000000000..486bca138 --- /dev/null +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/ContextUtilities.java @@ -0,0 +1,344 @@ +package org.hl7.fhir.r5.context; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.hl7.fhir.exceptions.DefinitionException; +import org.hl7.fhir.exceptions.FHIRException; +import org.hl7.fhir.r5.conformance.ProfileUtilities; +import org.hl7.fhir.r5.conformance.ProfileUtilities.ProfileKnowledgeProvider; +import org.hl7.fhir.r5.model.CanonicalResource; +import org.hl7.fhir.r5.model.CodeSystem; +import org.hl7.fhir.r5.model.ElementDefinition; +import org.hl7.fhir.r5.model.CodeSystem.ConceptDefinitionComponent; +import org.hl7.fhir.r5.model.CodeSystem.ConceptPropertyComponent; +import org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionBindingComponent; +import org.hl7.fhir.r5.model.NamingSystem.NamingSystemIdentifierType; +import org.hl7.fhir.r5.model.NamingSystem.NamingSystemUniqueIdComponent; +import org.hl7.fhir.r5.model.StructureDefinition.StructureDefinitionKind; +import org.hl7.fhir.r5.model.StructureDefinition.TypeDerivationRule; +import org.hl7.fhir.r5.utils.XVerExtensionManager; +import org.hl7.fhir.r5.model.Identifier; +import org.hl7.fhir.r5.model.NamingSystem; +import org.hl7.fhir.r5.model.StructureDefinition; +import org.hl7.fhir.utilities.OIDUtils; +import org.hl7.fhir.utilities.Utilities; +import org.hl7.fhir.utilities.i18n.I18nConstants; +import org.hl7.fhir.utilities.validation.ValidationMessage; +import org.hl7.fhir.utilities.validation.ValidationMessage.IssueType; +import org.hl7.fhir.utilities.validation.ValidationMessage.Source; + +public class ContextUtilities implements ProfileKnowledgeProvider { + + private IWorkerContext context; + private boolean suppressDebugMessages; + private boolean ignoreProfileErrors; + private XVerExtensionManager xverManager; + private Map oidCache = new HashMap<>(); + + public ContextUtilities(IWorkerContext context) { + super(); + this.context = context; + } + + public boolean isSuppressDebugMessages() { + return suppressDebugMessages; + } + + public void setSuppressDebugMessages(boolean suppressDebugMessages) { + this.suppressDebugMessages = suppressDebugMessages; + } + public boolean isIgnoreProfileErrors() { + return ignoreProfileErrors; + } + + public void setIgnoreProfileErrors(boolean ignoreProfileErrors) { + this.ignoreProfileErrors = ignoreProfileErrors; + } + + public String oid2Uri(String oid) { + if (oid != null && oid.startsWith("urn:oid:")) { + oid = oid.substring(8); + } + if (oidCache.containsKey(oid)) { + return oidCache.get(oid); + } + + String uri = OIDUtils.getUriForOid(oid); + if (uri != null) { + oidCache.put(oid, uri); + return uri; + } + CodeSystem cs = context.fetchCodeSystem("http://terminology.hl7.org/CodeSystem/v2-tables"); + if (cs != null) { + for (ConceptDefinitionComponent cc : cs.getConcept()) { + for (ConceptPropertyComponent cp : cc.getProperty()) { + if (Utilities.existsInList(cp.getCode(), "v2-table-oid", "v2-cs-oid") && oid.equals(cp.getValue().primitiveValue())) { + for (ConceptPropertyComponent cp2 : cc.getProperty()) { + if ("v2-cs-uri".equals(cp2.getCode())) { + oidCache.put(oid, cp2.getValue().primitiveValue()); + return cp2.getValue().primitiveValue(); + } + } + } + } + } + } + for (CodeSystem css : context.fetchResourcesByType(CodeSystem.class)) { + if (("urn:oid:"+oid).equals(css.getUrl())) { + oidCache.put(oid, css.getUrl()); + return css.getUrl(); + } + for (Identifier id : css.getIdentifier()) { + if ("urn:ietf:rfc:3986".equals(id.getSystem()) && ("urn:oid:"+oid).equals(id.getValue())) { + oidCache.put(oid, css.getUrl()); + return css.getUrl(); + } + } + } + for (NamingSystem ns : context.fetchResourcesByType(NamingSystem.class)) { + if (hasOid(ns, oid)) { + uri = getUri(ns); + if (uri != null) { + oidCache.put(oid, null); + return null; + } + } + } + oidCache.put(oid, null); + return null; + } + + private String getUri(NamingSystem ns) { + for (NamingSystemUniqueIdComponent id : ns.getUniqueId()) { + if (id.getType() == NamingSystemIdentifierType.URI) + return id.getValue(); + } + return null; + } + + private boolean hasOid(NamingSystem ns, String oid) { + for (NamingSystemUniqueIdComponent id : ns.getUniqueId()) { + if (id.getType() == NamingSystemIdentifierType.OID && id.getValue().equals(oid)) + return true; + } + return false; + } + + /** + * @return a list of the resource and type names defined for this version + */ + public List getTypeNames() { + List result = new ArrayList(); + for (StructureDefinition sd : context.fetchResourcesByType(StructureDefinition.class)) { + if (sd.getKind() != StructureDefinitionKind.LOGICAL && sd.getDerivation() == TypeDerivationRule.SPECIALIZATION) + result.add(sd.getName()); + } + Collections.sort(result); + return result; + } + + public String getLinkForUrl(String corePath, String url) { + if (url == null) { + return null; + } + + CanonicalResource cr = context.fetchResource(CanonicalResource.class, url); + if (cr != null) { + return cr.getUserString("path"); + } + if (url.equals("http://loinc.org")) { + return corePath+"loinc.html"; + } + if (url.equals("http://unitsofmeasure.org")) { + return corePath+"ucum.html"; + } + if (url.equals("http://snomed.info/sct")) { + return corePath+"snomed.html"; + } + return null; + } + + + protected String tail(String url) { + if (Utilities.noString(url)) { + return "noname"; + } + if (url.contains("/")) { + return url.substring(url.lastIndexOf("/")+1); + } + return url; + } + + private boolean hasUrlProperty(StructureDefinition sd) { + for (ElementDefinition ed : sd.getSnapshot().getElement()) { + if (ed.getPath().equals(sd.getType()+".url")) { + return true; + } + } + return false; + } + + // -- profile services --------------------------------------------------------- + + + /** + * @return a list of the resource names that are canonical resources defined for this version + */ + public List getCanonicalResourceNames() { + List names = new ArrayList<>(); + for (StructureDefinition sd : allStructures()) { + if (sd.getKind() == StructureDefinitionKind.RESOURCE && !sd.getAbstract() && hasUrlProperty(sd)) { + names.add(sd.getType()); + } + } + return names; + } + + /** + * @return a list of all structure definitions, with snapshots generated (if possible) + */ + public List allStructures(){ + List result = new ArrayList(); + Set set = new HashSet(); + for (StructureDefinition sd : getStructures()) { + if (!set.contains(sd)) { + try { + generateSnapshot(sd); + // new XmlParser().setOutputStyle(OutputStyle.PRETTY).compose(new FileOutputStream(Utilities.path("[tmp]", "snapshot", tail(sd.getUrl())+".xml")), sd); + } catch (Exception e) { + if (!isSuppressDebugMessages()) { + System.out.println("Unable to generate snapshot for "+tail(sd.getUrl()) +" from "+tail(sd.getBaseDefinition())+" because "+e.getMessage()); + if (true) { + e.printStackTrace(); + } + } + } + result.add(sd); + set.add(sd); + } + } + return result; + } + + /** + * @return a list of all structure definitions, without trying to generate snapshots + */ + public List getStructures() { + return context.fetchResourcesByType(StructureDefinition.class); + } + + /** + * Given a structure definition, generate a snapshot (or regenerate it) + * @param p + * @throws DefinitionException + * @throws FHIRException + */ + public void generateSnapshot(StructureDefinition p) throws DefinitionException, FHIRException { + generateSnapshot(p, false); + } + + public void generateSnapshot(StructureDefinition p, boolean ifLogical) { + if ((!p.hasSnapshot() || isProfileNeedsRegenerate(p) ) && (ifLogical || p.getKind() != StructureDefinitionKind.LOGICAL)) { + if (!p.hasBaseDefinition()) + throw new DefinitionException(context.formatMessage(I18nConstants.PROFILE___HAS_NO_BASE_AND_NO_SNAPSHOT, p.getName(), p.getUrl())); + StructureDefinition sd = context.fetchResource(StructureDefinition.class, p.getBaseDefinition()); + if (sd == null && "http://hl7.org/fhir/StructureDefinition/Base".equals(p.getBaseDefinition())) { + sd = ProfileUtilities.makeBaseDefinition(p.getFhirVersion()); + } + if (sd == null) { + throw new DefinitionException(context.formatMessage(I18nConstants.PROFILE___BASE__COULD_NOT_BE_RESOLVED, p.getName(), p.getUrl(), p.getBaseDefinition())); + } + List msgs = new ArrayList(); + List errors = new ArrayList(); + ProfileUtilities pu = new ProfileUtilities(context, msgs, this); + pu.setAutoFixSliceNames(true); + pu.setThrowException(false); + if (xverManager == null) { + xverManager = new XVerExtensionManager(context); + } + pu.setXver(xverManager); + if (sd.getDerivation() == TypeDerivationRule.CONSTRAINT) { + pu.sortDifferential(sd, p, p.getUrl(), errors, true); + } + pu.setDebug(false); + for (String err : errors) + msgs.add(new ValidationMessage(Source.ProfileValidator, IssueType.EXCEPTION, p.getUserString("path"), "Error sorting Differential: "+err, ValidationMessage.IssueSeverity.ERROR)); + pu.generateSnapshot(sd, p, p.getUrl(), sd.getUserString("webroot"), p.getName()); + for (ValidationMessage msg : msgs) { + if ((!ignoreProfileErrors && msg.getLevel() == ValidationMessage.IssueSeverity.ERROR) || msg.getLevel() == ValidationMessage.IssueSeverity.FATAL) + throw new DefinitionException(context.formatMessage(I18nConstants.PROFILE___ELEMENT__ERROR_GENERATING_SNAPSHOT_, p.getName(), p.getUrl(), msg.getLocation(), msg.getMessage())); + } + if (!p.hasSnapshot()) + throw new FHIRException(context.formatMessage(I18nConstants.PROFILE___ERROR_GENERATING_SNAPSHOT, p.getName(), p.getUrl())); + pu = null; + } + } + + + // work around the fact that some Implementation guides were published with old snapshot generators that left invalid snapshots behind. + private boolean isProfileNeedsRegenerate(StructureDefinition p) { + boolean needs = !p.hasUserData("hack.regnerated") && Utilities.existsInList(p.getUrl(), "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaireresponse"); + if (needs) { + p.setUserData("hack.regnerated", "yes"); + } + return needs; + } + + @Override + public boolean isDatatype(String typeSimple) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean isResource(String t) { + StructureDefinition sd; + try { + sd = context.fetchResource(StructureDefinition.class, "http://hl7.org/fhir/StructureDefinition/"+t); + } catch (Exception e) { + return false; + } + if (sd == null) + return false; + if (sd.getDerivation() == TypeDerivationRule.CONSTRAINT) + return false; + return sd.getKind() == StructureDefinitionKind.RESOURCE; + } + + @Override + public boolean hasLinkFor(String typeSimple) { + return false; + } + + @Override + public String getLinkFor(String corePath, String typeSimple) { + return null; + } + + @Override + public BindingResolution resolveBinding(StructureDefinition profile, ElementDefinitionBindingComponent binding, String path) { + return null; + } + + @Override + public BindingResolution resolveBinding(StructureDefinition profile, String url, String path) { + return null; + } + + @Override + public String getLinkForProfile(StructureDefinition profile, String url) { + return null; + } + @Override + public boolean prependLinks() { + return false; + } + +} + 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 40f3dedbd..62734717b 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 @@ -87,8 +87,8 @@ import javax.annotation.Nonnull; * implementation. * * The functionality it provides is - * - get access to parsers, validators, narrative builders etc - * (you can't create these directly because they need access + * - get access to canonical resources,terminology services, and validator + * (you can't create a validator directly because it needs access * to the right context for their information) * * - find resources that the tools need to carry out their tasks @@ -100,10 +100,121 @@ import javax.annotation.Nonnull; * * @author Grahame */ -public interface IWorkerContext { - public interface IPackageLoadingTracker { - public void packageLoaded(String pid, String version); +public interface IWorkerContext { + + class ValidationResult { + private ConceptDefinitionComponent definition; + private String system; + private IssueSeverity severity; + private String message; + private TerminologyServiceErrorClass errorClass; + private String txLink; + + @Override + public String toString() { + return "ValidationResult [definition=" + definition + ", system=" + system + ", severity=" + severity + ", message=" + message + ", errorClass=" + + errorClass + ", txLink=" + txLink + "]"; + } + + public ValidationResult(IssueSeverity severity, String message) { + this.severity = severity; + this.message = message; + } + + public ValidationResult(String system, ConceptDefinitionComponent definition) { + this.system = system; + this.definition = definition; + } + + public ValidationResult(IssueSeverity severity, String message, String system, ConceptDefinitionComponent definition) { + this.severity = severity; + this.message = message; + this.system = system; + this.definition = definition; + } + + public ValidationResult(IssueSeverity severity, String message, TerminologyServiceErrorClass errorClass) { + this.severity = severity; + this.message = message; + this.errorClass = errorClass; + } + + public boolean isOk() { + return severity == null || severity == IssueSeverity.INFORMATION || severity == IssueSeverity.WARNING; + } + + public String getSystem() { + return system; + } + + public String getDisplay() { + return definition == null ? null : definition.getDisplay(); + } + + public String getCode() { + return definition == null ? null : definition.getCode(); + } + + public String getDefinition() { + return definition == null ? null : definition.getDefinition(); + } + + public ConceptDefinitionComponent asConceptDefinition() { + return definition; + } + + public IssueSeverity getSeverity() { + return severity; + } + + public String getMessage() { + return message; + } + + public boolean IsNoService() { + return errorClass == TerminologyServiceErrorClass.NOSERVICE; + } + + public TerminologyServiceErrorClass getErrorClass() { + return errorClass; + } + + public ValidationResult setSeverity(IssueSeverity severity) { + this.severity = severity; + return this; + } + + public ValidationResult setMessage(String message) { + this.message = message; + return this; + } + + public ValidationResult setErrorClass(TerminologyServiceErrorClass errorClass) { + this.errorClass = errorClass; + return this; + } + + public String getTxLink() { + return txLink; + } + + public ValidationResult setTxLink(String txLink) { + this.txLink = txLink; + return this; + } + + public boolean hasMessage() { + return message != null; + } + + public Coding asCoding() { + if (isOk() && definition != null && definition.getCode() != null) { + return new Coding(system, definition.getCode(), definition.getDisplay()); + } else { + return null; + } + } } public class CodingValidationRequest { @@ -223,10 +334,6 @@ public interface IWorkerContext { } - public interface ICanonicalResourceLocator { - void findResource(Object caller, String url); // if it can be found, put it in the context - } - public interface IContextResourceLoader { /** * @return List of the resource types that should be loaded @@ -263,9 +370,9 @@ public interface IWorkerContext { String getResourcePath(Resource resource); /** - * called when a mew package is being loaded + * called when a new package is being loaded * - * this is called by loadPacakgeAndDependencies when a new package is loaded + * this is called by loadPackageAndDependencies when a new package is loaded * @param npm * @return * @throws IOException @@ -275,59 +382,22 @@ public interface IWorkerContext { } /** - * Get the versions of the definitions loaded in context + * Get the version of the definitions loaded in context + * This *does not* have to be 5.0 (R5) - the context can load other versions + * * @return */ public String getVersion(); /** - * return the link to the base of the specification for the loaded version e.g. http://hl7.org/fhir/R4 + * Get the UCUM service that provides access to units of measure reasoning services + * + * This service might not be available + * + * @return */ - public String getSpecUrl(); - - // get the UCUM service (might not be available) public UcumService getUcumService(); - - // -- Parsers (read and write instances) ---------------------------------------- - - - /** - * Get a parser to read/write instances. Use the defined type (will be extended - * as further types are added, though the only currently anticipate type is RDF) - * - * XML/JSON - the standard renderers - * XHTML - render the narrative only (generate it if necessary) - * - * @param type - * @return - */ - public IParser getParser(ParserType type); - - /** - * Get a parser to read/write instances. Determine the type - * from the stated type. Supported value for type: - * - the recommended MIME types - * - variants of application/xml and application/json - * - _format values xml, json - * - * @param type - * @return - */ - public IParser getParser(String type); - - /** - * Get a JSON parser - * - * @return - */ - public IParser newJsonParser(); - - /** - * Get an XML parser - * - * @return - */ - public IParser newXmlParser(); + public void setUcumService(UcumService ucumService); /** * Get a validator that can check whether a resource is valid @@ -358,6 +428,8 @@ public interface IWorkerContext { * It's an error if the second form doesn't agree with class_. It's an * error if class_ is null for the last form * + * class can be Resource, DomainResource or CanonicalResource, which means resource of all kinds + * * @param resource * @param Reference * @return @@ -379,6 +451,17 @@ public interface IWorkerContext { */ public T fetchResource(Class class_, String uri, CanonicalResource canonicalForSource); + /** + * Fetch all the resources of a particular type. if class == (null | Resource | DomainResource | CanonicalResource) return everything + * + * @param + * @param class_ + * @param uri + * @param canonicalForSource + * @return + */ + public List fetchResourcesByType(Class class_); + /** * Variation of fetchResource when you have a string type, and don't need the right class * @@ -453,40 +536,6 @@ public interface IWorkerContext { */ public Set getResourceNamesAsSet(); - /** - * @return a list of the resource names that are canonical resources defined for this version - */ - public List getCanonicalResourceNames(); - - /** - * @return a list of the resource and type names defined for this version - */ - public List getTypeNames(); - - /** - * @return a list of all structure definitions, with snapshots generated (if possible) - */ - public List allStructures(); - - /** - * @return a list of all structure definitions, without trying to generate snapshots - */ - public List getStructures(); - - /** - * @return a list of all conformance resources - */ - public List allConformanceResources(); - - /** - * Given a structure definition, generate a snapshot (or regenerate it) - * @param p - * @throws DefinitionException - * @throws FHIRException - */ - public void generateSnapshot(StructureDefinition p) throws DefinitionException, FHIRException; - public void generateSnapshot(StructureDefinition mr, boolean ifLogical); - // -- Terminology services ------------------------------------------------------ /** @@ -509,6 +558,8 @@ public interface IWorkerContext { * return null if there isn't one (then the tool might try * supportsSystem) * + * This is a short cut for fetchResource(CodeSystem.class...) + * * @param system * @return */ @@ -524,20 +575,14 @@ public interface IWorkerContext { * * in the Conformance resource * + * Not that not all supported code systems have an available CodeSystem resource + * * @param system * @return * @throws Exception */ public boolean supportsSystem(String system) throws TerminologyServiceException; - /** - * find concept maps for a source - * @param url - * @return - * @throws FHIRException - */ - public List findMapsForSource(String url) throws FHIRException; - /** * ValueSet Expansion - see $expand * @@ -574,127 +619,25 @@ public interface IWorkerContext { */ ValueSetExpansionOutcome expandVS(ConceptSetComponent inc, boolean hierarchical, boolean noInactive) throws TerminologyServiceException; + /** + * get/set the locale used when creating messages + * + * todo: what's the difference? + * + * @return + */ Locale getLocale(); - void setLocale(Locale locale); - - String formatMessage(String theMessage, Object... theMessageArguments); - void setValidationMessageLanguage(Locale locale); - class ValidationResult { - private ConceptDefinitionComponent definition; - private String system; - private IssueSeverity severity; - private String message; - private TerminologyServiceErrorClass errorClass; - private String txLink; - - @Override - public String toString() { - return "ValidationResult [definition=" + definition + ", system=" + system + ", severity=" + severity + ", message=" + message + ", errorClass=" - + errorClass + ", txLink=" + txLink + "]"; - } - - public ValidationResult(IssueSeverity severity, String message) { - this.severity = severity; - this.message = message; - } - - public ValidationResult(String system, ConceptDefinitionComponent definition) { - this.system = system; - this.definition = definition; - } - - public ValidationResult(IssueSeverity severity, String message, String system, ConceptDefinitionComponent definition) { - this.severity = severity; - this.message = message; - this.system = system; - this.definition = definition; - } - - public ValidationResult(IssueSeverity severity, String message, TerminologyServiceErrorClass errorClass) { - this.severity = severity; - this.message = message; - this.errorClass = errorClass; - } - - public boolean isOk() { - return severity == null || severity == IssueSeverity.INFORMATION || severity == IssueSeverity.WARNING; - } - - public String getSystem() { - return system; - } - - public String getDisplay() { - return definition == null ? null : definition.getDisplay(); - } - - public String getCode() { - return definition == null ? null : definition.getCode(); - } - - public String getDefinition() { - return definition == null ? null : definition.getDefinition(); - } - - public ConceptDefinitionComponent asConceptDefinition() { - return definition; - } - - public IssueSeverity getSeverity() { - return severity; - } - - public String getMessage() { - return message; - } - - public boolean IsNoService() { - return errorClass == TerminologyServiceErrorClass.NOSERVICE; - } - - public TerminologyServiceErrorClass getErrorClass() { - return errorClass; - } - - public ValidationResult setSeverity(IssueSeverity severity) { - this.severity = severity; - return this; - } - - public ValidationResult setMessage(String message) { - this.message = message; - return this; - } - - public ValidationResult setErrorClass(TerminologyServiceErrorClass errorClass) { - this.errorClass = errorClass; - return this; - } - - public String getTxLink() { - return txLink; - } - - public ValidationResult setTxLink(String txLink) { - this.txLink = txLink; - return this; - } - - public boolean hasMessage() { - return message != null; - } - - public Coding asCoding() { - if (isOk() && definition != null && definition.getCode() != null) { - return new Coding(system, definition.getCode(), definition.getDisplay()); - } else { - return null; - } - } - } + /** + * Access to the contexts internationalised error messages + * + * @param theMessage + * @param theMessageArguments + * @return + */ + String formatMessage(String theMessage, Object... theMessageArguments); /** * Validation of a code - consult the terminology infrstructure and/or service @@ -780,31 +723,32 @@ public interface IWorkerContext { */ public ValidationResult validateCode(ValidationOptions options, Coding code, ValueSet vs); + /** + * See comments in ValidationContextCarrier. This is called when there might be additional value sets etc + * available in the context, but we don't want to pre-process them. + * + * @param options + * @param code + * @param vs + * @param ctxt + * @return + */ public ValidationResult validateCode(ValidationOptions options, Coding code, ValueSet vs, ValidationContextCarrier ctxt); + /** + * Batch validate code - reduce latency and do a bunch of codes in a single server call. + * Each is the same as a validateCode + * + * @param options + * @param codes + * @param vs + */ public void validateCodeBatch(ValidationOptions options, List codes, ValueSet vs); - /** - * returns the recommended tla for the type (from the structure definitions) - * - * @param name - * @return - */ - public String getAbbreviation(String name); - - - /** - * translate an OID to a URI (look through known NamingSystems) - * @param code - * @return - */ - public String oid2Uri(String code); + + // todo: figure these out public Map getNSUrlMap(); - - /** - * @return true if the contxt has a terminology caching service internally - */ - public boolean hasCache(); + public TranslationServices translator(); public interface ILoggingService { public enum LogCategory { @@ -818,28 +762,30 @@ public interface IWorkerContext { public void logMessage(String message); // status messages, always display public void logDebugMessage(LogCategory category, String message); // verbose; only when debugging } - public void setLogger(@Nonnull ILoggingService logger); public ILoggingService getLogger(); public boolean isNoTerminologyServer(); public Set getCodeSystemsUsed(); - public TranslationServices translator(); - public List listTransforms(); - public StructureMap getTransform(String url); - - public String getOverrideVersionNs(); - public void setOverrideVersionNs(String value); - - public StructureDefinition fetchTypeDefinition(String typeName); - public StructureDefinition fetchRawProfile(String url); + public int getClientRetryCount(); + public IWorkerContext setClientRetryCount(int value); - public void setUcumService(UcumService ucumService); + public TimeTracker clock(); - public String getLinkForUrl(String corePath, String s); + /** + * This is a short cut for fetchResource(StructureDefinition.class, ...) + * but it accepts a typename - that is, it resolves based on StructureDefinition.type + * or StructureDefinition.url + * + * @param typeName + * @return + */ + public StructureDefinition fetchTypeDefinition(String typeName); + /** * Returns a set of keys that can be used to get binaries from this context. + * The binaries come from the loaded packages (mostly the pubpack) * * @return a set of binaries or null */ @@ -860,6 +806,10 @@ public interface IWorkerContext { */ public byte[] getBinaryForKey(String binaryKey); + /* + * Todo: move these loaders out to IWorkerContextManager + * + */ /** * Load relevant resources of the appropriate types (as specified by the loader) from the nominated package * @@ -904,12 +854,8 @@ public interface IWorkerContext { public boolean hasPackage(PackageVersion pack); public PackageDetails getPackage(PackageVersion pack); - public int getClientRetryCount(); - public IWorkerContext setClientRetryCount(int value); - - public TimeTracker clock(); - public IPackageLoadingTracker getPackageTracker(); - public IWorkerContext setPackageTracker(IPackageLoadingTracker packageTracker); + public IWorkerContextManager.IPackageLoadingTracker getPackageTracker(); + public IWorkerContext setPackageTracker(IWorkerContextManager.IPackageLoadingTracker packageTracker); public PackageVersion getPackageForUrl(String url); } \ No newline at end of file diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/IWorkerContextManager.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/IWorkerContextManager.java new file mode 100644 index 000000000..c33b19357 --- /dev/null +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/IWorkerContextManager.java @@ -0,0 +1,13 @@ +package org.hl7.fhir.r5.context; + +public interface IWorkerContextManager { + + interface IPackageLoadingTracker { + public void packageLoaded(String pid, String version); + } + + interface ICanonicalResourceLocator { + void findResource(Object caller, String url); // if it can be found, put it in the context + } + +} 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 922380c89..055099396 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 @@ -93,7 +93,7 @@ import ca.uhn.fhir.parser.DataFormatException; * very light client to connect to an open unauthenticated terminology service */ -public class SimpleWorkerContext extends BaseWorkerContext implements IWorkerContext, ProfileKnowledgeProvider { +public class SimpleWorkerContext extends BaseWorkerContext implements IWorkerContext { public static class PackageResourceLoader extends CanonicalResourceProxy { @@ -139,13 +139,11 @@ public class SimpleWorkerContext extends BaseWorkerContext implements IWorkerCon private String revision; private String date; private IValidatorFactory validatorFactory; - private boolean ignoreProfileErrors; private boolean progress; private final List loadedPackages = new ArrayList<>(); private boolean canNoTS; private XVerExtensionManager xverManager; private boolean allowLazyLoading = true; - private boolean suppressDebugMessages; private SimpleWorkerContext() throws IOException, FHIRException { super(); @@ -551,34 +549,6 @@ public class SimpleWorkerContext extends BaseWorkerContext implements IWorkerCon binaries.put(name, bytes); } - @Override - public IParser getParser(ParserType type) { - switch (type) { - case JSON: return newJsonParser(); - case XML: return newXmlParser(); - default: - throw new Error(formatMessage(I18nConstants.PARSER_TYPE__NOT_SUPPORTED, type.toString())); - } - } - - @Override - public IParser getParser(String type) { - if (type.equalsIgnoreCase("JSON")) - return new JsonParser(); - if (type.equalsIgnoreCase("XML")) - return new XmlParser(); - throw new Error(formatMessage(I18nConstants.PARSER_TYPE__NOT_SUPPORTED, type.toString())); - } - - @Override - public IParser newJsonParser() { - return new JsonParser(); - } - @Override - public IParser newXmlParser() { - return new XmlParser(); - } - @Override public IResourceValidator newValidator() throws FHIRException { if (validatorFactory == null) @@ -600,68 +570,7 @@ public class SimpleWorkerContext extends BaseWorkerContext implements IWorkerCon return result; } - @Override - public List getTypeNames() { - List result = new ArrayList(); - for (StructureDefinition sd : listStructures()) { - if (sd.getKind() != StructureDefinitionKind.LOGICAL && sd.getDerivation() == TypeDerivationRule.SPECIALIZATION) - result.add(sd.getName()); - } - Collections.sort(result); - return result; - } - - @Override - public String getAbbreviation(String name) { - return "xxx"; - } - - @Override - public boolean isDatatype(String typeSimple) { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean isResource(String t) { - StructureDefinition sd; - try { - sd = fetchResource(StructureDefinition.class, "http://hl7.org/fhir/StructureDefinition/"+t); - } catch (Exception e) { - return false; - } - if (sd == null) - return false; - if (sd.getDerivation() == TypeDerivationRule.CONSTRAINT) - return false; - return sd.getKind() == StructureDefinitionKind.RESOURCE; - } - - @Override - public boolean hasLinkFor(String typeSimple) { - return false; - } - - @Override - public String getLinkFor(String corePath, String typeSimple) { - return null; - } - - @Override - public BindingResolution resolveBinding(StructureDefinition profile, ElementDefinitionBindingComponent binding, String path) { - return null; - } - - @Override - public BindingResolution resolveBinding(StructureDefinition profile, String url, String path) { - return null; - } - - @Override - public String getLinkForProfile(StructureDefinition profile, String url) { - return null; - } - + public Questionnaire getQuestionnaire() { return questionnaire; } @@ -670,30 +579,7 @@ public class SimpleWorkerContext extends BaseWorkerContext implements IWorkerCon this.questionnaire = questionnaire; } - @Override - public List allStructures() { - List result = new ArrayList(); - Set set = new HashSet(); - for (StructureDefinition sd : listStructures()) { - if (!set.contains(sd)) { - try { - generateSnapshot(sd); - // new XmlParser().setOutputStyle(OutputStyle.PRETTY).compose(new FileOutputStream(Utilities.path("[tmp]", "snapshot", tail(sd.getUrl())+".xml")), sd); - } catch (Exception e) { - if (!suppressDebugMessages) { - System.out.println("Unable to generate snapshot for "+tail(sd.getUrl()) +" from "+tail(sd.getBaseDefinition())+" because "+e.getMessage()); - if (true) { - e.printStackTrace(); - } - } - } - result.add(sd); - set.add(sd); - } - } - return result; - } - + public void loadBinariesFromFolder(String folder) throws IOException { for (String n : new File(folder).list()) { @@ -732,15 +618,7 @@ public class SimpleWorkerContext extends BaseWorkerContext implements IWorkerCon } } - @Override - public boolean prependLinks() { - return false; - } - - @Override - public boolean hasCache() { - return true; - } + @Override public String getVersion() { @@ -750,7 +628,7 @@ public class SimpleWorkerContext extends BaseWorkerContext implements IWorkerCon public List findTransformsforSource(String url) { List res = new ArrayList(); - for (StructureMap map : listTransforms()) { + for (StructureMap map : fetchResourcesByType(StructureMap.class)) { boolean match = false; boolean ok = true; for (StructureMapStructureComponent t : map.getStructure()) { @@ -779,82 +657,17 @@ public class SimpleWorkerContext extends BaseWorkerContext implements IWorkerCon if (r instanceof StructureDefinition) { StructureDefinition p = (StructureDefinition)r; try { - generateSnapshot(p); + new ContextUtilities(this).generateSnapshot(p); } catch (Exception e) { // not sure what to do in this case? - if (!suppressDebugMessages) { - System.out.println("Unable to generate snapshot for "+uri+": "+e.getMessage()); - } + System.out.println("Unable to generate snapshot for "+uri+": "+e.getMessage()); } } return r; } - - @Override - public StructureDefinition fetchRawProfile(String uri) { - StructureDefinition r = super.fetchResource(StructureDefinition.class, uri); - return r; - } - - @Override - public void generateSnapshot(StructureDefinition p) throws FHIRException { - generateSnapshot(p, false); - } - - @Override - public void generateSnapshot(StructureDefinition p, boolean logical) throws FHIRException { - if ((!p.hasSnapshot() || isProfileNeedsRegenerate(p) ) && (logical || p.getKind() != StructureDefinitionKind.LOGICAL)) { - if (!p.hasBaseDefinition()) - throw new DefinitionException(formatMessage(I18nConstants.PROFILE___HAS_NO_BASE_AND_NO_SNAPSHOT, p.getName(), p.getUrl())); - StructureDefinition sd = fetchResource(StructureDefinition.class, p.getBaseDefinition()); - if (sd == null && "http://hl7.org/fhir/StructureDefinition/Base".equals(p.getBaseDefinition())) { - sd = ProfileUtilities.makeBaseDefinition(p.getFhirVersion()); - } - if (sd == null) { - throw new DefinitionException(formatMessage(I18nConstants.PROFILE___BASE__COULD_NOT_BE_RESOLVED, p.getName(), p.getUrl(), p.getBaseDefinition())); - } - List msgs = new ArrayList(); - List errors = new ArrayList(); - ProfileUtilities pu = new ProfileUtilities(this, msgs, this); - pu.setAutoFixSliceNames(true); - pu.setThrowException(false); - if (xverManager == null) { - xverManager = new XVerExtensionManager(this); - } - pu.setXver(xverManager); - if (sd.getDerivation() == TypeDerivationRule.CONSTRAINT) { - pu.sortDifferential(sd, p, p.getUrl(), errors, true); - } - pu.setDebug(false); - for (String err : errors) - msgs.add(new ValidationMessage(Source.ProfileValidator, IssueType.EXCEPTION, p.getUserString("path"), "Error sorting Differential: "+err, ValidationMessage.IssueSeverity.ERROR)); - pu.generateSnapshot(sd, p, p.getUrl(), sd.getUserString("webroot"), p.getName()); - for (ValidationMessage msg : msgs) { - if ((!ignoreProfileErrors && msg.getLevel() == ValidationMessage.IssueSeverity.ERROR) || msg.getLevel() == ValidationMessage.IssueSeverity.FATAL) - throw new DefinitionException(formatMessage(I18nConstants.PROFILE___ELEMENT__ERROR_GENERATING_SNAPSHOT_, p.getName(), p.getUrl(), msg.getLocation(), msg.getMessage())); - } - if (!p.hasSnapshot()) - throw new FHIRException(formatMessage(I18nConstants.PROFILE___ERROR_GENERATING_SNAPSHOT, p.getName(), p.getUrl())); - pu = null; - } - } - // work around the fact that some Implementation guides were published with old snapshot generators that left invalid snapshots behind. - private boolean isProfileNeedsRegenerate(StructureDefinition p) { - boolean needs = !p.hasUserData("hack.regnerated") && Utilities.existsInList(p.getUrl(), "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaireresponse"); - if (needs) { - p.setUserData("hack.regnerated", "yes"); - } - return needs; - } - public boolean isIgnoreProfileErrors() { - return ignoreProfileErrors; - } - public void setIgnoreProfileErrors(boolean ignoreProfileErrors) { - this.ignoreProfileErrors = ignoreProfileErrors; - } public String listMapUrls() { return Utilities.listCanonicalUrls(transforms.keys()); @@ -923,14 +736,6 @@ public class SimpleWorkerContext extends BaseWorkerContext implements IWorkerCon this.allowLazyLoading = allowLazyLoading; } - public boolean isSuppressDebugMessages() { - return suppressDebugMessages; - } - - public void setSuppressDebugMessages(boolean suppressDebugMessages) { - this.suppressDebugMessages = suppressDebugMessages; - } - } diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/Element.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/Element.java index 5d546ff9c..9532d4c6c 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/Element.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/Element.java @@ -42,6 +42,7 @@ import java.util.Set; import org.apache.commons.lang3.Validate; import org.hl7.fhir.exceptions.FHIRException; import org.hl7.fhir.r5.conformance.ProfileUtilities; +import org.hl7.fhir.r5.context.ContextUtilities; import org.hl7.fhir.r5.model.Base; import org.hl7.fhir.r5.model.DataType; import org.hl7.fhir.r5.model.ElementDefinition; @@ -486,7 +487,7 @@ public class Element extends Base { } private boolean isDataType(Base v) { - return v instanceof DataType && property.getContext().getTypeNames().contains(v.fhirType()); + return v instanceof DataType && new ContextUtilities(property.getContext()).getTypeNames().contains(v.fhirType()); } @Override @@ -845,7 +846,7 @@ public class Element extends Base { private List children; public ElementSortComparator(Element e, Property property) { String tn = e.getType(); - StructureDefinition sd = property.getContext().fetchResource(StructureDefinition.class, ProfileUtilities.sdNs(tn, property.getContext().getOverrideVersionNs())); + StructureDefinition sd = property.getContext().fetchResource(StructureDefinition.class, ProfileUtilities.sdNs(tn, null)); if (sd != null && !sd.getAbstract()) children = sd.getSnapshot().getElement(); else diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/JsonParser.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/JsonParser.java index bb749783d..53f7be046 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/JsonParser.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/JsonParser.java @@ -379,7 +379,7 @@ public class JsonParser extends ParserBase { logError(line(res), col(res), npath, IssueType.INVALID, context.formatMessage(I18nConstants.UNABLE_TO_FIND_RESOURCETYPE_PROPERTY), IssueSeverity.FATAL); } else { String name = rt.getAsString(); - StructureDefinition sd = context.fetchResource(StructureDefinition.class, ProfileUtilities.sdNs(name, context.getOverrideVersionNs())); + StructureDefinition sd = context.fetchResource(StructureDefinition.class, ProfileUtilities.sdNs(name, null)); if (sd == null) { logError(line(res), col(res), npath, IssueType.INVALID, context.formatMessage(I18nConstants.CONTAINED_RESOURCE_DOES_NOT_APPEAR_TO_BE_A_FHIR_RESOURCE_UNKNOWN_NAME_, name), IssueSeverity.FATAL); } else { diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/ObjectConverter.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/ObjectConverter.java index 7ca34a4e7..4fbc7c8db 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/ObjectConverter.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/ObjectConverter.java @@ -86,7 +86,7 @@ public class ObjectConverter { if (base == null) return null; String tn = base.fhirType(); - StructureDefinition sd = context.fetchResource(StructureDefinition.class, ProfileUtilities.sdNs(tn, context.getOverrideVersionNs())); + StructureDefinition sd = context.fetchResource(StructureDefinition.class, ProfileUtilities.sdNs(tn, null)); if (sd == null) throw new FHIRException("Unable to find definition for type "+tn); Element res = new Element(property.getName(), property); diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/ParserBase.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/ParserBase.java index e6294e210..322e123c2 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/ParserBase.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/ParserBase.java @@ -39,6 +39,7 @@ import java.util.List; import org.hl7.fhir.exceptions.DefinitionException; import org.hl7.fhir.exceptions.FHIRException; import org.hl7.fhir.exceptions.FHIRFormatError; +import org.hl7.fhir.r5.context.ContextUtilities; import org.hl7.fhir.r5.context.IWorkerContext; import org.hl7.fhir.r5.formats.FormatUtilities; import org.hl7.fhir.r5.formats.IParser.OutputStyle; @@ -156,7 +157,7 @@ public abstract class ParserBase { logError(line, col, name, IssueType.STRUCTURE, context.formatMessage(I18nConstants.THIS_CANNOT_BE_PARSED_AS_A_FHIR_OBJECT_NO_NAME), IssueSeverity.FATAL); return null; } - for (StructureDefinition sd : context.allStructures()) { + for (StructureDefinition sd : new ContextUtilities(context).allStructures()) { if (sd.getDerivation() == TypeDerivationRule.SPECIALIZATION && !sd.getUrl().startsWith("http://hl7.org/fhir/StructureDefinition/de-")) { if(name.equals(sd.getType()) && (ns == null || ns.equals(FormatUtilities.FHIR_NS)) && !ToolingExtensions.hasExtension(sd, "http://hl7.org/fhir/StructureDefinition/elementdefinition-namespace")) return sd; @@ -175,15 +176,15 @@ public abstract class ParserBase { return null; } // first pass: only look at base definitions - for (StructureDefinition sd : context.getStructures()) { + for (StructureDefinition sd : context.fetchResourcesByType(StructureDefinition.class)) { if (sd.getUrl().equals("http://hl7.org/fhir/StructureDefinition/"+name)) { - context.generateSnapshot(sd); + new ContextUtilities(context).generateSnapshot(sd); return sd; } } - for (StructureDefinition sd : context.getStructures()) { + for (StructureDefinition sd : context.fetchResourcesByType(StructureDefinition.class)) { if (name.equals(sd.getType()) && sd.getDerivation() == TypeDerivationRule.SPECIALIZATION) { - context.generateSnapshot(sd); + new ContextUtilities(context).generateSnapshot(sd); return sd; } } diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/Property.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/Property.java index d9d6a052e..880d0bda5 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/Property.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/Property.java @@ -265,7 +265,7 @@ public class Property { return false; StructureDefinition sd = context.fetchResource(StructureDefinition.class, structure.getUrl().substring(0, structure.getUrl().lastIndexOf("/")+1)+getType(name)); if (sd == null) - sd = context.fetchResource(StructureDefinition.class, ProfileUtilities.sdNs(getType(name), context.getOverrideVersionNs())); + sd = context.fetchResource(StructureDefinition.class, ProfileUtilities.sdNs(getType(name), null)); if (sd != null && sd.getKind() == StructureDefinitionKind.PRIMITIVETYPE) return true; if (sd == null || sd.getKind() != StructureDefinitionKind.LOGICAL) @@ -348,7 +348,7 @@ public class Property { assert aType.getProfile().size() == 1; url = aType.getProfile().get(0).getValue(); } else { - url = ProfileUtilities.sdNs(t, context.getOverrideVersionNs()); + url = ProfileUtilities.sdNs(t, null); } break; } diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/XmlParser.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/XmlParser.java index 0c5a0ce9c..5062f4db2 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/XmlParser.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/XmlParser.java @@ -534,7 +534,7 @@ public class XmlParser extends ParserBase { private void parseResource(String string, org.w3c.dom.Element container, Element parent, Property elementProperty) throws FHIRFormatError, DefinitionException, FHIRException, IOException { org.w3c.dom.Element res = XMLUtil.getFirstChild(container); String name = res.getLocalName(); - StructureDefinition sd = context.fetchResource(StructureDefinition.class, ProfileUtilities.sdNs(name, context.getOverrideVersionNs())); + StructureDefinition sd = context.fetchResource(StructureDefinition.class, ProfileUtilities.sdNs(name, null)); if (sd == null) throw new FHIRFormatError(context.formatMessage(I18nConstants.CONTAINED_RESOURCE_DOES_NOT_APPEAR_TO_BE_A_FHIR_RESOURCE_UNKNOWN_NAME_, res.getLocalName())); parent.updateProperty(new Property(context, sd.getSnapshot().getElement().get(0), sd), SpecialElement.fromProperty(parent.getProperty()), elementProperty); diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/ProfileDrivenRenderer.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/ProfileDrivenRenderer.java index e876d539b..fa3c1aba9 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/ProfileDrivenRenderer.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/ProfileDrivenRenderer.java @@ -15,6 +15,7 @@ import org.hl7.fhir.exceptions.DefinitionException; import org.hl7.fhir.exceptions.FHIRException; import org.hl7.fhir.exceptions.FHIRFormatError; import org.hl7.fhir.r5.conformance.ProfileUtilities; +import org.hl7.fhir.r5.context.ContextUtilities; import org.hl7.fhir.r5.formats.FormatUtilities; import org.hl7.fhir.r5.model.Address; import org.hl7.fhir.r5.model.Annotation; @@ -946,7 +947,7 @@ public class ProfileDrivenRenderer extends ResourceRenderer { } if (xverManager.matchingUrl(url) && xverManager.status(url) == XVerExtensionStatus.Valid) { ed = xverManager.makeDefinition(url); - getContext().getWorker().generateSnapshot(ed); + new ContextUtilities(getContext().getWorker()).generateSnapshot(ed); getContext().getWorker().cacheResource(ed); } } diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/QuestionnaireRenderer.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/QuestionnaireRenderer.java index c4092eb5c..581ee6d02 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/QuestionnaireRenderer.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/QuestionnaireRenderer.java @@ -7,6 +7,7 @@ import java.util.List; import java.util.UUID; import org.hl7.fhir.exceptions.FHIRException; +import org.hl7.fhir.r5.context.ContextUtilities; import org.hl7.fhir.r5.model.CanonicalType; import org.hl7.fhir.r5.model.CodeType; import org.hl7.fhir.r5.model.CodeableConcept; @@ -133,7 +134,7 @@ public class QuestionnaireRenderer extends TerminologyRenderer { li.tx(opt.getValue().primitiveValue()); } else if (opt.getValue() instanceof Coding) { Coding c = (Coding) opt.getValue(); - String link = c.hasSystem() ? context.getWorker().getLinkForUrl(context.getSpecificationLink(), c.getSystem()) : null; + String link = c.hasSystem() ? new ContextUtilities(context.getWorker()).getLinkForUrl(context.getSpecificationLink(), c.getSystem()) : null; if (link == null) { li.tx(c.getSystem()+"#"+c.getCode()); } else { diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/ValueSetRenderer.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/ValueSetRenderer.java index 7333c0175..b9e5632d4 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/ValueSetRenderer.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/ValueSetRenderer.java @@ -27,6 +27,7 @@ import org.hl7.fhir.r5.model.Enumerations.FilterOperator; import org.hl7.fhir.r5.model.Extension; import org.hl7.fhir.r5.model.ExtensionHelper; import org.hl7.fhir.r5.model.PrimitiveType; +import org.hl7.fhir.r5.model.Reference; import org.hl7.fhir.r5.model.Resource; import org.hl7.fhir.r5.model.UriType; import org.hl7.fhir.r5.model.ValueSet; @@ -97,22 +98,33 @@ public class ValueSetRenderer extends TerminologyRenderer { private List findReleventMaps(ValueSet vs) throws FHIRException { List res = new ArrayList(); - for (CanonicalResource md : getContext().getWorker().allConformanceResources()) { - if (md instanceof ConceptMap) { - ConceptMap cm = (ConceptMap) md; - if (isSource(vs, cm.getSourceScope())) { - ConceptMapRenderInstructions re = findByTarget(cm.getTargetScope()); - if (re == null) { - re = new ConceptMapRenderInstructions(cm.present(), cm.getUrl(), false); - } - if (re != null) { - ValueSet vst = cm.hasTargetScope() ? getContext().getWorker().fetchResource(ValueSet.class, cm.hasTargetScopeCanonicalType() ? cm.getTargetScopeCanonicalType().getValue() : cm.getTargetScopeUriType().asStringValue()) : null; - res.add(new UsedConceptMap(re, vst == null ? cm.getUserString("path") : vst.getUserString("path"), cm)); - } + for (ConceptMap cm : getContext().getWorker().fetchResourcesByType(ConceptMap.class)) { + if (isSource(vs, cm.getSourceScope())) { + ConceptMapRenderInstructions re = findByTarget(cm.getTargetScope()); + if (re == null) { + re = new ConceptMapRenderInstructions(cm.present(), cm.getUrl(), false); + } + if (re != null) { + ValueSet vst = cm.hasTargetScope() ? getContext().getWorker().fetchResource(ValueSet.class, cm.hasTargetScopeCanonicalType() ? cm.getTargetScopeCanonicalType().getValue() : cm.getTargetScopeUriType().asStringValue()) : null; + res.add(new UsedConceptMap(re, vst == null ? cm.getUserString("path") : vst.getUserString("path"), cm)); } } } return res; + +// @Override +// public List findMapsForSource(String url) throws FHIRException { +// synchronized (lock) { +// List res = new ArrayList(); +// for (ConceptMap map : maps.getList()) { +// if (((Reference) map.getSourceScope()).getReference().equals(url)) { +// res.add(map); +// } +// } +// return res; +// } +// } + // Map mymaps = new HashMap(); // for (ConceptMap a : context.getWorker().findMapsForSource(vs.getUrl())) { // String url = ""; @@ -1272,7 +1284,7 @@ public class ValueSetRenderer extends TerminologyRenderer { } ValueSetExpansionComponent vse = null; - if (!context.isNoSlowLookup() && !getContext().getWorker().hasCache()) { + if (!context.isNoSlowLookup()) { // && !getContext().getWorker().hasCache()) { removed GG 20220107 like what is this trying to do? try { ValueSetExpansionOutcome vso = getContext().getWorker().expandVS(inc, false, false); ValueSet valueset = vso.getValueset(); diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/utils/Resolver.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/utils/Resolver.java index 724466b3f..9e7b6941b 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/utils/Resolver.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/utils/Resolver.java @@ -56,7 +56,7 @@ public class Resolver { } else if (rw instanceof ElementWrappers.ResourceWrapperMetaElement) { this.element = ((ElementWrappers.ResourceWrapperMetaElement) rw).getElement(); } else { - throw new Error("Not supported yet"); + // this is not supported for now... throw new Error("Not supported yet"); } } diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/terminologies/ValueSetExpansionCache.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/terminologies/ValueSetExpansionCache.java index de3156623..8d3e47f89 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/terminologies/ValueSetExpansionCache.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/terminologies/ValueSetExpansionCache.java @@ -72,6 +72,7 @@ import org.hl7.fhir.exceptions.FHIRFormatError; import org.hl7.fhir.r5.context.IWorkerContext; import org.hl7.fhir.r5.formats.IParser.OutputStyle; import org.hl7.fhir.r5.formats.JsonParser; +import org.hl7.fhir.r5.formats.XmlParser; import org.hl7.fhir.r5.model.CanonicalResource; import org.hl7.fhir.r5.model.OperationOutcome; import org.hl7.fhir.r5.model.Parameters; @@ -99,7 +100,7 @@ public class ValueSetExpansionCache implements ValueSetExpanderFactory { vso = context.expandVS(source, false, expParams == null || !expParams.getParameterBool("excludeNested")); if (cacheFolder != null) { FileOutputStream s = new FileOutputStream(Utilities.path(cacheFolder, makeFileName(source.getUrl()))); - context.newXmlParser().setOutputStyle(OutputStyle.PRETTY).compose(s, vso.getValueset()); + new XmlParser().setOutputStyle(OutputStyle.PRETTY).compose(s, vso.getValueset()); s.close(); } } @@ -153,7 +154,7 @@ public class ValueSetExpansionCache implements ValueSetExpanderFactory { if (f.getName().endsWith(".xml")) { final FileInputStream is = new FileInputStream(f); try { - Resource r = context.newXmlParser().setOutputStyle(OutputStyle.PRETTY).parse(is); + Resource r = new XmlParser().setOutputStyle(OutputStyle.PRETTY).parse(is); if (r instanceof OperationOutcome) { OperationOutcome oo = (OperationOutcome) r; expansions.put(ToolingExtensions.getExtension(oo,VS_ID_EXT).getValue().toString(), @@ -200,7 +201,7 @@ public class ValueSetExpansionCache implements ValueSetExpanderFactory { } if (cacheFolder != null) { FileOutputStream s = new FileOutputStream(Utilities.path(cacheFolder, makeFileName(md.getUrl()+"|"+md.getVersion()))); - context.newXmlParser().setOutputStyle(OutputStyle.PRETTY).compose(s, md); + new XmlParser().setOutputStyle(OutputStyle.PRETTY).compose(s, md); s.close(); } } diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/FHIRPathEngine.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/FHIRPathEngine.java index c3f6909f0..78d987b4b 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/FHIRPathEngine.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/FHIRPathEngine.java @@ -27,6 +27,7 @@ import org.hl7.fhir.exceptions.FHIRException; import org.hl7.fhir.exceptions.FHIRFormatError; import org.hl7.fhir.exceptions.PathEngineException; import org.hl7.fhir.r5.conformance.ProfileUtilities; +import org.hl7.fhir.r5.context.ContextUtilities; import org.hl7.fhir.r5.context.IWorkerContext; import org.hl7.fhir.r5.context.IWorkerContext.ValidationResult; import org.hl7.fhir.r5.model.Base; @@ -364,7 +365,7 @@ public class FHIRPathEngine { super(); this.worker = worker; profileUtilities = utilities; - for (StructureDefinition sd : worker.getStructures()) { + for (StructureDefinition sd : worker.fetchResourcesByType(StructureDefinition.class)) { if (sd.getDerivation() == TypeDerivationRule.SPECIALIZATION && sd.getKind() != StructureDefinitionKind.LOGICAL) { allTypes.put(sd.getName(), sd); } @@ -5524,22 +5525,22 @@ public class FHIRPathEngine { m = getElementDefinition(sd, type.substring(type.indexOf("#")+1), false, expr); if (m != null && hasDataType(m.definition)) { if (m.fixedType != null) { - StructureDefinition dt = worker.fetchResource(StructureDefinition.class, ProfileUtilities.sdNs(m.fixedType, worker.getOverrideVersionNs())); + StructureDefinition dt = worker.fetchResource(StructureDefinition.class, ProfileUtilities.sdNs(m.fixedType, null)); if (dt == null) { - throw makeException(expr, I18nConstants.FHIRPATH_NO_TYPE, ProfileUtilities.sdNs(m.fixedType, worker.getOverrideVersionNs()), "getChildTypesByName"); + throw makeException(expr, I18nConstants.FHIRPATH_NO_TYPE, ProfileUtilities.sdNs(m.fixedType, null), "getChildTypesByName"); } sdl.add(dt); } else for (TypeRefComponent t : m.definition.getType()) { - StructureDefinition dt = worker.fetchResource(StructureDefinition.class, ProfileUtilities.sdNs(t.getCode(), worker.getOverrideVersionNs())); + StructureDefinition dt = worker.fetchResource(StructureDefinition.class, ProfileUtilities.sdNs(t.getCode(), null)); if (dt == null) { - throw makeException(expr, I18nConstants.FHIRPATH_NO_TYPE, ProfileUtilities.sdNs(t.getCode(), worker.getOverrideVersionNs()), "getChildTypesByName"); + throw makeException(expr, I18nConstants.FHIRPATH_NO_TYPE, ProfileUtilities.sdNs(t.getCode(), null), "getChildTypesByName"); } - addTypeAndDescendents(sdl, dt, worker.allStructures()); + addTypeAndDescendents(sdl, dt, new ContextUtilities(worker).allStructures()); // also add any descendant types } } else { - addTypeAndDescendents(sdl, sd, worker.allStructures()); + addTypeAndDescendents(sdl, sd, new ContextUtilities(worker).allStructures()); if (type.contains("#")) { tail = type.substring(type.indexOf("#")+1); tail = tail.substring(tail.indexOf(".")); @@ -5683,7 +5684,7 @@ public class FHIRPathEngine { if (ed.getType().size() > 1) { // if there's more than one type, the test above would fail this throw new Error("Internal typing issue...."); } - StructureDefinition nsd = worker.fetchResource(StructureDefinition.class, ProfileUtilities.sdNs(ed.getType().get(0).getCode(), worker.getOverrideVersionNs())); + StructureDefinition nsd = worker.fetchResource(StructureDefinition.class, ProfileUtilities.sdNs(ed.getType().get(0).getCode(), null)); if (nsd == null) { throw makeException(expr, I18nConstants.FHIRPATH_NO_TYPE, ed.getType().get(0).getCode(), "getElementDefinition"); } @@ -5901,7 +5902,7 @@ public class FHIRPathEngine { if (ed.getTypes().get(0).hasProfile()) { return worker.fetchResource(StructureDefinition.class, ed.getTypes().get(0).getProfile().get(0).getValue()); } else { - return worker.fetchResource(StructureDefinition.class, ProfileUtilities.sdNs(ed.getTypes().get(0).getCode(), worker.getOverrideVersionNs())); + return worker.fetchResource(StructureDefinition.class, ProfileUtilities.sdNs(ed.getTypes().get(0).getCode(), null)); } } diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/GraphQLSchemaGenerator.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/GraphQLSchemaGenerator.java index ee0a1f6e2..7fa04a878 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/GraphQLSchemaGenerator.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/GraphQLSchemaGenerator.java @@ -36,6 +36,7 @@ package org.hl7.fhir.r5.utils; import org.hl7.fhir.exceptions.FHIRException; import org.hl7.fhir.r5.conformance.ProfileUtilities; +import org.hl7.fhir.r5.context.ContextUtilities; import org.hl7.fhir.r5.context.IWorkerContext; import org.hl7.fhir.r5.model.ElementDefinition; import org.hl7.fhir.r5.model.ElementDefinition.TypeRefComponent; @@ -96,7 +97,7 @@ public class GraphQLSchemaGenerator { Map pl = new HashMap<>(); Map tl = new HashMap<>(); Map existingTypeNames = new HashMap<>(); - for (StructureDefinition sd : context.allStructures()) { + for (StructureDefinition sd : new ContextUtilities(context).allStructures()) { if (sd.getKind() == StructureDefinitionKind.PRIMITIVETYPE && sd.getDerivation() == TypeDerivationRule.SPECIALIZATION) { pl.put(sd.getName(), sd); } diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/PublicationHacker.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/PublicationHacker.java index 2c796b6b2..dd5f5d1c4 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/PublicationHacker.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/PublicationHacker.java @@ -4,6 +4,7 @@ import org.hl7.fhir.r5.context.IWorkerContext; import org.hl7.fhir.r5.model.ServiceRequest; import org.hl7.fhir.r5.model.StringType; import org.hl7.fhir.utilities.Utilities; +import org.hl7.fhir.utilities.VersionUtilities; public class PublicationHacker { @@ -16,7 +17,7 @@ public class PublicationHacker { // ServiceRequest.code if (res.getValue().contains("LOINC is (preferred)[http://build.fhir.org/terminologies.html#preferred]")) { - res.setValue(res.getValue().replace("LOINC is (preferred)[http://build.fhir.org/terminologies.html#preferred]", "LOINC is [preferred]("+Utilities.pathURL(context.getSpecUrl(), "terminologies.html#preferred)"))); + res.setValue(res.getValue().replace("LOINC is (preferred)[http://build.fhir.org/terminologies.html#preferred]", "LOINC is [preferred]("+Utilities.pathURL(VersionUtilities.getSpecUrl(context.getVersion()), "terminologies.html#preferred)"))); } if (res.getValue().contains("[here](valueset-diagnostic-requests.html)")) { res.setValue(res.getValue().replace("[here](valueset-diagnostic-requests.html)", "here")); diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/structuremap/StructureMapUtilities.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/structuremap/StructureMapUtilities.java index 8f0c4f7d2..d6bb3ae45 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/structuremap/StructureMapUtilities.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/structuremap/StructureMapUtilities.java @@ -38,6 +38,7 @@ 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.ContextUtilities; import org.hl7.fhir.r5.context.IWorkerContext; import org.hl7.fhir.r5.context.IWorkerContext.ValidationResult; import org.hl7.fhir.r5.elementmodel.Element; @@ -1315,13 +1316,13 @@ public class StructureMapUtilities { private List findMatchingMaps(String value) { List res = new ArrayList(); if (value.contains("*")) { - for (StructureMap sm : worker.listTransforms()) { + for (StructureMap sm : worker.fetchResourcesByType(StructureMap.class)) { if (urlMatches(value, sm.getUrl())) { res.add(sm); } } } else { - StructureMap sm = worker.getTransform(value); + StructureMap sm = worker.fetchResource(StructureMap.class, value); if (sm != null) res.add(sm); } @@ -1861,7 +1862,7 @@ public class StructureMapUtilities { String su = conceptMapUrl; if (conceptMapUrl.equals("http://hl7.org/fhir/ConceptMap/special-oid2uri")) { - String uri = worker.oid2Uri(src.getCode()); + String uri = new ContextUtilities(worker).oid2Uri(src.getCode()); if (uri == null) uri = "urn:oid:" + src.getCode(); if ("uri".equals(fieldToReturn)) @@ -2408,7 +2409,7 @@ public class StructureMapUtilities { private TypeDetails getParam(VariablesForProfiling vars, StructureMapGroupRuleTargetParameterComponent parameter) throws DefinitionException { DataType p = parameter.getValue(); if (!(p instanceof IdType)) - return new TypeDetails(CollectionStatus.SINGLETON, ProfileUtilities.sdNs(p.fhirType(), worker.getOverrideVersionNs())); + return new TypeDetails(CollectionStatus.SINGLETON, ProfileUtilities.sdNs(p.fhirType(), null)); else { String n = ((IdType) p).asStringValue(); VariableForProfiling b = vars.get(VariableMode.INPUT, n); diff --git a/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/CDARoundTripTests.java b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/CDARoundTripTests.java index 83b97230b..77c13ad19 100644 --- a/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/CDARoundTripTests.java +++ b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/CDARoundTripTests.java @@ -5,6 +5,7 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.List; +import org.hl7.fhir.r5.context.ContextUtilities; import org.hl7.fhir.r5.context.SimpleWorkerContext; import org.hl7.fhir.r5.elementmodel.Element; import org.hl7.fhir.r5.elementmodel.Manager; @@ -38,10 +39,10 @@ public class CDARoundTripTests { context.loadFromFile(TestingUtilities.loadTestResourceStream("validator", "cda", "ed.xml"), "ed.xml", null); context.loadFromFile(TestingUtilities.loadTestResourceStream("validator", "cda", "st.xml"), "st.xml", null); context.loadFromFile(TestingUtilities.loadTestResourceStream("validator", "cda", "cda.xml"), "cda.xml", null); - for (StructureDefinition sd : context.getStructures()) { + for (StructureDefinition sd : context.fetchResourcesByType(StructureDefinition.class)) { if (!sd.hasSnapshot()) { // System.out.println("generate snapshot for " + sd.getUrl()); - context.generateSnapshot(sd, true); + new ContextUtilities(context).generateSnapshot(sd, true); } } } diff --git a/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/XmlParserTests.java b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/XmlParserTests.java index e8ba3ec28..a1415e9da 100644 --- a/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/XmlParserTests.java +++ b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/XmlParserTests.java @@ -3,6 +3,7 @@ package org.hl7.fhir.r5.test; import java.io.ByteArrayOutputStream; import java.io.IOException; +import org.hl7.fhir.r5.context.ContextUtilities; import org.hl7.fhir.r5.context.SimpleWorkerContext; import org.hl7.fhir.r5.elementmodel.Element; import org.hl7.fhir.r5.elementmodel.Manager; @@ -36,10 +37,10 @@ public class XmlParserTests { context.loadFromFile(TestingUtilities.loadTestResourceStream("validator", "cda", "ed.xml"), "ed.xml", null); context.loadFromFile(TestingUtilities.loadTestResourceStream("validator", "cda", "st.xml"), "st.xml", null); context.loadFromFile(TestingUtilities.loadTestResourceStream("validator", "cda", "cda.xml"), "cda.xml", null); - for (StructureDefinition sd : context.getStructures()) { + for (StructureDefinition sd : context.fetchResourcesByType(StructureDefinition.class)) { if (!sd.hasSnapshot()) { System.out.println("generate snapshot for " + sd.getUrl()); - context.generateSnapshot(sd, true); + new ContextUtilities(context).generateSnapshot(sd, true); } } } diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/VersionUtilities.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/VersionUtilities.java index 6beae5a03..8b04ba54a 100644 --- a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/VersionUtilities.java +++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/VersionUtilities.java @@ -564,5 +564,18 @@ public class VersionUtilities { return refVer.equals(v); } + public static String getSpecUrl(String v) { + switch (getMajMin(v)) { + case "1.0" : return "http://hl7.org/fhir/DSTU1"; + case "1.4" : return "http://hl7.org/fhir/DSTU2"; + case "3.0" : return "http://hl7.org/fhir/STU3"; + case "4.0" : return "http://hl7.org/fhir/R4"; + case "4.5" : return "http://build.fhir.org"; + case "5.0" : return "http://build.fhir.org"; + default: + return "http://hl7.org/fhir"; + } + } + } \ No newline at end of file diff --git a/org.hl7.fhir.utilities/src/main/resources/Messages.properties b/org.hl7.fhir.utilities/src/main/resources/Messages.properties index 75985cd76..1c1c1f4db 100644 --- a/org.hl7.fhir.utilities/src/main/resources/Messages.properties +++ b/org.hl7.fhir.utilities/src/main/resources/Messages.properties @@ -28,8 +28,8 @@ CodeSystem_CS_VS_IncludeDetails = CodeSystem {0} has an ''all system'' value set CodeSystem_CS_VS_Invalid = CodeSystem {0} has an ''all system'' value set of {1}, but doesn''t have a single include CODESYSTEM_CS_VS_EXP_MISMATCH = CodeSystem {0} has an ''all system'' value set of {1}, but it is an expansion with the wrong number of concepts (found {2}, expected {3}) CodeSystem_CS_VS_WrongSystem = CodeSystem {0} has an ''all system'' value set of {1}, but doesn''t have a matching system ({2}) -Extension_EXTP_Context_Wrong = The extension {0} is not allowed to be used at this point (allowed = {1}; this element is [{2}) -Extension_EXTM_Context_Wrong = The modifier extension {0} is not allowed to be used at this point (allowed = {1}; this element is [{2}) +Extension_EXTP_Context_Wrong = The extension {0} is not allowed to be used at this point (allowed = {1}; this element is {2}) +Extension_EXTM_Context_Wrong = The modifier extension {0} is not allowed to be used at this point (allowed = {1}; this element is {2}) Extension_EXT_Count_Mismatch = Extensions count mismatch: expected {0} but found {1} Extension_EXT_Count_NotFound = Extension count mismatch: unable to find extension: {0} Extension_EXT_Fixed_Banned = No extensions allowed, as the specified fixed value doesn''t contain any extensions diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/BaseValidator.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/BaseValidator.java index 8209fe33a..2b6ef9b6e 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/BaseValidator.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/BaseValidator.java @@ -36,6 +36,7 @@ import org.hl7.fhir.convertors.factory.VersionConvertorFactory_14_50; import org.hl7.fhir.convertors.factory.VersionConvertorFactory_30_50; import org.hl7.fhir.convertors.factory.VersionConvertorFactory_40_50; import org.hl7.fhir.exceptions.FHIRException; +import org.hl7.fhir.r5.context.ContextUtilities; import org.hl7.fhir.r5.context.IWorkerContext; import org.hl7.fhir.r5.elementmodel.Element; import org.hl7.fhir.r5.elementmodel.JsonParser; @@ -1035,7 +1036,7 @@ public class BaseValidator implements IValidationContextResourceLoader { return null; case Valid: StructureDefinition defn = xverDefn(url); - context.generateSnapshot(defn); + new ContextUtilities(context).generateSnapshot(defn); context.cacheResource(defn); return defn; default: @@ -1061,7 +1062,7 @@ public class BaseValidator implements IValidationContextResourceLoader { break; case Valid: StructureDefinition ex = xverDefn(url); - context.generateSnapshot(ex); + new ContextUtilities(context).generateSnapshot(ex); context.cacheResource(ex); return ex; default: diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/Scanner.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/Scanner.java index dddf0d6de..4071eb61b 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/Scanner.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/Scanner.java @@ -2,6 +2,7 @@ package org.hl7.fhir.validation; import lombok.Getter; import org.hl7.fhir.exceptions.FHIRException; +import org.hl7.fhir.r5.context.ContextUtilities; import org.hl7.fhir.r5.context.SimpleWorkerContext; import org.hl7.fhir.r5.elementmodel.Element; import org.hl7.fhir.r5.model.ImplementationGuide; @@ -62,7 +63,7 @@ public class Scanner { List refs = new ArrayList<>(); ValidatorUtils.parseSources(sources, refs, getContext()); - List res = new ArrayList(); + List res = new ArrayList<>(); for (String ref : refs) { Content cnt = getIgLoader().loadContent(ref, "validate", false); @@ -94,7 +95,7 @@ public class Scanner { } } Set done = new HashSet<>(); - for (StructureDefinition sd : getContext().allStructures()) { + for (StructureDefinition sd : new ContextUtilities(getContext()).allStructures()) { if (!done.contains(sd.getUrl())) { done.add(sd.getUrl()); if (sd.getUrl().startsWith(canonical) && rt.equals(sd.getType())) { 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 76fbf57ea..7cdfea825 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 @@ -12,10 +12,12 @@ import org.hl7.fhir.convertors.txClient.TerminologyClientFactory; import org.hl7.fhir.exceptions.DefinitionException; import org.hl7.fhir.exceptions.FHIRException; import org.hl7.fhir.r5.conformance.ProfileUtilities; +import org.hl7.fhir.r5.context.ContextUtilities; import org.hl7.fhir.r5.context.IWorkerContext; -import org.hl7.fhir.r5.context.IWorkerContext.ICanonicalResourceLocator; -import org.hl7.fhir.r5.context.IWorkerContext.IPackageLoadingTracker; import org.hl7.fhir.r5.context.IWorkerContext.PackageVersion; +import org.hl7.fhir.r5.context.IWorkerContextManager; +import org.hl7.fhir.r5.context.IWorkerContextManager.ICanonicalResourceLocator; +import org.hl7.fhir.r5.context.IWorkerContextManager.IPackageLoadingTracker; import org.hl7.fhir.r5.context.SimpleWorkerContext; import org.hl7.fhir.r5.context.SystemOutLoggingService; import org.hl7.fhir.r5.elementmodel.Element; @@ -135,7 +137,7 @@ POSSIBILITY OF SUCH DAMAGE. * @author Grahame Grieve */ @Accessors(chain = true) -public class ValidationEngine implements IValidatorResourceFetcher, IValidationPolicyAdvisor, IPackageInstaller, IPackageLoadingTracker { +public class ValidationEngine implements IValidatorResourceFetcher, IValidationPolicyAdvisor, IPackageInstaller, IWorkerContextManager.IPackageLoadingTracker { @Getter @Setter private SimpleWorkerContext context; @Getter @Setter private Map binaries = new HashMap<>(); @@ -151,7 +153,7 @@ public class ValidationEngine implements IValidatorResourceFetcher, IValidationP @Getter @Setter private boolean debug = false; @Getter @Setter private IValidatorResourceFetcher fetcher; @Getter @Setter private IValidationPolicyAdvisor policyAdvisor; - @Getter @Setter private ICanonicalResourceLocator locator; + @Getter @Setter private IWorkerContextManager.ICanonicalResourceLocator locator; @Getter @Setter private boolean assumeValidRestReferences; @Getter @Setter private boolean noExtensibleBindingMessages; @Getter @Setter private boolean noUnicodeBiDiControlChars; @@ -497,7 +499,7 @@ public class ValidationEngine implements IValidatorResourceFetcher, IValidationP } public StructureMap compile(String mapUri) throws FHIRException, IOException { - StructureMap map = context.getTransform(mapUri); + StructureMap map = context.fetchResource(StructureMap.class, mapUri); return map; } @@ -505,7 +507,7 @@ public class ValidationEngine implements IValidatorResourceFetcher, IValidationP List outputs = new ArrayList<>(); StructureMapUtilities scu = new StructureMapUtilities(context, new TransformSupportServices(outputs, mapLog, context)); org.hl7.fhir.r5.elementmodel.Element src = Manager.parseSingle(context, new ByteArrayInputStream(source), cntType); - StructureMap map = context.getTransform(mapUri); + StructureMap map = context.fetchResource(StructureMap.class, mapUri); if (map == null) throw new Error("Unable to find map " + mapUri + " (Known Maps = " + context.listMapUrls() + ")"); org.hl7.fhir.r5.elementmodel.Element resource = getTargetResourceFromStructureMap(map); scu.transform(null, src, map, resource); @@ -524,7 +526,7 @@ public class ValidationEngine implements IValidatorResourceFetcher, IValidationP if (targetTypeUrl == null) throw new FHIRException("Unable to determine resource URL for target type"); StructureDefinition structureDefinition = null; - for (StructureDefinition sd : this.context.getStructures()) { + for (StructureDefinition sd : this.context.fetchResourcesByType(StructureDefinition.class)) { if (sd.getUrl().equalsIgnoreCase(targetTypeUrl)) { structureDefinition = sd; break; @@ -639,7 +641,7 @@ public class ValidationEngine implements IValidatorResourceFetcher, IValidationP } public void prepare() { - for (StructureDefinition sd : context.allStructures()) { + for (StructureDefinition sd : new ContextUtilities(context).allStructures()) { try { makeSnapshot(sd); } catch (Exception e) { @@ -757,7 +759,7 @@ public class ValidationEngine implements IValidatorResourceFetcher, IValidationP String url = getMapId(type, targetVer); List outputs = new ArrayList(); StructureMapUtilities scu = new StructureMapUtilities(context, new TransformSupportServices(outputs, mapLog, context)); - StructureMap map = context.getTransform(url); + StructureMap map = context.fetchResource(StructureMap.class, url); if (map == null) throw new Error("Unable to find map " + url + " (Known Maps = " + context.listMapUrls() + ")"); org.hl7.fhir.r5.elementmodel.Element resource = getTargetResourceFromStructureMap(map); diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/services/StandAloneValidatorFetcher.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/services/StandAloneValidatorFetcher.java index c29b100a4..2cd209e08 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/services/StandAloneValidatorFetcher.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/services/StandAloneValidatorFetcher.java @@ -4,7 +4,8 @@ import com.google.gson.JsonObject; import org.hl7.fhir.convertors.txClient.TerminologyClientFactory; import org.hl7.fhir.exceptions.FHIRException; import org.hl7.fhir.r5.context.IWorkerContext; -import org.hl7.fhir.r5.context.IWorkerContext.ICanonicalResourceLocator; +import org.hl7.fhir.r5.context.IWorkerContextManager; +import org.hl7.fhir.r5.context.IWorkerContextManager.ICanonicalResourceLocator; import org.hl7.fhir.r5.elementmodel.Element; import org.hl7.fhir.r5.model.CanonicalResource; import org.hl7.fhir.r5.model.ElementDefinition; @@ -36,7 +37,7 @@ import java.util.List; import java.util.Locale; import java.util.Map; -public class StandAloneValidatorFetcher implements IValidatorResourceFetcher, IValidationPolicyAdvisor, ICanonicalResourceLocator { +public class StandAloneValidatorFetcher implements IValidatorResourceFetcher, IValidationPolicyAdvisor, IWorkerContextManager.ICanonicalResourceLocator { List mappingsUris = new ArrayList<>(); private FilesystemPackageCacheManager pcm; diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/services/ValidationService.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/services/ValidationService.java index 0faa41b41..a27c64f99 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/services/ValidationService.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/services/ValidationService.java @@ -6,6 +6,7 @@ import org.hl7.fhir.r5.context.SystemOutLoggingService; import org.hl7.fhir.r5.context.TerminologyCache; import org.hl7.fhir.r5.conformance.ProfileUtilities; import org.hl7.fhir.r5.conformance.R5ExtensionsLoader; +import org.hl7.fhir.r5.context.ContextUtilities; import org.hl7.fhir.r5.context.IWorkerContext.PackageVersion; import org.hl7.fhir.r5.context.SimpleWorkerContext.PackageResourceLoader; import org.hl7.fhir.r5.elementmodel.Manager; @@ -242,13 +243,14 @@ public class ValidationService { if (cliContext.getMap() == null) throw new Exception("Must provide a map when doing a transform"); try { - List structures = validator.getContext().allStructures(); + ContextUtilities cu = new ContextUtilities(validator.getContext()); + List structures = cu.allStructures(); for (StructureDefinition sd : structures) { if (!sd.hasSnapshot()) { if (sd.getKind() != null && sd.getKind() == StructureDefinitionKind.LOGICAL) { - validator.getContext().generateSnapshot(sd, true); + cu.generateSnapshot(sd, true); } else { - validator.getContext().generateSnapshot(sd, false); + cu.generateSnapshot(sd, false); } } } @@ -277,13 +279,14 @@ public class ValidationService { if (cliContext.getOutput() == null) throw new Exception("Must provide an output name when compiling a transform"); try { - List structures = validator.getContext().allStructures(); + ContextUtilities cu = new ContextUtilities(validator.getContext()); + List structures = cu.allStructures(); for (StructureDefinition sd : structures) { if (!sd.hasSnapshot()) { if (sd.getKind() != null && sd.getKind() == StructureDefinitionKind.LOGICAL) { - validator.getContext().generateSnapshot(sd, true); + cu.generateSnapshot(sd, true); } else { - validator.getContext().generateSnapshot(sd, false); + cu.generateSnapshot(sd, false); } } } diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/InstanceValidator.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/InstanceValidator.java index 27b1d119e..914bda54e 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/InstanceValidator.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/InstanceValidator.java @@ -60,6 +60,7 @@ import org.hl7.fhir.exceptions.FHIRException; import org.hl7.fhir.exceptions.PathEngineException; import org.hl7.fhir.exceptions.TerminologyServiceException; import org.hl7.fhir.r5.conformance.ProfileUtilities; +import org.hl7.fhir.r5.context.ContextUtilities; import org.hl7.fhir.r5.context.IWorkerContext; import org.hl7.fhir.r5.context.IWorkerContext.ValidationResult; import org.hl7.fhir.r5.elementmodel.Element; @@ -1483,7 +1484,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat res.getCodingFirstRep().setCode(list.get(0).primitiveValue()); } else if ("Coding.system[fmt:OID]".equals(m)) { String oid = list.get(0).primitiveValue(); - String url = context.oid2Uri(oid); + String url = new ContextUtilities(context).oid2Uri(oid); if (url != null) { res.getCodingFirstRep().setSystem(url); } else { @@ -1522,7 +1523,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat res.setCode(list.get(0).primitiveValue()); } else if ("Coding.system[fmt:OID]".equals(m)) { String oid = list.get(0).primitiveValue(); - String url = context.oid2Uri(oid); + String url = new ContextUtilities(context).oid2Uri(oid); if (url != null) { res.setSystem(url); } else { @@ -5939,7 +5940,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat } public void checkAllInvariants() { - for (StructureDefinition sd : context.allStructures()) { + for (StructureDefinition sd : new ContextUtilities(context).allStructures()) { if (sd.getDerivation() == TypeDerivationRule.SPECIALIZATION) { for (ElementDefinition ed : sd.getSnapshot().getElement()) { for (ElementDefinitionConstraintComponent inv : ed.getConstraint()) { diff --git a/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/r5/test/StructureMappingTests.java b/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/r5/test/StructureMappingTests.java index 82f2235eb..fe6ad69c3 100644 --- a/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/r5/test/StructureMappingTests.java +++ b/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/r5/test/StructureMappingTests.java @@ -10,6 +10,7 @@ import java.util.stream.Stream; import javax.xml.parsers.ParserConfigurationException; +import org.hl7.fhir.r5.context.ContextUtilities; import org.hl7.fhir.r5.context.SimpleWorkerContext; import org.hl7.fhir.r5.elementmodel.Manager.FhirFormat; import org.hl7.fhir.r5.formats.IParser; @@ -64,10 +65,10 @@ public class StructureMappingTests { context.loadFromFile(TestingUtilities.loadTestResourceStream("validator", "cda", "ed.xml"), "ed.xml", null); context.loadFromFile(TestingUtilities.loadTestResourceStream("validator", "cda", "st.xml"), "st.xml", null); context.loadFromFile(TestingUtilities.loadTestResourceStream("validator", "cda", "cda.xml"), "cda.xml", null); - for (StructureDefinition sd : context.getStructures()) { + for (StructureDefinition sd : context.fetchResourcesByType(StructureDefinition.class)) { if (!sd.hasSnapshot()) { System.out.println("generate snapshot for " + sd.getUrl()); - context.generateSnapshot(sd, true); + new ContextUtilities(context).generateSnapshot(sd, true); } } if (context.getValidatorFactory() == null) { diff --git a/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/validation/tests/ValidationTests.java b/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/validation/tests/ValidationTests.java index 24ec6b3f1..e4e5960c9 100644 --- a/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/validation/tests/ValidationTests.java +++ b/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/validation/tests/ValidationTests.java @@ -33,6 +33,7 @@ import org.hl7.fhir.exceptions.FHIRException; import org.hl7.fhir.exceptions.FHIRFormatError; import org.hl7.fhir.exceptions.PathEngineException; import org.hl7.fhir.r5.conformance.ProfileUtilities; +import org.hl7.fhir.r5.context.ContextUtilities; import org.hl7.fhir.r5.elementmodel.Element; import org.hl7.fhir.r5.elementmodel.Manager; import org.hl7.fhir.r5.elementmodel.Manager.FhirFormat; @@ -325,7 +326,7 @@ public class ValidationTests implements IEvaluationContext, IValidatorResourceFe String contents = TestingUtilities.loadTestResource("validator", filename); CanonicalResource mr = (CanonicalResource) loadResource(filename, contents); if (mr instanceof StructureDefinition) { - val.getContext().generateSnapshot((StructureDefinition) mr, true); + new ContextUtilities(val.getContext()).generateSnapshot((StructureDefinition) mr, true); } val.getContext().cacheResource(mr); } diff --git a/pom.xml b/pom.xml index 497b86acf..2f382b269 100644 --- a/pom.xml +++ b/pom.xml @@ -19,7 +19,7 @@ 5.4.0 - 1.1.115 + 1.1.116-SNAPSHOT 5.7.1 1.8.2 3.0.0-M5