"); file.println(outcome); for (String s : headers) 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 0b5803bec..7f90e56c1 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 @@ -4,34 +4,34 @@ import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; -/* - Copyright (c) 2011+, HL7, Inc. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - * Neither the name of HL7 nor the names of its contributors may be used to - endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. - - */ +/* + Copyright (c) 2011+, HL7, Inc. + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name of HL7 nor the names of its contributors may be used to + endorse or promote products derived from this software without specific + prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + */ @@ -44,7 +44,6 @@ import org.fhir.ucum.UcumService; import org.hl7.fhir.exceptions.DefinitionException; import org.hl7.fhir.exceptions.FHIRException; import org.hl7.fhir.exceptions.TerminologyServiceException; -import org.hl7.fhir.r5.context.IWorkerContext.CodingValidationRequest; import org.hl7.fhir.r5.context.TerminologyCache.CacheToken; import org.hl7.fhir.r5.formats.IParser; import org.hl7.fhir.r5.formats.ParserType; @@ -64,7 +63,7 @@ import org.hl7.fhir.r5.model.ValueSet; import org.hl7.fhir.r5.model.ValueSet.ConceptSetComponent; import org.hl7.fhir.r5.terminologies.ValueSetExpander.TerminologyServiceErrorClass; import org.hl7.fhir.r5.terminologies.ValueSetExpander.ValueSetExpansionOutcome; -import org.hl7.fhir.r5.utils.IResourceValidator; +import org.hl7.fhir.r5.utils.validation.IResourceValidator; import org.hl7.fhir.utilities.TimeTracker; import org.hl7.fhir.utilities.TranslationServices; import org.hl7.fhir.utilities.npm.BasePackageCacheManager; @@ -247,10 +246,10 @@ public interface IWorkerContext { * Get the versions of the definitions loaded in context * @return */ - public String getVersion(); - - /** - * return the link to the base of the specification for the loaded version e.g. http://hl7.org/fhir/R4 + public String getVersion(); + + /** + * return the link to the base of the specification for the loaded version e.g. http://hl7.org/fhir/R4 */ public String getSpecUrl(); 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 7e132e33b..13ee2c3a1 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 @@ -54,9 +54,7 @@ import org.hl7.fhir.exceptions.FHIRFormatError; import org.hl7.fhir.r5.conformance.ProfileUtilities; import org.hl7.fhir.r5.conformance.ProfileUtilities.ProfileKnowledgeProvider; import org.hl7.fhir.r5.context.CanonicalResourceManager.CanonicalResourceProxy; -import org.hl7.fhir.r5.context.IWorkerContext.PackageVersion; import org.hl7.fhir.r5.context.IWorkerContext.ILoggingService.LogCategory; -import org.hl7.fhir.r5.context.SimpleWorkerContext.PackageResourceLoader; import org.hl7.fhir.r5.formats.IParser; import org.hl7.fhir.r5.formats.JsonParser; import org.hl7.fhir.r5.formats.ParserType; @@ -76,7 +74,7 @@ import org.hl7.fhir.r5.model.StructureMap; import org.hl7.fhir.r5.model.StructureMap.StructureMapModelMode; import org.hl7.fhir.r5.model.StructureMap.StructureMapStructureComponent; import org.hl7.fhir.r5.terminologies.TerminologyClient; -import org.hl7.fhir.r5.utils.IResourceValidator; +import org.hl7.fhir.r5.utils.validation.IResourceValidator; import org.hl7.fhir.r5.utils.XVerExtensionManager; import org.hl7.fhir.utilities.CSFileInputStream; import org.hl7.fhir.utilities.TextFile; @@ -85,15 +83,12 @@ import org.hl7.fhir.utilities.Utilities; import org.hl7.fhir.utilities.VersionUtilities; import org.hl7.fhir.utilities.i18n.I18nConstants; import org.hl7.fhir.utilities.npm.BasePackageCacheManager; -import org.hl7.fhir.utilities.npm.FilesystemPackageCacheManager; import org.hl7.fhir.utilities.npm.NpmPackage; import org.hl7.fhir.utilities.npm.NpmPackage.PackageResourceInformation; import org.hl7.fhir.utilities.validation.ValidationMessage; import org.hl7.fhir.utilities.validation.ValidationMessage.IssueType; import org.hl7.fhir.utilities.validation.ValidationMessage.Source; -import com.google.gson.JsonObject; - import ca.uhn.fhir.parser.DataFormatException; /* diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/structuremap/FFHIRPathHostServices.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/structuremap/FFHIRPathHostServices.java index 3748e2235..c5024dc22 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/structuremap/FFHIRPathHostServices.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/structuremap/FFHIRPathHostServices.java @@ -9,7 +9,7 @@ import org.hl7.fhir.r5.model.Resource; import org.hl7.fhir.r5.model.TypeDetails; import org.hl7.fhir.r5.model.ValueSet; import org.hl7.fhir.r5.utils.FHIRPathEngine; -import org.hl7.fhir.r5.utils.IResourceValidator; +import org.hl7.fhir.r5.utils.validation.IResourceValidator; import org.hl7.fhir.utilities.validation.ValidationMessage; import java.util.ArrayList; diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/validation/BundleValidationRule.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/validation/BundleValidationRule.java new file mode 100644 index 000000000..370f67c4c --- /dev/null +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/validation/BundleValidationRule.java @@ -0,0 +1,29 @@ +package org.hl7.fhir.r5.utils.validation; + +public class BundleValidationRule { + private String rule; + private String profile; + private boolean checked; + + public BundleValidationRule(String rule, String profile) { + super(); + this.rule = rule; + this.profile = profile; + } + + public String getRule() { + return rule; + } + + public String getProfile() { + return profile; + } + + public boolean isChecked() { + return checked; + } + + public void setChecked(boolean checked) { + this.checked = checked; + } +} diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/IResourceValidator.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/validation/IResourceValidator.java similarity index 60% rename from org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/IResourceValidator.java rename to org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/validation/IResourceValidator.java index e1c24bf02..2ce6aca70 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/IResourceValidator.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/validation/IResourceValidator.java @@ -1,4 +1,4 @@ -package org.hl7.fhir.r5.utils; +package org.hl7.fhir.r5.utils.validation; /* Copyright (c) 2011+, HL7, Inc. @@ -30,26 +30,18 @@ package org.hl7.fhir.r5.utils; */ +import com.google.gson.JsonObject; +import org.hl7.fhir.exceptions.FHIRException; +import org.hl7.fhir.r5.elementmodel.Manager.FhirFormat; +import org.hl7.fhir.r5.model.StructureDefinition; +import org.hl7.fhir.r5.utils.validation.constants.BestPracticeWarningLevel; +import org.hl7.fhir.r5.utils.validation.constants.CheckDisplayOption; +import org.hl7.fhir.r5.utils.validation.constants.IdStatus; +import org.hl7.fhir.utilities.validation.ValidationMessage; import java.io.IOException; import java.io.InputStream; -import java.net.MalformedURLException; -import java.net.URISyntaxException; import java.util.List; -import java.util.Locale; - -import org.hl7.fhir.exceptions.DefinitionException; -import org.hl7.fhir.exceptions.FHIRException; -import org.hl7.fhir.exceptions.FHIRFormatError; -import org.hl7.fhir.r5.elementmodel.Element; -import org.hl7.fhir.r5.elementmodel.Manager.FhirFormat; -import org.hl7.fhir.r5.model.CanonicalResource; -import org.hl7.fhir.r5.model.StructureDefinition; -import org.hl7.fhir.r5.utils.IResourceValidator.BundleValidationRule; -import org.hl7.fhir.utilities.Utilities; -import org.hl7.fhir.utilities.validation.ValidationMessage; - -import com.google.gson.JsonObject; /** * Interface to the instance validator. This takes a resource, in one of many forms, and @@ -60,124 +52,21 @@ import com.google.gson.JsonObject; */ public interface IResourceValidator { - public class BundleValidationRule { - private String rule; - private String profile; - private boolean checked; - - public BundleValidationRule(String rule, String profile) { - super(); - this.rule = rule; - this.profile = profile; - } - public String getRule() { - return rule; - } - public String getProfile() { - return profile; - } - public boolean isChecked() { - return checked; - } - public void setChecked(boolean checked) { - this.checked = checked; - } - } - - public enum ReferenceValidationPolicy { - IGNORE, CHECK_TYPE_IF_EXISTS, CHECK_EXISTS, CHECK_EXISTS_AND_TYPE, CHECK_VALID; - - public boolean checkExists() { - return this == CHECK_EXISTS_AND_TYPE || this == CHECK_EXISTS || this == CHECK_VALID || this == CHECK_TYPE_IF_EXISTS; - } - - public boolean checkType() { - return this == CHECK_TYPE_IF_EXISTS || this == CHECK_EXISTS_AND_TYPE || this == CHECK_VALID; - } - - public boolean checkValid() { - return this == CHECK_VALID; - } - } - - public interface IValidationProfileUsageTracker { - void recordProfileUsage(StructureDefinition profile, Object appContext, Element element); - } - - - public interface IValidatorResourceFetcher { - - Element fetch(IResourceValidator validator, Object appContext, String url) throws FHIRFormatError, DefinitionException, FHIRException, IOException; - ReferenceValidationPolicy validationPolicy(IResourceValidator validator, Object appContext, String path, String url); - boolean resolveURL(IResourceValidator validator, Object appContext, String path, String url, String type) throws IOException, FHIRException; - - byte[] fetchRaw(IResourceValidator validator, String url) throws MalformedURLException, IOException; // for attachment checking - - IValidatorResourceFetcher setLocale(Locale locale); - - - /** - * this is used when the validator encounters a reference to a structure definition, value set or code system at some random URL reference - * while validating. - * - * Added in v5.2.2. return null to leave functionality as it was before then. - * - * @param primitiveValue - * @return an R5 version of the resource - * @throws URISyntaxException - */ - CanonicalResource fetchCanonicalResource(IResourceValidator validator, String url) throws URISyntaxException; - - /** - * Whether to try calling fetchCanonicalResource for this reference (not whether it will succeed - just throw an exception from fetchCanonicalResource if it doesn't resolve. This is a policy thing. - * - * Added in v5.2.2. return false to leave functionality as it was before then. - * - * @param url - * @return - */ - boolean fetchesCanonicalResource(IResourceValidator validator, String url); - } - - public enum BestPracticeWarningLevel { - Ignore, - Hint, - Warning, - Error - } - - public enum CheckDisplayOption { - Ignore, - Check, - CheckCaseAndSpace, - CheckCase, - CheckSpace - } - - enum IdStatus { - OPTIONAL, REQUIRED, PROHIBITED - } - /** * how much to check displays for coded elements - * @return */ CheckDisplayOption getCheckDisplay(); void setCheckDisplay(CheckDisplayOption checkDisplay); /** * whether the resource must have an id or not (depends on context) - * - * @return */ - IdStatus getResourceIdRule(); void setResourceIdRule(IdStatus resourceIdRule); /** * whether the validator should enforce best practice guidelines * as defined by various HL7 committees - * */ BestPracticeWarningLevel getBestPracticeWarningLevel(); IResourceValidator setBestPracticeWarningLevel(BestPracticeWarningLevel value); @@ -185,48 +74,46 @@ public interface IResourceValidator { IValidatorResourceFetcher getFetcher(); IResourceValidator setFetcher(IValidatorResourceFetcher value); + IValidationPolicyAdvisor getPolicyAdvisor(); + IResourceValidator setPolicyAdvisor(IValidationPolicyAdvisor advisor); + IValidationProfileUsageTracker getTracker(); IResourceValidator setTracker(IValidationProfileUsageTracker value); boolean isNoBindingMsgSuppressed(); IResourceValidator setNoBindingMsgSuppressed(boolean noBindingMsgSuppressed); - public boolean isNoInvariantChecks(); - public IResourceValidator setNoInvariantChecks(boolean value) ; + boolean isNoInvariantChecks(); + IResourceValidator setNoInvariantChecks(boolean value) ; - public boolean isWantInvariantInMessage(); - public IResourceValidator setWantInvariantInMessage(boolean wantInvariantInMessage); + boolean isWantInvariantInMessage(); + IResourceValidator setWantInvariantInMessage(boolean wantInvariantInMessage); - public boolean isNoTerminologyChecks(); - public IResourceValidator setNoTerminologyChecks(boolean noTerminologyChecks); + boolean isNoTerminologyChecks(); + IResourceValidator setNoTerminologyChecks(boolean noTerminologyChecks); - public boolean isNoExtensibleWarnings(); - public IResourceValidator setNoExtensibleWarnings(boolean noExtensibleWarnings); + boolean isNoExtensibleWarnings(); + IResourceValidator setNoExtensibleWarnings(boolean noExtensibleWarnings); - public boolean isNoUnicodeBiDiControlChars(); - public void setNoUnicodeBiDiControlChars(boolean noUnicodeBiDiControlChars); + boolean isNoUnicodeBiDiControlChars(); + void setNoUnicodeBiDiControlChars(boolean noUnicodeBiDiControlChars); /** * Whether being unable to resolve a profile in found in Resource.meta.profile or ElementDefinition.type.profile or targetProfile is an error or just a warning - * @return */ - public boolean isErrorForUnknownProfiles(); - public void setErrorForUnknownProfiles(boolean errorForUnknownProfiles); + boolean isErrorForUnknownProfiles(); + void setErrorForUnknownProfiles(boolean errorForUnknownProfiles); - public boolean isShowMessagesFromReferences(); - public void setShowMessagesFromReferences(boolean value); + boolean isShowMessagesFromReferences(); + void setShowMessagesFromReferences(boolean value); /** * this is used internally in the publishing stack to ensure that everything is water tight, but * this check is not necessary or appropriate at run time when the validator is hosted in HAPI * @return */ - public boolean isWantCheckSnapshotUnchanged(); - public void setWantCheckSnapshotUnchanged(boolean wantCheckSnapshotUnchanged); - - //FIXME: don't need that, gets never used? -// public String getValidationLanguage(); -// public void setValidationLanguage(String value); + boolean isWantCheckSnapshotUnchanged(); + void setWantCheckSnapshotUnchanged(boolean wantCheckSnapshotUnchanged); /** * It's common to see references such as Patient/234234 - these usually mean a reference to a Patient resource. @@ -235,27 +122,28 @@ public interface IResourceValidator { * * @return */ - public boolean isAssumeValidRestReferences(); - public void setAssumeValidRestReferences(boolean value); + boolean isAssumeValidRestReferences(); + void setAssumeValidRestReferences(boolean value); /** * if this is true, the validator will accept extensions and references to example.org and acme.com as * valid, on the basis that they are understood to be references to content that could exist in priniple but can't in practice */ - public boolean isAllowExamples(); - public void setAllowExamples(boolean value) ; + boolean isAllowExamples(); + void setAllowExamples(boolean value) ; - public boolean isNoCheckAggregation(); - public void setNoCheckAggregation(boolean value); + boolean isNoCheckAggregation(); + void setNoCheckAggregation(boolean value); + /** * CrumbTrail - whether the validator creates hints to * @return */ - public boolean isCrumbTrails(); - public void setCrumbTrails(boolean crumbTrails); + boolean isCrumbTrails(); + void setCrumbTrails(boolean crumbTrails); - public boolean isValidateValueSetCodesOnTxServer(); - public void setValidateValueSetCodesOnTxServer(boolean value); + boolean isValidateValueSetCodesOnTxServer(); + void setValidateValueSetCodesOnTxServer(boolean value); /** * Bundle validation rules allow for requesting particular entries in a bundle get validated against particular profiles @@ -264,7 +152,7 @@ public interface IResourceValidator { * * @return */ - public ListgetBundleValidationRules(); + List getBundleValidationRules(); /** * Validate suite diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/validation/IValidationPolicyAdvisor.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/validation/IValidationPolicyAdvisor.java new file mode 100644 index 000000000..58a7f62bf --- /dev/null +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/validation/IValidationPolicyAdvisor.java @@ -0,0 +1,41 @@ +package org.hl7.fhir.r5.utils.validation; + +import org.hl7.fhir.r5.elementmodel.Element; +import org.hl7.fhir.r5.utils.validation.constants.ContainedReferenceValidationPolicy; +import org.hl7.fhir.r5.utils.validation.constants.ReferenceValidationPolicy; + +public interface IValidationPolicyAdvisor { + + /** + * + * @param validator + * @param appContext What was originally provided from the app for it's context + * @param path Path that led us to this resource. + * @param url Url of the profile the container resource is being validated against. + * @return {@link ReferenceValidationPolicy} + */ + ReferenceValidationPolicy policyForReference(IResourceValidator validator, + Object appContext, + String path, + String url); + + /** + * //TODO pass through the actual containing Element as opposed to the type, id + * @param validator + * @param appContext What was originally provided from the app for it's context + * @param containerType Type of the resources that contains the resource being validated + * @param containerId Id of the resources that contains the resource being validated + * @param containingResourceType Type of the resource that will be validated (BUNDLE_ENTRY, BUNDLE_OUTCOME, CONTAINED_RESOURCE, PARAMETER) + * @param path Path that led us to this resource. + * @param url Url of the profile the container resource is being validated against. + * @return {@link ReferenceValidationPolicy} + */ + ContainedReferenceValidationPolicy policyForContained(IResourceValidator validator, + Object appContext, + String containerType, + String containerId, + Element.SpecialElement containingResourceType, + String path, + String url); + +} \ No newline at end of file diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/validation/IValidationProfileUsageTracker.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/validation/IValidationProfileUsageTracker.java new file mode 100644 index 000000000..b0ef7bfd7 --- /dev/null +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/validation/IValidationProfileUsageTracker.java @@ -0,0 +1,8 @@ +package org.hl7.fhir.r5.utils.validation; + +import org.hl7.fhir.r5.elementmodel.Element; +import org.hl7.fhir.r5.model.StructureDefinition; + +public interface IValidationProfileUsageTracker { + void recordProfileUsage(StructureDefinition profile, Object appContext, Element element); +} diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/validation/IValidatorResourceFetcher.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/validation/IValidatorResourceFetcher.java new file mode 100644 index 000000000..26378c3c8 --- /dev/null +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/validation/IValidatorResourceFetcher.java @@ -0,0 +1,41 @@ +package org.hl7.fhir.r5.utils.validation; + +import org.hl7.fhir.exceptions.FHIRException; +import org.hl7.fhir.r5.elementmodel.Element; +import org.hl7.fhir.r5.model.CanonicalResource; + +import java.io.IOException; +import java.net.URISyntaxException; +import java.util.Locale; + +public interface IValidatorResourceFetcher { + + Element fetch(IResourceValidator validator, Object appContext, String url) throws FHIRException, IOException; + + boolean resolveURL(IResourceValidator validator, Object appContext, String path, String url, String type) throws IOException, FHIRException; + + byte[] fetchRaw(IResourceValidator validator, String url) throws IOException; // for attachment checking + + IValidatorResourceFetcher setLocale(Locale locale); + + /** + * this is used when the validator encounters a reference to a structure definition, value set or code system at some random URL reference + * while validating. + * + * Added in v5.2.2. return null to leave functionality as it was before then. + * + * @return an R5 version of the resource + * @throws URISyntaxException + */ + CanonicalResource fetchCanonicalResource(IResourceValidator validator, String url) throws URISyntaxException; + + /** + * Whether to try calling fetchCanonicalResource for this reference (not whether it will succeed - just throw an exception from fetchCanonicalResource if it doesn't resolve. This is a policy thing. + *
+ * Added in v5.2.2. return false to leave functionality as it was before then. + * + * @param url + * @return + */ + boolean fetchesCanonicalResource(IResourceValidator validator, String url); +} diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/validation/constants/BestPracticeWarningLevel.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/validation/constants/BestPracticeWarningLevel.java new file mode 100644 index 000000000..441fadea8 --- /dev/null +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/validation/constants/BestPracticeWarningLevel.java @@ -0,0 +1,8 @@ +package org.hl7.fhir.r5.utils.validation.constants; + +public enum BestPracticeWarningLevel { + Ignore, + Hint, + Warning, + Error +} diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/validation/constants/CheckDisplayOption.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/validation/constants/CheckDisplayOption.java new file mode 100644 index 000000000..9a080366a --- /dev/null +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/validation/constants/CheckDisplayOption.java @@ -0,0 +1,9 @@ +package org.hl7.fhir.r5.utils.validation.constants; + +public enum CheckDisplayOption { + Ignore, + Check, + CheckCaseAndSpace, + CheckCase, + CheckSpace +} diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/validation/constants/ContainedReferenceValidationPolicy.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/validation/constants/ContainedReferenceValidationPolicy.java new file mode 100644 index 000000000..8361ebdde --- /dev/null +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/validation/constants/ContainedReferenceValidationPolicy.java @@ -0,0 +1,19 @@ +package org.hl7.fhir.r5.utils.validation.constants; + +public enum ContainedReferenceValidationPolicy { + IGNORE, + CHECK_TYPE, + CHECK_VALID; + + public boolean ignore() { + return this == IGNORE; + } + + public boolean checkType() { + return this == CHECK_TYPE || this == CHECK_VALID; + } + + public boolean checkValid() { + return this == CHECK_VALID; + } +} diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/validation/constants/IdStatus.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/validation/constants/IdStatus.java new file mode 100644 index 000000000..84004111d --- /dev/null +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/validation/constants/IdStatus.java @@ -0,0 +1,7 @@ +package org.hl7.fhir.r5.utils.validation.constants; + +public enum IdStatus { + OPTIONAL, + REQUIRED, + PROHIBITED +} diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/validation/constants/ReferenceValidationPolicy.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/validation/constants/ReferenceValidationPolicy.java new file mode 100644 index 000000000..616fb10eb --- /dev/null +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/validation/constants/ReferenceValidationPolicy.java @@ -0,0 +1,25 @@ +package org.hl7.fhir.r5.utils.validation.constants; + +public enum ReferenceValidationPolicy { + IGNORE, + CHECK_TYPE_IF_EXISTS, + CHECK_EXISTS, + CHECK_EXISTS_AND_TYPE, + CHECK_VALID; + + public boolean ignore() { + return this == IGNORE; + } + + public boolean checkExists() { + return this == CHECK_EXISTS_AND_TYPE || this == CHECK_EXISTS || this == CHECK_VALID || this == CHECK_TYPE_IF_EXISTS; + } + + public boolean checkType() { + return this == CHECK_TYPE_IF_EXISTS || this == CHECK_EXISTS_AND_TYPE || this == CHECK_VALID; + } + + public boolean checkValid() { + return this == CHECK_VALID; + } +} diff --git a/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/ParsingTests.java b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/ParsingTests.java index 9e1f1c7cf..fc2f92699 100644 --- a/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/ParsingTests.java +++ b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/ParsingTests.java @@ -1,61 +1,27 @@ package org.hl7.fhir.r5.test; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; import java.io.IOException; -import java.io.InputStream; import java.util.ArrayList; import java.util.List; import java.util.stream.Stream; import javax.xml.parsers.ParserConfigurationException; -import org.apache.commons.io.IOUtils; -import org.apache.commons.lang3.NotImplementedException; -import org.hl7.fhir.exceptions.DefinitionException; -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.conformance.ProfileUtilities.ProfileKnowledgeProvider; -import org.hl7.fhir.r5.context.IWorkerContext.IContextResourceLoader; 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.Base; -import org.hl7.fhir.r5.model.Bundle; -import org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionBindingComponent; -import org.hl7.fhir.r5.model.ExpressionNode.CollectionStatus; import org.hl7.fhir.r5.model.Resource; -import org.hl7.fhir.r5.model.StructureDefinition; -import org.hl7.fhir.r5.model.StructureDefinition.StructureDefinitionKind; -import org.hl7.fhir.r5.model.StructureDefinition.TypeDerivationRule; -import org.hl7.fhir.r5.renderers.RendererFactory; -import org.hl7.fhir.r5.renderers.utils.RenderingContext; -import org.hl7.fhir.r5.renderers.utils.RenderingContext.ResourceRendererMode; -import org.hl7.fhir.r5.model.TypeDetails; -import org.hl7.fhir.r5.model.ValueSet; import org.hl7.fhir.r5.test.utils.TestingUtilities; -import org.hl7.fhir.r5.utils.FHIRPathEngine; -import org.hl7.fhir.r5.utils.FHIRPathEngine.IEvaluationContext; -import org.hl7.fhir.r5.utils.IResourceValidator; -import org.hl7.fhir.r5.utils.XVerExtensionManager; import org.hl7.fhir.utilities.TextFile; -import org.hl7.fhir.utilities.Utilities; import org.hl7.fhir.utilities.npm.FilesystemPackageCacheManager; import org.hl7.fhir.utilities.npm.NpmPackage; import org.hl7.fhir.utilities.npm.ToolsVersion; -import org.hl7.fhir.utilities.validation.ValidationMessage; -import org.hl7.fhir.utilities.validation.ValidationMessage.IssueSeverity; -import org.hl7.fhir.utilities.xml.XMLUtil; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; -import org.w3c.dom.Document; -import org.w3c.dom.Element; import org.xml.sax.SAXException; public class ParsingTests { diff --git a/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/SnapShotGenerationTests.java b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/SnapShotGenerationTests.java index 066edc1bd..8c06c149a 100644 --- a/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/SnapShotGenerationTests.java +++ b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/SnapShotGenerationTests.java @@ -39,7 +39,7 @@ import org.hl7.fhir.r5.model.ValueSet; import org.hl7.fhir.r5.test.utils.TestingUtilities; import org.hl7.fhir.r5.utils.FHIRPathEngine; import org.hl7.fhir.r5.utils.FHIRPathEngine.IEvaluationContext; -import org.hl7.fhir.r5.utils.IResourceValidator; +import org.hl7.fhir.r5.utils.validation.IResourceValidator; import org.hl7.fhir.r5.utils.XVerExtensionManager; import org.hl7.fhir.utilities.Utilities; import org.hl7.fhir.utilities.npm.CommonPackages; diff --git a/org.hl7.fhir.report/pom.xml b/org.hl7.fhir.report/pom.xml index 69bdb4fe3..0e535718b 100644 --- a/org.hl7.fhir.report/pom.xml +++ b/org.hl7.fhir.report/pom.xml @@ -5,7 +5,7 @@
diff --git a/org.hl7.fhir.utilities/pom.xml b/org.hl7.fhir.utilities/pom.xml index 7c1fc33af..e83a15947 100644 --- a/org.hl7.fhir.utilities/pom.xml +++ b/org.hl7.fhir.utilities/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core -5.6.1-SNAPSHOT +5.6.2-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.utilities/src/test/java/org/hl7/fhir/utilities/UtilitiesTest.java b/org.hl7.fhir.utilities/src/test/java/org/hl7/fhir/utilities/UtilitiesTest.java index 252a0d033..b2264c95f 100644 --- a/org.hl7.fhir.utilities/src/test/java/org/hl7/fhir/utilities/UtilitiesTest.java +++ b/org.hl7.fhir.utilities/src/test/java/org/hl7/fhir/utilities/UtilitiesTest.java @@ -8,6 +8,7 @@ import org.junit.jupiter.api.Test; import java.io.File; import java.io.IOException; import java.nio.file.Paths; +import java.text.MessageFormat; import java.util.Random; import static org.junit.jupiter.api.Assertions.*; @@ -126,27 +127,34 @@ class UtilitiesTest { public static final int BIG_NEG = Utilities.ONE_MB * -1; + + private static final String buildMeasureLimitMessage(int size, String contains) { + return MessageFormat.format("\"{0}\" should contain \"{1}\"", size, contains); + } + + //TODO we've witnessed at least one intermittent failure of this test. It could be refactored to run several times to + // trigger edge cases more often now that it provides better feedback. @Test @DisplayName("Test size bounds on file size utility.") void describeSizeTest() { Assertions.assertAll("GB Measure Limits", - () -> assertTrue(Utilities.describeSize(GB_MEASURE_JUST_OVER).contains(Utilities.GB)), - () -> assertTrue(Utilities.describeSize(GB_MEASURE_EXACT).contains(Utilities.MB)), - () -> assertTrue(Utilities.describeSize(GB_MEASURE_JUST_UNDER).contains(Utilities.MB)) + () -> assertTrue(Utilities.describeSize(GB_MEASURE_JUST_OVER).contains(Utilities.GB), buildMeasureLimitMessage(GB_MEASURE_JUST_OVER, Utilities.GB)), + () -> assertTrue(Utilities.describeSize(GB_MEASURE_EXACT).contains(Utilities.MB), buildMeasureLimitMessage(GB_MEASURE_EXACT, Utilities.MB)), + () -> assertTrue(Utilities.describeSize(GB_MEASURE_JUST_UNDER).contains(Utilities.MB), buildMeasureLimitMessage(GB_MEASURE_JUST_UNDER, Utilities.MB)) ); Assertions.assertAll("MB Measure Limits", - () -> assertTrue(Utilities.describeSize(MB_MEASURE_JUST_OVER).contains(Utilities.MB)), - () -> assertTrue(Utilities.describeSize(MB_MEASURE_EXACT).contains(Utilities.KB)), - () -> assertTrue(Utilities.describeSize(MB_MEASURE_JUST_UNDER).contains(Utilities.KB)) + () -> assertTrue(Utilities.describeSize(MB_MEASURE_JUST_OVER).contains(Utilities.MB), buildMeasureLimitMessage(MB_MEASURE_JUST_OVER, Utilities.MB)), + () -> assertTrue(Utilities.describeSize(MB_MEASURE_EXACT).contains(Utilities.KB), buildMeasureLimitMessage(MB_MEASURE_EXACT, Utilities.KB)), + () -> assertTrue(Utilities.describeSize(MB_MEASURE_JUST_UNDER).contains(Utilities.KB), buildMeasureLimitMessage(MB_MEASURE_JUST_UNDER, Utilities.KB)) ); Assertions.assertAll("KB Measure Limits", - () -> assertTrue(Utilities.describeSize(KB_MEASURE_JUST_OVER).contains(Utilities.KB)), - () -> assertTrue(Utilities.describeSize(KB_MEASURE_EXACT).contains(Utilities.BT)), - () -> assertTrue(Utilities.describeSize(KB_MEASURE_JUST_UNDER).contains(Utilities.BT)) + () -> assertTrue(Utilities.describeSize(KB_MEASURE_JUST_OVER).contains(Utilities.KB), buildMeasureLimitMessage(KB_MEASURE_JUST_OVER, Utilities.KB)), + () -> assertTrue(Utilities.describeSize(KB_MEASURE_EXACT).contains(Utilities.BT), buildMeasureLimitMessage(KB_MEASURE_EXACT, Utilities.BT)), + () -> assertTrue(Utilities.describeSize(KB_MEASURE_JUST_UNDER).contains(Utilities.BT), buildMeasureLimitMessage(KB_MEASURE_JUST_UNDER, Utilities.BT)) ); Assertions.assertAll("BT Measure Limits", - () -> assertTrue(Utilities.describeSize(BT_MEASURE).contains(Utilities.BT)), - () -> assertTrue(Utilities.describeSize(EMPTY).contains(Utilities.BT)) + () -> assertTrue(Utilities.describeSize(BT_MEASURE).contains(Utilities.BT), buildMeasureLimitMessage(BT_MEASURE, Utilities.BT)), + () -> assertTrue(Utilities.describeSize(EMPTY).contains(Utilities.BT), buildMeasureLimitMessage(EMPTY, Utilities.BT)) ); Assertions.assertThrows(IllegalArgumentException.class, () -> Utilities.describeSize(BIG_NEG)); } diff --git a/org.hl7.fhir.validation.cli/pom.xml b/org.hl7.fhir.validation.cli/pom.xml index 1111b260c..afc498a13 100644 --- a/org.hl7.fhir.validation.cli/pom.xml +++ b/org.hl7.fhir.validation.cli/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core -5.6.1-SNAPSHOT +5.6.2-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.validation/pom.xml b/org.hl7.fhir.validation/pom.xml index c7f9dc9bb..d84e3480f 100644 --- a/org.hl7.fhir.validation/pom.xml +++ b/org.hl7.fhir.validation/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core -5.6.1-SNAPSHOT +5.6.2-SNAPSHOT ../pom.xml 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 d33363999..a26e280f4 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 @@ -1,84 +1,39 @@ package org.hl7.fhir.validation; -import static org.apache.commons.lang3.StringUtils.isBlank; - -import java.text.DateFormat; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Date; -import java.util.HashMap; - -/* - Copyright (c) 2011+, HL7, Inc. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - * Neither the name of HL7 nor the names of its contributors may be used to - endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. - - */ - - /* -Copyright (c) 2011+, HL7, Inc -All rights reserved. + Copyright (c) 2011+, HL7, Inc. + All rights reserved. -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - * Neither the name of HL7 nor the names of its contributors may be used to - endorse or promote products derived from this software without specific - prior written permission. + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name of HL7 nor the names of its contributors may be used to + endorse or promote products derived from this software without specific + prior written permission. -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. */ -import java.util.List; -import java.util.Map; import org.apache.commons.lang3.StringUtils; import org.hl7.fhir.r5.context.IWorkerContext; import org.hl7.fhir.r5.elementmodel.Element; -import org.hl7.fhir.r5.model.Base; -import org.hl7.fhir.r5.model.DomainResource; -import org.hl7.fhir.r5.model.Resource; -import org.hl7.fhir.r5.model.StructureDefinition; -import org.hl7.fhir.r5.model.ValueSet; +import org.hl7.fhir.r5.model.*; import org.hl7.fhir.r5.terminologies.ValueSetUtilities; import org.hl7.fhir.r5.utils.XVerExtensionManager; import org.hl7.fhir.r5.utils.XVerExtensionManager.XVerExtensionStatus; @@ -88,11 +43,16 @@ import org.hl7.fhir.utilities.validation.ValidationMessage; import org.hl7.fhir.utilities.validation.ValidationMessage.IssueSeverity; import org.hl7.fhir.utilities.validation.ValidationMessage.IssueType; import org.hl7.fhir.utilities.validation.ValidationMessage.Source; -import org.hl7.fhir.validation.BaseValidator.TrackedLocationRelatedMessage; import org.hl7.fhir.validation.instance.utils.IndexedElement; -public class BaseValidator { +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import static org.apache.commons.lang3.StringUtils.isBlank; + +public class BaseValidator { public class TrackedLocationRelatedMessage { private Object location; private ValidationMessage vmsg; @@ -107,8 +67,7 @@ public class BaseValidator { public ValidationMessage getVmsg() { return vmsg; } - - } + } public class ValidationControl { private boolean allowed; diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/NativeHostServices.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/NativeHostServices.java index e332a9ae8..57107e01d 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/NativeHostServices.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/NativeHostServices.java @@ -34,9 +34,6 @@ package org.hl7.fhir.validation; import java.io.ByteArrayOutputStream; import java.io.IOException; -import org.hl7.fhir.convertors.conv10_50.VersionConvertor_10_50; -import org.hl7.fhir.convertors.conv14_50.VersionConvertor_14_50; -import org.hl7.fhir.convertors.conv30_50.VersionConvertor_30_50; import org.hl7.fhir.convertors.factory.VersionConvertorFactory_10_50; import org.hl7.fhir.convertors.factory.VersionConvertorFactory_14_50; import org.hl7.fhir.convertors.factory.VersionConvertorFactory_30_50; @@ -69,9 +66,9 @@ import org.hl7.fhir.r5.model.FhirPublication; import org.hl7.fhir.r5.model.OperationOutcome; import org.hl7.fhir.r5.model.Resource; import org.hl7.fhir.r5.model.ValueSet; -import org.hl7.fhir.r5.utils.IResourceValidator.BestPracticeWarningLevel; -import org.hl7.fhir.r5.utils.IResourceValidator.CheckDisplayOption; -import org.hl7.fhir.r5.utils.IResourceValidator.IdStatus; +import org.hl7.fhir.r5.utils.validation.constants.BestPracticeWarningLevel; +import org.hl7.fhir.r5.utils.validation.constants.CheckDisplayOption; +import org.hl7.fhir.r5.utils.validation.constants.IdStatus; import org.hl7.fhir.utilities.Utilities; import org.hl7.fhir.utilities.VersionUtilities; 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 033927d7f..197460299 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 @@ -3,9 +3,6 @@ package org.hl7.fhir.validation; import lombok.Getter; import lombok.Setter; import lombok.experimental.Accessors; -import org.hl7.fhir.convertors.conv10_50.VersionConvertor_10_50; -import org.hl7.fhir.convertors.conv14_50.VersionConvertor_14_50; -import org.hl7.fhir.convertors.conv30_50.VersionConvertor_30_50; import org.hl7.fhir.convertors.factory.VersionConvertorFactory_10_50; import org.hl7.fhir.convertors.factory.VersionConvertorFactory_14_50; import org.hl7.fhir.convertors.factory.VersionConvertorFactory_30_50; @@ -35,10 +32,13 @@ import org.hl7.fhir.r5.renderers.utils.RenderingContext; import org.hl7.fhir.r5.renderers.utils.RenderingContext.ResourceRendererMode; import org.hl7.fhir.r5.utils.EOperationOutcome; import org.hl7.fhir.r5.utils.FHIRPathEngine; -import org.hl7.fhir.r5.utils.IResourceValidator; -import org.hl7.fhir.r5.utils.IResourceValidator.*; +import org.hl7.fhir.r5.utils.validation.BundleValidationRule; +import org.hl7.fhir.r5.utils.validation.IResourceValidator; import org.hl7.fhir.r5.utils.ToolingExtensions; import org.hl7.fhir.r5.utils.structuremap.StructureMapUtilities; +import org.hl7.fhir.r5.utils.validation.IValidationPolicyAdvisor; +import org.hl7.fhir.r5.utils.validation.IValidatorResourceFetcher; +import org.hl7.fhir.r5.utils.validation.constants.*; import org.hl7.fhir.utilities.TimeTracker; import org.hl7.fhir.utilities.*; import org.hl7.fhir.utilities.SimpleHTTPClient.HTTPResult; @@ -57,7 +57,6 @@ import org.xml.sax.SAXException; import java.io.*; import java.net.URISyntaxException; -import java.net.URL; import java.util.*; /* @@ -131,7 +130,7 @@ POSSIBILITY OF SUCH DAMAGE. * @author Grahame Grieve */ @Accessors(chain = true) -public class ValidationEngine implements IValidatorResourceFetcher, IPackageInstaller { +public class ValidationEngine implements IValidatorResourceFetcher, IValidationPolicyAdvisor, IPackageInstaller { @Getter @Setter private SimpleWorkerContext context; @Getter @Setter private Map ca.uhn.hapi.fhir org.hl7.fhir.core -5.6.1-SNAPSHOT +5.6.2-SNAPSHOT ../pom.xml binaries = new HashMap<>(); @@ -146,6 +145,7 @@ public class ValidationEngine implements IValidatorResourceFetcher, IPackageInst @Getter @Setter private PrintWriter mapLog; @Getter @Setter private boolean debug = false; @Getter @Setter private IValidatorResourceFetcher fetcher; + @Getter @Setter private IValidationPolicyAdvisor policyAdvisor; @Getter @Setter private ICanonicalResourceLocator locator; @Getter @Setter private boolean assumeValidRestReferences; @Getter @Setter private boolean noExtensibleBindingMessages; @@ -730,22 +730,43 @@ public class ValidationEngine implements IValidatorResourceFetcher, IPackageInst } @Override - public ReferenceValidationPolicy validationPolicy(IResourceValidator validator, Object appContext, String path, String url) { + public ReferenceValidationPolicy policyForReference(IResourceValidator validator, Object appContext, String path, String url) { Resource resource = context.fetchResource(StructureDefinition.class, url); if (resource != null) { return ReferenceValidationPolicy.CHECK_VALID; } if (!(url.contains("hl7.org") || url.contains("fhir.org"))) { return ReferenceValidationPolicy.IGNORE; - } else if (fetcher != null) { - return fetcher.validationPolicy(validator, appContext, path, url); + } else if (policyAdvisor != null) { + return policyAdvisor.policyForReference(validator, appContext, path, url); } else { return ReferenceValidationPolicy.CHECK_EXISTS_AND_TYPE; } } @Override - public boolean resolveURL(IResourceValidator validator, Object appContext, String path, String url, String type) throws IOException, FHIRException { + public ContainedReferenceValidationPolicy policyForContained(IResourceValidator validator, + Object appContext, + String containerType, + String containerId, + Element.SpecialElement containingResourceType, + String path, + String url) { + Resource resource = context.fetchResource(StructureDefinition.class, url); + if (resource != null) { + return ContainedReferenceValidationPolicy.CHECK_VALID; + } + if (!(url.contains("hl7.org") || url.contains("fhir.org"))) { + return ContainedReferenceValidationPolicy.IGNORE; + } else if (policyAdvisor != null) { + return policyAdvisor.policyForContained(validator, appContext, containerType, containerId, containingResourceType, path, url); + } else { + return ContainedReferenceValidationPolicy.CHECK_TYPE; + } + } + + @Override + public boolean resolveURL(IResourceValidator validator, Object appContext, String path, String url, String type) throws FHIRException { if (!url.startsWith("http://") && !url.startsWith("https://")) { // ignore these return true; } diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/model/CliContext.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/model/CliContext.java index f6ae3964d..1ac810f2d 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/model/CliContext.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/model/CliContext.java @@ -7,7 +7,7 @@ import java.util.Locale; import java.util.Map; import java.util.Objects; -import org.hl7.fhir.r5.utils.IResourceValidator.BundleValidationRule; +import org.hl7.fhir.r5.utils.validation.BundleValidationRule; import org.hl7.fhir.validation.cli.utils.QuestionnaireMode; import org.hl7.fhir.validation.cli.utils.EngineMode; 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 9eba19d20..7c3340fc8 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 @@ -8,9 +8,11 @@ import org.hl7.fhir.r5.context.IWorkerContext.ICanonicalResourceLocator; import org.hl7.fhir.r5.elementmodel.Element; import org.hl7.fhir.r5.model.CanonicalResource; import org.hl7.fhir.r5.terminologies.TerminologyClient; -import org.hl7.fhir.r5.utils.IResourceValidator; -import org.hl7.fhir.r5.utils.IResourceValidator.IValidatorResourceFetcher; -import org.hl7.fhir.r5.utils.IResourceValidator.ReferenceValidationPolicy; +import org.hl7.fhir.r5.utils.validation.IResourceValidator; +import org.hl7.fhir.r5.utils.validation.IValidationPolicyAdvisor; +import org.hl7.fhir.r5.utils.validation.IValidatorResourceFetcher; +import org.hl7.fhir.r5.utils.validation.constants.ContainedReferenceValidationPolicy; +import org.hl7.fhir.r5.utils.validation.constants.ReferenceValidationPolicy; import org.hl7.fhir.utilities.Utilities; import org.hl7.fhir.utilities.VersionUtilities; import org.hl7.fhir.utilities.VersionUtilities.VersionURLInfo; @@ -28,7 +30,7 @@ import java.util.List; import java.util.Locale; import java.util.Map; -public class StandAloneValidatorFetcher implements IValidatorResourceFetcher, ICanonicalResourceLocator { +public class StandAloneValidatorFetcher implements IValidatorResourceFetcher, IValidationPolicyAdvisor, ICanonicalResourceLocator { List mappingsUris = new ArrayList<>(); private FilesystemPackageCacheManager pcm; @@ -51,10 +53,24 @@ public class StandAloneValidatorFetcher implements IValidatorResourceFetcher, IC } @Override - public ReferenceValidationPolicy validationPolicy(IResourceValidator validator, Object appContext, String path, String url) { + public ReferenceValidationPolicy policyForReference(IResourceValidator validator, + Object appContext, + String path, + String url) { return ReferenceValidationPolicy.CHECK_TYPE_IF_EXISTS; } + @Override + public ContainedReferenceValidationPolicy policyForContained(IResourceValidator validator, + Object appContext, + String containerType, + String containerId, + Element.SpecialElement containingResourceType, + String path, + String url) { + return ContainedReferenceValidationPolicy.CHECK_TYPE; + } + @Override public boolean resolveURL(IResourceValidator validator, Object appContext, String path, String url, String type) throws IOException, FHIRException { if (!Utilities.isAbsoluteUrl(url)) { diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/utils/Params.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/utils/Params.java index e17b99afa..b738a825f 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/utils/Params.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/utils/Params.java @@ -1,7 +1,6 @@ package org.hl7.fhir.validation.cli.utils; -import org.apache.http.auth.AUTH; -import org.hl7.fhir.r5.utils.IResourceValidator.BundleValidationRule; +import org.hl7.fhir.r5.utils.validation.BundleValidationRule; import org.hl7.fhir.utilities.VersionUtilities; import org.hl7.fhir.validation.cli.model.CliContext; 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 0f08b395a..4c6b51d6d 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 @@ -47,8 +47,6 @@ import java.util.List; import java.util.Map; import java.util.Set; import java.util.UUID; -import java.util.regex.Matcher; -import java.util.regex.Pattern; import org.apache.commons.codec.binary.Base64InputStream; import org.apache.commons.lang3.NotImplementedException; @@ -135,9 +133,10 @@ import org.hl7.fhir.r5.terminologies.ValueSetExpander.TerminologyServiceErrorCla import org.hl7.fhir.r5.utils.FHIRLexer.FHIRLexerException; import org.hl7.fhir.r5.utils.FHIRPathEngine; import org.hl7.fhir.r5.utils.FHIRPathEngine.IEvaluationContext; -import org.hl7.fhir.r5.utils.IResourceValidator; +import org.hl7.fhir.r5.utils.validation.*; import org.hl7.fhir.r5.utils.ToolingExtensions; import org.hl7.fhir.r5.utils.XVerExtensionManager; +import org.hl7.fhir.r5.utils.validation.constants.*; import org.hl7.fhir.utilities.CommaSeparatedStringBuilder; import org.hl7.fhir.utilities.SIDUtilities; import org.hl7.fhir.utilities.UnicodeUtilities; @@ -174,8 +173,6 @@ import org.w3c.dom.Document; import com.google.gson.Gson; import com.google.gson.JsonObject; -import javax.annotation.Nonnull; - /** * Thinking of using this in a java program? Don't! @@ -381,6 +378,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat private Map fetchCache = new HashMap<>(); private HashMap resourceTracker = new HashMap<>(); private IValidatorResourceFetcher fetcher; + private IValidationPolicyAdvisor policyAdvisor; long time = 0; private IEvaluationContext externalHostServices; private boolean noExtensibleWarnings; @@ -464,6 +462,17 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat return this; } + @Override + public IValidationPolicyAdvisor getPolicyAdvisor() { + return policyAdvisor; + } + + @Override + public IResourceValidator setPolicyAdvisor(IValidationPolicyAdvisor advisor) { + this.policyAdvisor = advisor; + return this; + } + public IValidationProfileUsageTracker getTracker() { return this.tracker; } @@ -2114,7 +2123,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat } if (!found) { if (type.equals("canonical")) { - ReferenceValidationPolicy rp = fetcher.validationPolicy(this, appContext, path, url); + ReferenceValidationPolicy rp = policyAdvisor == null ? ReferenceValidationPolicy.CHECK_VALID : policyAdvisor.policyForReference(this, appContext, path, url); if (rp == ReferenceValidationPolicy.CHECK_EXISTS || rp == ReferenceValidationPolicy.CHECK_EXISTS_AND_TYPE) { rule(errors, IssueType.INVALID, e.line(), e.col(), path, found, I18nConstants.TYPE_SPECIFIC_CHECKS_DT_CANONICAL_RESOLVE, url); } else { @@ -2131,7 +2140,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat } } else { if (type.equals("canonical")) { - ReferenceValidationPolicy rp = fetcher.validationPolicy(this, appContext, path, url); + ReferenceValidationPolicy rp = policyAdvisor == null ? ReferenceValidationPolicy.CHECK_VALID : policyAdvisor.policyForReference(this, appContext, path, url); if (rp == ReferenceValidationPolicy.CHECK_EXISTS_AND_TYPE || rp == ReferenceValidationPolicy.CHECK_TYPE_IF_EXISTS || rp == ReferenceValidationPolicy.CHECK_VALID) { try { Resource r = fetcher.fetchCanonicalResource(this, url); @@ -2690,14 +2699,22 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat checkFixedValue(errors, path + ".denominator", focus.getNamedChild("denominator"), fixed.getDenominator(), fixedSource, "denominator", focus, pattern); } - private void checkReference(ValidatorHostContext hostContext, List errors, String path, Element element, StructureDefinition profile, ElementDefinition container, String parentType, NodeStack stack) throws FHIRException { + private void checkReference(ValidatorHostContext hostContext, + List errors, + String path, + Element element, + StructureDefinition profile, + ElementDefinition container, + String parentType, + NodeStack stack) throws FHIRException { Reference reference = ObjectConverter.readAsReference(element); String ref = reference.getReference(); if (Utilities.noString(ref)) { if (!path.contains("element.pattern")) { // this business rule doesn't apply to patterns if (Utilities.noString(reference.getIdentifier().getSystem()) && Utilities.noString(reference.getIdentifier().getValue())) { - warning(errors, IssueType.STRUCTURE, element.line(), element.col(), path, !Utilities.noString(element.getNamedChildValue("display")), I18nConstants.REFERENCE_REF_NODISPLAY); + warning(errors, IssueType.STRUCTURE, element.line(), element.col(), path, + !Utilities.noString(element.getNamedChildValue("display")), I18nConstants.REFERENCE_REF_NODISPLAY); } } return; @@ -2718,7 +2735,13 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat refType = "bundled"; } } - ReferenceValidationPolicy pol = refType.equals("contained") || refType.equals("bundled") ? ReferenceValidationPolicy.CHECK_VALID : fetcher == null ? ReferenceValidationPolicy.IGNORE : fetcher.validationPolicy(this, hostContext.getAppContext(), path, ref); + ReferenceValidationPolicy pol; + if (refType.equals("contained") || refType.equals("bundled")) { + pol = ReferenceValidationPolicy.CHECK_VALID; + } else { + if (policyAdvisor == null) pol = ReferenceValidationPolicy.IGNORE; + else pol = policyAdvisor.policyForReference(this, hostContext.getAppContext(), path, ref); + } if (pol.checkExists()) { if (we == null) { @@ -2745,7 +2768,8 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat } } } - boolean ok = (allowExamples && (ref.contains("example.org") || ref.contains("acme.com"))) || (we != null || pol == ReferenceValidationPolicy.CHECK_TYPE_IF_EXISTS); + boolean ok = (allowExamples && (ref.contains("example.org") || ref.contains("acme.com"))) + || (we != null || pol == ReferenceValidationPolicy.CHECK_TYPE_IF_EXISTS); rule(errors, IssueType.STRUCTURE, element.line(), element.col(), path, ok, I18nConstants.REFERENCE_REF_CANTRESOLVE, ref); } @@ -2767,22 +2791,26 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat boolean matchingResource = false; for (CanonicalType target : containerType.getTargetProfile()) { StructureDefinition sd = resolveProfile(profile, target.asStringValue()); - if (rule(errors, IssueType.NOTFOUND, element.line(), element.col(), path, sd != null, I18nConstants.REFERENCE_REF_CANTRESOLVEPROFILE, target.asStringValue())) { + if (rule(errors, IssueType.NOTFOUND, element.line(), element.col(), path, sd != null, + I18nConstants.REFERENCE_REF_CANTRESOLVEPROFILE, target.asStringValue())) { if (("http://hl7.org/fhir/StructureDefinition/" + sd.getType()).equals(tu)) { matchingResource = true; break; } } } - rule(errors, IssueType.STRUCTURE, element.line(), element.col(), path, matchingResource, I18nConstants.REFERENCE_REF_WRONGTARGET, reference.getType(), container.getType("Reference").getTargetProfile()); + rule(errors, IssueType.STRUCTURE, element.line(), element.col(), path, matchingResource, + I18nConstants.REFERENCE_REF_WRONGTARGET, reference.getType(), container.getType("Reference").getTargetProfile()); } // the type has to match the actual - rule(errors, IssueType.STRUCTURE, element.line(), element.col(), path, ft == null || ft.equals(reference.getType()), I18nConstants.REFERENCE_REF_BADTARGETTYPE, reference.getType(), ft); + rule(errors, IssueType.STRUCTURE, element.line(), element.col(), path, + ft == null || ft.equals(reference.getType()), I18nConstants.REFERENCE_REF_BADTARGETTYPE, reference.getType(), ft); } if (we != null && pol.checkType()) { - if (warning(errors, IssueType.STRUCTURE, element.line(), element.col(), path, ft != null, I18nConstants.REFERENCE_REF_NOTYPE)) { + if (warning(errors, IssueType.STRUCTURE, element.line(), element.col(), path, ft != null, + I18nConstants.REFERENCE_REF_NOTYPE)) { // we validate as much as we can. First, can we infer a type from the profile? boolean ok = false; TypeRefComponent type = getReferenceTypeRef(container.getType()); @@ -2791,7 +2819,8 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat List profiles = new ArrayList<>(); for (UriType u : type.getTargetProfile()) { StructureDefinition sd = resolveProfile(profile, u.getValue()); - if (rule(errors, IssueType.STRUCTURE, element.line(), element.col(), path, sd != null, I18nConstants.REFERENCE_REF_CANTRESOLVEPROFILE, u.getValue())) { + if (rule(errors, IssueType.STRUCTURE, element.line(), element.col(), path, sd != null, + I18nConstants.REFERENCE_REF_CANTRESOLVEPROFILE, u.getValue())) { types.add(sd.getType()); if (ft.equals(sd.getType())) { ok = true; @@ -2800,14 +2829,16 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat } } if (!pol.checkValid()) { - rule(errors, IssueType.STRUCTURE, element.line(), element.col(), path, profiles.size() > 0, I18nConstants.REFERENCE_REF_CANTMATCHTYPE, ref, StringUtils.join("; ", type.getTargetProfile())); + rule(errors, IssueType.STRUCTURE, element.line(), element.col(), path, profiles.size() > 0, + I18nConstants.REFERENCE_REF_CANTMATCHTYPE, ref, StringUtils.join("; ", type.getTargetProfile())); } else { - Map > badProfiles = new HashMap >(); - Map > goodProfiles = new HashMap >(); + Map > badProfiles = new HashMap<>(); + Map > goodProfiles = new HashMap<>(); int goodCount = 0; for (StructureDefinition pr : profiles) { List profileErrors = new ArrayList (); - validateResource(we.hostContext(hostContext, pr), profileErrors, we.getResource(), we.getFocus(), pr, IdStatus.OPTIONAL, we.getStack().resetIds()); + validateResource(we.hostContext(hostContext, pr), profileErrors, we.getResource(), we.getFocus(), pr, + IdStatus.OPTIONAL, we.getStack().resetIds()); if (!hasErrors(profileErrors)) { goodCount++; goodProfiles.put(pr, profileErrors); @@ -2827,14 +2858,16 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat } else if (goodProfiles.size() == 0) { if (!isShowMessagesFromReferences()) { - rule(errors, IssueType.STRUCTURE, element.line(), element.col(), path, areAllBaseProfiles(profiles), I18nConstants.REFERENCE_REF_CANTMATCHCHOICE, ref, asList(type.getTargetProfile())); + rule(errors, IssueType.STRUCTURE, element.line(), element.col(), path, areAllBaseProfiles(profiles), + I18nConstants.REFERENCE_REF_CANTMATCHCHOICE, ref, asList(type.getTargetProfile())); for (StructureDefinition sd : badProfiles.keySet()) { slicingHint(errors, IssueType.STRUCTURE, element.line(), element.col(), path, false, false, context.formatMessage(I18nConstants.DETAILS_FOR__MATCHING_AGAINST_PROFILE_, ref, sd.getUrl()), errorSummaryForSlicingAsHtml(badProfiles.get(sd)), errorSummaryForSlicingAsText(badProfiles.get(sd))); } } else { - rule(errors, IssueType.STRUCTURE, element.line(), element.col(), path, profiles.size() == 1, I18nConstants.REFERENCE_REF_CANTMATCHCHOICE, ref, asList(type.getTargetProfile())); + rule(errors, IssueType.STRUCTURE, element.line(), element.col(), path, profiles.size() == 1, + I18nConstants.REFERENCE_REF_CANTMATCHCHOICE, ref, asList(type.getTargetProfile())); for (List messages : badProfiles.values()) { for (ValidationMessage vm : messages) { if (!errors.contains(vm)) { @@ -2845,13 +2878,16 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat } } else { if (!isShowMessagesFromReferences()) { - warning(errors, IssueType.STRUCTURE, element.line(), element.col(), path, false, I18nConstants.REFERENCE_REF_MULTIPLEMATCHES, ref, asListByUrl(goodProfiles.keySet())); + warning(errors, IssueType.STRUCTURE, element.line(), element.col(), path, false, + I18nConstants.REFERENCE_REF_MULTIPLEMATCHES, ref, asListByUrl(goodProfiles.keySet())); for (StructureDefinition sd : badProfiles.keySet()) { - slicingHint(errors, IssueType.STRUCTURE, element.line(), element.col(), path, false, false, context.formatMessage(I18nConstants.DETAILS_FOR__MATCHING_AGAINST_PROFILE_, ref, sd.getUrl()), + slicingHint(errors, IssueType.STRUCTURE, element.line(), element.col(), path, false, + false, context.formatMessage(I18nConstants.DETAILS_FOR__MATCHING_AGAINST_PROFILE_, ref, sd.getUrl()), errorSummaryForSlicingAsHtml(badProfiles.get(sd)), errorSummaryForSlicingAsText(badProfiles.get(sd))); } } else { - warning(errors, IssueType.STRUCTURE, element.line(), element.col(), path, false, I18nConstants.REFERENCE_REF_MULTIPLEMATCHES, ref, asListByUrl(goodProfiles.keySet())); + warning(errors, IssueType.STRUCTURE, element.line(), element.col(), path, false, + I18nConstants.REFERENCE_REF_MULTIPLEMATCHES, ref, asListByUrl(goodProfiles.keySet())); for (List messages : goodProfiles.values()) { for (ValidationMessage vm : messages) { if (!errors.contains(vm)) { @@ -2862,7 +2898,8 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat } } } - rule(errors, IssueType.STRUCTURE, element.line(), element.col(), path, ok, I18nConstants.REFERENCE_REF_BADTARGETTYPE, ft, types.toString()); + rule(errors, IssueType.STRUCTURE, element.line(), element.col(), path, ok, + I18nConstants.REFERENCE_REF_BADTARGETTYPE, ft, types.toString()); } if (type.hasAggregation() && !noCheckAggregation) { boolean modeOk = false; @@ -2876,7 +2913,8 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat else if (mode.getValue().equals(AggregationMode.REFERENCED) && (refType.equals("bundled") || refType.equals("remote"))) modeOk = true; } - rule(errors, IssueType.STRUCTURE, element.line(), element.col(), path, modeOk, I18nConstants.REFERENCE_REF_AGGREGATION, refType, b.toString()); + rule(errors, IssueType.STRUCTURE, element.line(), element.col(), path, modeOk, + I18nConstants.REFERENCE_REF_AGGREGATION, refType, b.toString()); } } } @@ -2905,7 +2943,8 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat sdF = sdF.hasBaseDefinition() ? context.fetchResource(StructureDefinition.class, sdF.getBaseDefinition()) : null; } } - rule(errors, IssueType.STRUCTURE, element.line(), element.col(), path, types.isEmpty() || ok, I18nConstants.REFERENCE_REF_BADTARGETTYPE2, ft, ref, types); + rule(errors, IssueType.STRUCTURE, element.line(), element.col(), path, types.isEmpty() || ok, + I18nConstants.REFERENCE_REF_BADTARGETTYPE2, ft, ref, types); } if (pol == ReferenceValidationPolicy.CHECK_VALID) { @@ -4349,84 +4388,108 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat } } - private void validateContains(ValidatorHostContext hostContext, List errors, String path, ElementDefinition child, ElementDefinition context, Element resource, Element element, NodeStack stack, IdStatus idstatus) throws FHIRException { + private void validateContains(ValidatorHostContext hostContext, List errors, String path, + ElementDefinition child, ElementDefinition context, Element resource, + Element element, NodeStack stack, IdStatus idstatus, StructureDefinition parentProfile) throws FHIRException { + + SpecialElement special = element.getSpecial(); + + ContainedReferenceValidationPolicy containedValidationPolicy = getPolicyAdvisor() == null ? + ContainedReferenceValidationPolicy.CHECK_VALID : getPolicyAdvisor().policyForContained(this, + hostContext, context.fhirType(), context.getId(), special, path, parentProfile.getUrl()); + + if (containedValidationPolicy.ignore()) { + return; + } + String resourceName = element.getType(); - TypeRefComponent trr = null; + TypeRefComponent typeForResource = null; CommaSeparatedStringBuilder bt = new CommaSeparatedStringBuilder(); - for (TypeRefComponent tr : child.getType()) { - bt.append(tr.getCode()); - if (tr.getCode().equals("Resource") || tr.getCode().equals(resourceName) ) { - trr = tr; + + // Iterate through all possible types + for (TypeRefComponent type : child.getType()) { + bt.append(type.getCode()); + if (type.getCode().equals("Resource") || type.getCode().equals(resourceName) ) { + typeForResource = type; break; } } + stack.qualifyPath(".ofType("+resourceName+")"); - if (trr == null) { - rule(errors, IssueType.INFORMATIONAL, element.line(), element.col(), stack.getLiteralPath(), false, I18nConstants.BUNDLE_BUNDLE_ENTRY_TYPE, resourceName, bt.toString()); - } else if (isValidResourceType(resourceName, trr)) { - // special case: resource wrapper is reset if we're crossing a bundle boundary, but not otherwise - ValidatorHostContext hc = null; - if (element.getSpecial() == SpecialElement.BUNDLE_ENTRY || element.getSpecial() == SpecialElement.BUNDLE_OUTCOME || element.getSpecial() == SpecialElement.PARAMETER) { - resource = element; - hc = hostContext.forEntry(element); - } else { - hc = hostContext.forContained(element); - } - stack.resetIds(); - if (element.getSpecial() != null) { - switch (element.getSpecial()) { - case BUNDLE_ENTRY: - idstatus = IdStatus.OPTIONAL; - break; - case BUNDLE_OUTCOME: - idstatus = IdStatus.OPTIONAL; - break; - case CONTAINED: - stack.setContained(true); - idstatus = IdStatus.REQUIRED; - break; - case PARAMETER: - idstatus = IdStatus.OPTIONAL; - break; - default: - break; + + if (typeForResource == null) { + rule(errors, IssueType.INFORMATIONAL, element.line(), element.col(), stack.getLiteralPath(), + false, I18nConstants.BUNDLE_BUNDLE_ENTRY_TYPE, resourceName, bt.toString()); + } else if (isValidResourceType(resourceName, typeForResource)) { + if (containedValidationPolicy.checkValid()) { + // special case: resource wrapper is reset if we're crossing a bundle boundary, but not otherwise + ValidatorHostContext hc = null; + if (special == SpecialElement.BUNDLE_ENTRY || special == SpecialElement.BUNDLE_OUTCOME || special == SpecialElement.PARAMETER) { + resource = element; + hc = hostContext.forEntry(element); + } else { + hc = hostContext.forContained(element); } - } - if (trr.getProfile().size() == 1) { - long t = System.nanoTime(); - StructureDefinition profile = this.context.fetchResource(StructureDefinition.class, trr.getProfile().get(0).asStringValue()); - timeTracker.sd(t); - trackUsage(profile, hostContext, element); - if (rule(errors, IssueType.INVALID, element.line(), element.col(), stack.getLiteralPath(), profile != null, I18nConstants.BUNDLE_BUNDLE_ENTRY_NOPROFILE, resourceName)) { - validateResource(hc, errors, resource, element, profile, idstatus, stack); + + stack.resetIds(); + if (special != null) { + switch (special) { + case BUNDLE_ENTRY: + case BUNDLE_OUTCOME: + case PARAMETER: + idstatus = IdStatus.OPTIONAL; + break; + case CONTAINED: + stack.setContained(true); + idstatus = IdStatus.REQUIRED; + break; + default: + break; + } } - } else if (trr.getProfile().size() == 0) { - long t = System.nanoTime(); - StructureDefinition profile = this.context.fetchResource(StructureDefinition.class, "http://hl7.org/fhir/StructureDefinition/" + resourceName); - timeTracker.sd(t); - trackUsage(profile, hostContext, element); - if (rule(errors, IssueType.INVALID, element.line(), element.col(), stack.getLiteralPath(), profile != null, I18nConstants.BUNDLE_BUNDLE_ENTRY_NOPROFILE, resourceName)) { - validateResource(hc, errors, resource, element, profile, idstatus, stack); + + if (typeForResource.getProfile().size() == 1) { + long t = System.nanoTime(); + StructureDefinition profile = this.context.fetchResource(StructureDefinition.class, typeForResource.getProfile().get(0).asStringValue()); + timeTracker.sd(t); + trackUsage(profile, hostContext, element); + if (rule(errors, IssueType.INVALID, element.line(), element.col(), stack.getLiteralPath(), + profile != null, I18nConstants.BUNDLE_BUNDLE_ENTRY_NOPROFILE, resourceName)) { + validateResource(hc, errors, resource, element, profile, idstatus, stack); + } + } else if (typeForResource.getProfile().isEmpty()) { + long t = System.nanoTime(); + StructureDefinition profile = this.context.fetchResource(StructureDefinition.class, + "http://hl7.org/fhir/StructureDefinition/" + resourceName); + timeTracker.sd(t); + trackUsage(profile, hostContext, element); + if (rule(errors, IssueType.INVALID, element.line(), element.col(), stack.getLiteralPath(), + profile != null, I18nConstants.BUNDLE_BUNDLE_ENTRY_NOPROFILE, resourceName)) { + validateResource(hc, errors, resource, element, profile, idstatus, stack); + } + } else { + CommaSeparatedStringBuilder b = new CommaSeparatedStringBuilder(); + for (CanonicalType u : typeForResource.getProfile()) { + b.append(u.asStringValue()); + } + rule(errors, IssueType.INVALID, element.line(), element.col(), stack.getLiteralPath(), + false, I18nConstants.BUNDLE_BUNDLE_ENTRY_MULTIPLE_PROFILES, typeForResource.getCode(), b.toString()); } - } else { - CommaSeparatedStringBuilder b = new CommaSeparatedStringBuilder(); - for (CanonicalType u : trr.getProfile()) { - b.append(u.asStringValue()); - } - rule(errors, IssueType.INVALID, element.line(), element.col(), stack.getLiteralPath(), false, I18nConstants.BUNDLE_BUNDLE_ENTRY_MULTIPLE_PROFILES, trr.getCode(), b.toString()); } } else { List types = new ArrayList<>(); - for (UriType u : trr.getProfile()) { + for (UriType u : typeForResource.getProfile()) { StructureDefinition sd = this.context.fetchResource(StructureDefinition.class, u.getValue()); if (sd != null && !types.contains(sd.getType())) { types.add(sd.getType()); } } if (types.size() == 1) { - rule(errors, IssueType.INFORMATIONAL, element.line(), element.col(), stack.getLiteralPath(), false, I18nConstants.BUNDLE_BUNDLE_ENTRY_TYPE2, resourceName, types.get(0)); + rule(errors, IssueType.INFORMATIONAL, element.line(), element.col(), stack.getLiteralPath(), + false, I18nConstants.BUNDLE_BUNDLE_ENTRY_TYPE2, resourceName, types.get(0)); } else { - rule(errors, IssueType.INFORMATIONAL, element.line(), element.col(), stack.getLiteralPath(), false, I18nConstants.BUNDLE_BUNDLE_ENTRY_TYPE3, resourceName, types); + rule(errors, IssueType.INFORMATIONAL, element.line(), element.col(), stack.getLiteralPath(), + false, I18nConstants.BUNDLE_BUNDLE_ENTRY_TYPE3, resourceName, types); } } } @@ -4590,7 +4653,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat rule(errors, IssueType.STRUCTURE, element.line(), element.col(), ei.getPath(), false, I18nConstants.EXTENSION_PROF_TYPE, profile.getUrl(), type, stype); } } - // + // Excluding reference is a kludge to get around versioning issues if (checkDefn.getType().get(0).hasProfile()) { for (CanonicalType p : checkDefn.getType().get(0).getProfile()) { @@ -4717,7 +4780,8 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat } } } else if (type.equals("Resource") || isResource(type)) { - validateContains(hostContext, errors, ei.getPath(), checkDefn, definition, resource, ei.getElement(), localStack, idStatusForEntry(element, ei)); // if + validateContains(hostContext, errors, ei.getPath(), checkDefn, definition, resource, ei.getElement(), + localStack, idStatusForEntry(element, ei), profile); // if elementValidated = true; // (str.matches(".*([.,/])work\\1$")) } else if (Utilities.isAbsoluteUrl(type)) { @@ -5288,18 +5352,24 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat /* * The actual base entry point for internal use (re-entrant) */ - private void validateResource(ValidatorHostContext hostContext, List errors, Element resource, Element element, StructureDefinition defn, IdStatus idstatus, NodeStack stack) throws FHIRException { + private void validateResource(ValidatorHostContext hostContext, List errors, Element resource, + Element element, StructureDefinition defn, IdStatus idstatus, NodeStack stack) throws FHIRException { + + // check here if we call validation policy here, and then change it to the new interface assert stack != null; assert resource != null; boolean ok = true; String resourceName = element.getType(); // todo: consider namespace...? + if (defn == null) { long t = System.nanoTime(); defn = element.getProperty().getStructure(); if (defn == null) defn = context.fetchResource(StructureDefinition.class, "http://hl7.org/fhir/StructureDefinition/" + resourceName); timeTracker.sd(t); - ok = rule(errors, IssueType.INVALID, element.line(), element.col(), stack.addToLiteralPath(resourceName), defn != null, I18nConstants.VALIDATION_VAL_PROFILE_NODEFINITION, resourceName); + //check exists + ok = rule(errors, IssueType.INVALID, element.line(), element.col(), stack.addToLiteralPath(resourceName), + defn != null, I18nConstants.VALIDATION_VAL_PROFILE_NODEFINITION, resourceName); } // special case: we have a bundle, and the profile is not for a bundle. We'll try the first entry instead @@ -5308,19 +5378,16 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat if (first != null && typeMatchesDefn(first.getElement().getType(), defn)) { element = first.getElement(); stack = first; - resourceName = element.getType(); idstatus = IdStatus.OPTIONAL; // why? } // todo: validate everything in this bundle. } - ok = rule(errors, IssueType.INVALID, -1, -1, stack.getLiteralPath(), typeMatchesDefn(resourceName, defn), I18nConstants.VALIDATION_VAL_PROFILE_WRONGTYPE, defn.getType(), resourceName, defn.getName()); - if (ok) { if (idstatus == IdStatus.REQUIRED && (element.getNamedChild(ID) == null)) { rule(errors, IssueType.INVALID, element.line(), element.col(), stack.getLiteralPath(), false, I18nConstants.RESOURCE_RES_ID_MISSING); } else if (idstatus == IdStatus.PROHIBITED && (element.getNamedChild(ID) != null)) { rule(errors, IssueType.INVALID, element.line(), element.col(), stack.getLiteralPath(), false, I18nConstants.RESOURCE_RES_ID_PROHIBITED); - } + } if (element.getNamedChild(ID) != null) { Element eid = element.getNamedChild(ID); if (eid.getProperty() != null && eid.getProperty().getDefinition() != null && eid.getProperty().getDefinition().getBase().getPath().equals("Resource.id")) { @@ -5328,6 +5395,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat rule(errors, IssueType.INVALID, eid.line(), eid.col(), ns.getLiteralPath(), FormatUtilities.isValidId(eid.primitiveValue()), I18nConstants.RESOURCE_RES_ID_MALFORMED); } } + // validate start(hostContext, errors, element, element, defn, stack); // root is both definition and type } } diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/InstanceValidatorFactory.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/InstanceValidatorFactory.java index d51487f6e..cf69c05fc 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/InstanceValidatorFactory.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/InstanceValidatorFactory.java @@ -1,7 +1,7 @@ -package org.hl7.fhir.validation.instance; - -import org.hl7.fhir.exceptions.FHIRException; - +package org.hl7.fhir.validation.instance; + +import org.hl7.fhir.exceptions.FHIRException; + /* Copyright (c) 2011+, HL7, Inc. All rights reserved. @@ -30,24 +30,24 @@ import org.hl7.fhir.exceptions.FHIRException; POSSIBILITY OF SUCH DAMAGE. */ - - - -import org.hl7.fhir.r5.context.IWorkerContext; -import org.hl7.fhir.r5.context.SimpleWorkerContext.IValidatorFactory; -import org.hl7.fhir.r5.utils.IResourceValidator; -import org.hl7.fhir.r5.utils.XVerExtensionManager; - -public class InstanceValidatorFactory implements IValidatorFactory { - - @Override - public IResourceValidator makeValidator(IWorkerContext ctxt, XVerExtensionManager xverManager) throws FHIRException { - return new InstanceValidator(ctxt, null, xverManager); - } - - @Override - public IResourceValidator makeValidator(IWorkerContext ctxt) throws FHIRException { - return new InstanceValidator(ctxt, null, null); - } - + + + +import org.hl7.fhir.r5.context.IWorkerContext; +import org.hl7.fhir.r5.context.SimpleWorkerContext.IValidatorFactory; +import org.hl7.fhir.r5.utils.validation.IResourceValidator; +import org.hl7.fhir.r5.utils.XVerExtensionManager; + +public class InstanceValidatorFactory implements IValidatorFactory { + + @Override + public IResourceValidator makeValidator(IWorkerContext ctxt, XVerExtensionManager xverManager) throws FHIRException { + return new InstanceValidator(ctxt, null, xverManager); + } + + @Override + public IResourceValidator makeValidator(IWorkerContext ctxt) throws FHIRException { + return new InstanceValidator(ctxt, null, null); + } + } \ No newline at end of file diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/type/BundleValidator.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/type/BundleValidator.java index 6f53644d1..2ab7ab597 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/type/BundleValidator.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/type/BundleValidator.java @@ -14,7 +14,7 @@ import org.hl7.fhir.r5.model.Constants; import org.hl7.fhir.r5.model.Enumerations.FHIRVersion; import org.hl7.fhir.r5.model.StructureDefinition; import org.hl7.fhir.r5.utils.XVerExtensionManager; -import org.hl7.fhir.r5.utils.IResourceValidator.BundleValidationRule; +import org.hl7.fhir.r5.utils.validation.BundleValidationRule; import org.hl7.fhir.utilities.Utilities; import org.hl7.fhir.utilities.VersionUtilities; import org.hl7.fhir.utilities.i18n.I18nConstants; @@ -369,7 +369,8 @@ public class BundleValidator extends BaseValidator{ if (ref != null && !Utilities.noString(reference) && !reference.startsWith("#")) { Element target = resolveInBundle(entries, reference, fullUrl, type, id); - rule(errors, IssueType.INVALID, ref.line(), ref.col(), stack.addToLiteralPath("reference"), target != null, I18nConstants.BUNDLE_BUNDLE_ENTRY_NOTFOUND, reference, name); + rule(errors, IssueType.INVALID, ref.line(), ref.col(), stack.addToLiteralPath("reference"), target != null, + I18nConstants.BUNDLE_BUNDLE_ENTRY_NOTFOUND, reference, name); } } diff --git a/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/conversion/tests/R3R4ConversionTests.java b/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/conversion/tests/R3R4ConversionTests.java index 9ea700674..f0a78967b 100644 --- a/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/conversion/tests/R3R4ConversionTests.java +++ b/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/conversion/tests/R3R4ConversionTests.java @@ -37,11 +37,12 @@ import org.hl7.fhir.r4.model.StructureDefinition.StructureDefinitionKind; import org.hl7.fhir.r4.model.StructureMap; import org.hl7.fhir.r4.model.UriType; import org.hl7.fhir.r4.test.utils.TestingUtilities; -import org.hl7.fhir.r4.utils.IResourceValidator; -import org.hl7.fhir.r4.utils.IResourceValidator.IValidatorResourceFetcher; -import org.hl7.fhir.r4.utils.IResourceValidator.ReferenceValidationPolicy; +import org.hl7.fhir.r4.utils.validation.IResourceValidator; +import org.hl7.fhir.r4.utils.validation.IValidatorResourceFetcher; +import org.hl7.fhir.r4.utils.validation.constants.ReferenceValidationPolicy; import org.hl7.fhir.r4.utils.StructureMapUtilities; import org.hl7.fhir.r4.utils.StructureMapUtilities.ITransformerServices; +import org.hl7.fhir.r4.utils.validation.IValidationPolicyAdvisor; import org.hl7.fhir.utilities.IniFile; import org.hl7.fhir.utilities.TextFile; import org.hl7.fhir.utilities.Utilities; @@ -62,7 +63,7 @@ import com.google.gson.JsonObject; import com.google.gson.JsonPrimitive; @Disabled -public class R3R4ConversionTests implements ITransformerServices, IValidatorResourceFetcher { +public class R3R4ConversionTests implements ITransformerServices, IValidatorResourceFetcher, IValidationPolicyAdvisor { private static final boolean SAVING = true; private FilesystemPackageCacheManager pcm = null; @@ -454,7 +455,15 @@ public class R3R4ConversionTests implements ITransformerServices, IValidatorReso } @Override - public ReferenceValidationPolicy validationPolicy(Object appContext, String path, String url) { + public ReferenceValidationPolicy policyForReference(IResourceValidator validator, Object appContext, String path, String url) { + return ReferenceValidationPolicy.IGNORE; + } + + @Override + public ReferenceValidationPolicy policyForContained(IResourceValidator validator, Object appContext, + String containerType, String containerId, + Element.SpecialElement containingResourceType, String path, + String url) { return ReferenceValidationPolicy.IGNORE; } diff --git a/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/conversion/tests/SnapShotGenerationXTests.java b/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/conversion/tests/SnapShotGenerationXTests.java index d6a087ab5..d5896e537 100644 --- a/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/conversion/tests/SnapShotGenerationXTests.java +++ b/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/conversion/tests/SnapShotGenerationXTests.java @@ -4,7 +4,6 @@ import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; -import java.io.InputStream; import java.util.ArrayList; import java.util.List; @@ -20,7 +19,6 @@ import org.hl7.fhir.exceptions.PathEngineException; import org.hl7.fhir.r5.conformance.ProfileUtilities; import org.hl7.fhir.r5.conformance.ProfileUtilities.ProfileKnowledgeProvider; 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.Base; import org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionBindingComponent; @@ -37,7 +35,7 @@ import org.hl7.fhir.r5.renderers.utils.RenderingContext.ResourceRendererMode; import org.hl7.fhir.r5.test.utils.TestingUtilities; import org.hl7.fhir.r5.utils.FHIRPathEngine; import org.hl7.fhir.r5.utils.FHIRPathEngine.IEvaluationContext; -import org.hl7.fhir.r5.utils.IResourceValidator; +import org.hl7.fhir.r5.utils.validation.IResourceValidator; import org.hl7.fhir.utilities.Utilities; import org.hl7.fhir.utilities.validation.ValidationMessage; import org.hl7.fhir.utilities.validation.ValidationMessage.IssueSeverity; 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 0d2ccf2c8..0d38760f4 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 @@ -5,7 +5,6 @@ import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.net.MalformedURLException; -import java.net.URL; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Collections; @@ -16,9 +15,6 @@ import java.util.Map; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.NotImplementedException; -import org.hl7.fhir.convertors.conv10_50.VersionConvertor_10_50; -import org.hl7.fhir.convertors.conv14_50.VersionConvertor_14_50; -import org.hl7.fhir.convertors.conv30_50.VersionConvertor_30_50; import org.hl7.fhir.convertors.factory.VersionConvertorFactory_10_50; import org.hl7.fhir.convertors.factory.VersionConvertorFactory_14_50; import org.hl7.fhir.convertors.factory.VersionConvertorFactory_30_50; @@ -32,7 +28,6 @@ import org.hl7.fhir.r5.elementmodel.Element; import org.hl7.fhir.r5.elementmodel.Manager; import org.hl7.fhir.r5.elementmodel.Manager.FhirFormat; import org.hl7.fhir.r5.elementmodel.ObjectConverter; -import org.hl7.fhir.r5.elementmodel.SHCParser; import org.hl7.fhir.r5.formats.JsonParser; import org.hl7.fhir.r5.formats.XmlParser; import org.hl7.fhir.r5.model.Base; @@ -48,11 +43,13 @@ import org.hl7.fhir.r5.model.ValueSet; import org.hl7.fhir.r5.test.utils.TestingUtilities; import org.hl7.fhir.r5.utils.FHIRPathEngine; import org.hl7.fhir.r5.utils.FHIRPathEngine.IEvaluationContext; -import org.hl7.fhir.r5.utils.IResourceValidator; -import org.hl7.fhir.r5.utils.IResourceValidator.BestPracticeWarningLevel; -import org.hl7.fhir.r5.utils.IResourceValidator.BundleValidationRule; -import org.hl7.fhir.r5.utils.IResourceValidator.IValidatorResourceFetcher; -import org.hl7.fhir.r5.utils.IResourceValidator.ReferenceValidationPolicy; +import org.hl7.fhir.r5.utils.validation.IResourceValidator; +import org.hl7.fhir.r5.utils.validation.IValidationPolicyAdvisor; +import org.hl7.fhir.r5.utils.validation.constants.BestPracticeWarningLevel; +import org.hl7.fhir.r5.utils.validation.BundleValidationRule; +import org.hl7.fhir.r5.utils.validation.IValidatorResourceFetcher; +import org.hl7.fhir.r5.utils.validation.constants.ContainedReferenceValidationPolicy; +import org.hl7.fhir.r5.utils.validation.constants.ReferenceValidationPolicy; import org.hl7.fhir.utilities.SimpleHTTPClient; import org.hl7.fhir.utilities.SimpleHTTPClient.HTTPResult; import org.hl7.fhir.utilities.TextFile; @@ -80,7 +77,7 @@ import com.google.gson.JsonElement; import com.google.gson.JsonObject; @RunWith(Parameterized.class) -public class ValidationTests implements IEvaluationContext, IValidatorResourceFetcher { +public class ValidationTests implements IEvaluationContext, IValidatorResourceFetcher, IValidationPolicyAdvisor { public final static boolean PRINT_OUTPUT_TO_CONSOLE = true; @@ -179,6 +176,9 @@ public class ValidationTests implements IEvaluationContext, IValidatorResourceFe } else { val.setFetcher(this); } + + val.setPolicyAdvisor(this); + if (content.has("allowed-extension-domain")) val.getExtensionDomains().add(content.get("allowed-extension-domain").getAsString()); if (content.has("allowed-extension-domains")) @@ -509,13 +509,24 @@ public class ValidationTests implements IEvaluationContext, IValidatorResourceFe } @Override - public ReferenceValidationPolicy validationPolicy(IResourceValidator validator, Object appContext, String path, String url) { - if (content.has("validate")) - return ReferenceValidationPolicy.valueOf(content.get("validate").getAsString()); + public ReferenceValidationPolicy policyForReference(IResourceValidator validator, Object appContext, String path, String url) { + if (content.has("validateReference")) + return ReferenceValidationPolicy.valueOf(content.get("validateReference").getAsString()); else return ReferenceValidationPolicy.IGNORE; } + @Override + public ContainedReferenceValidationPolicy policyForContained(IResourceValidator validator, Object appContext, + String containerType, String containerId, + Element.SpecialElement containingResourceType, + String path, String url) { + if (content.has("validateContains")) + return ContainedReferenceValidationPolicy.valueOf(content.get("validateContains").getAsString()); + else + return ContainedReferenceValidationPolicy.CHECK_VALID; + } + @Override public boolean resolveURL(IResourceValidator validator, Object appContext, String path, String url, String type) throws IOException, FHIRException { return !url.contains("example.org") && !url.startsWith("http://hl7.org/fhir/invalid"); diff --git a/pom.xml b/pom.xml index ca6fa9907..81266af93 100644 --- a/pom.xml +++ b/pom.xml @@ -14,12 +14,12 @@ HAPI FHIR --> org.hl7.fhir.core -5.6.1-SNAPSHOT +5.6.2-SNAPSHOT pom 5.1.0 -1.1.77 +1.1.79-SNAPSHOT 5.7.1 1.7.1 3.0.0-M5