diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 1fea49ef9..84027fd66 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,8 +1,10 @@ Validator Fixes: +* better validation of external references. Note: this is a potentially significant change: things that were called ok before may not be now, and things that were not ok before may become so, depending on the interplay between this and auto-load, further work may be needed here +* Support better validation of version specific profiles in meta.profile. This may also find new errors that were not previously being found * Support auto-determination of the version of FHIR to use when using the java validator * auto-load packages from the package server when references to profiles etc are encountered -* Support better validation of version specific profiles in meta.profile * look for references inside other parameters in Parameters resource +* no validation for CanonicalResource.url (further work needed) Other Code changes: * Rendering: add rendering for Parameters resources @@ -14,5 +16,5 @@ Other Code changes: TODO before commit: * check version of contained resources -* review validation of CanonicalResource.url + diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/VersionUtilities.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/VersionUtilities.java index 544f83079..c17a684e5 100644 --- a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/VersionUtilities.java +++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/VersionUtilities.java @@ -1,24 +1,27 @@ package org.hl7.fhir.utilities; +import java.util.ArrayList; +import java.util.List; + import org.hl7.fhir.exceptions.FHIRException; import org.hl7.fhir.utilities.cache.NpmPackage; /* 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 + + * 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, + * 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 + * 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. @@ -29,13 +32,13 @@ import org.hl7.fhir.utilities.cache.NpmPackage; 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. - + */ public class VersionUtilities { - - + + public static class VersionURLInfo { private String version; private String url; @@ -163,7 +166,7 @@ public class VersionUtilities { public static String getMajMin(String version) { if (version == null) return null; - + if (Utilities.charCount(version, '.') == 1) { String[] p = version.split("\\."); return p[0]+"."+p[1]; @@ -256,4 +259,110 @@ public class VersionUtilities { return null; } + public static List getCanonicalResourceNames(String version) { + ArrayList res = new ArrayList(); + if (isR2Ver(version) || isR2BVer(version)) { + res.add("ValueSet"); + res.add("ConceptMap"); + res.add("NamingSystem"); + res.add("StructureDefinition"); + res.add("DataElement"); + res.add("Conformance"); + res.add("OperationDefinition"); + res.add("SearchParameter"); + res.add("ImplementationGuide"); + res.add("TestScript"); + } + if (isR3Ver(version)) { + res.add("CapabilityStatement"); + res.add("StructureDefinition"); + res.add("ImplementationGuide"); + res.add("SearchParameter"); + res.add("MessageDefinition"); + res.add("OperationDefinition"); + res.add("CompartmentDefinition"); + res.add("StructureMap"); + res.add("GraphDefinition"); + res.add("DataElement"); + res.add("CodeSystem"); + res.add("ValueSet"); + res.add("ConceptMap"); + res.add("ExpansionProfile"); + res.add("Questionnaire"); + res.add("ActivityDefinition"); + res.add("ServiceDefinition"); + res.add("PlanDefinition"); + res.add("Measure"); + res.add("TestScript"); + + } + if (isR4Ver(version)) { + + res.add("ActivityDefinition"); + res.add("CapabilityStatement"); + res.add("ChargeItemDefinition"); + res.add("CodeSystem"); + res.add("CompartmentDefinition"); + res.add("ConceptMap"); + res.add("EffectEvidenceSynthesis"); + res.add("EventDefinition"); + res.add("Evidence"); + res.add("EvidenceVariable"); + res.add("ExampleScenario"); + res.add("GraphDefinition"); + res.add("ImplementationGuide"); + res.add("Library"); + res.add("Measure"); + res.add("MessageDefinition"); + res.add("NamingSystem"); + res.add("OperationDefinition"); + res.add("PlanDefinition"); + res.add("Questionnaire"); + res.add("ResearchDefinition"); + res.add("ResearchElementDefinition"); + res.add("RiskEvidenceSynthesis"); + res.add("SearchParameter"); + res.add("StructureDefinition"); + res.add("StructureMap"); + res.add("TerminologyCapabilities"); + res.add("TestScript"); + res.add("ValueSet"); + } + + if (isR5Ver(version)) { + + res.add("ActivityDefinition"); + res.add("CapabilityStatement"); + res.add("CapabilityStatement2"); + res.add("ChargeItemDefinition"); + res.add("Citation"); + res.add("CodeSystem"); + res.add("CompartmentDefinition"); + res.add("ConceptMap"); + res.add("ConditionDefinition"); + res.add("EventDefinition"); + res.add("Evidence"); + res.add("EvidenceReport"); + res.add("EvidenceVariable"); + res.add("ExampleScenario"); + res.add("GraphDefinition"); + res.add("ImplementationGuide"); + res.add("Library"); + res.add("Measure"); + res.add("MessageDefinition"); + res.add("NamingSystem"); + res.add("OperationDefinition"); + res.add("PlanDefinition"); + res.add("Questionnaire"); + res.add("SearchParameter"); + res.add("StructureDefinition"); + res.add("StructureMap"); + res.add("TerminologyCapabilities"); + res.add("TestScript"); + res.add("ValueSet"); + + } + return res; + } + } \ No newline at end of file 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 b2d890072..554bded5a 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 @@ -1854,15 +1854,19 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat rule(errors, IssueType.INVALID, e.line(), e.col(), path, url.startsWith("#") || Utilities.isAbsoluteUrl(url), I18nConstants.TYPE_SPECIFIC_CHECKS_CANONICAL_ABSOLUTE, url); } - // now, do we check the URI target? - if (fetcher != null) { - boolean found; - try { - found = isDefinitionURL(url) || (allowExamples && (url.contains("example.org") || url.contains("acme.com")) || url.contains("acme.org")) || (url.startsWith("http://hl7.org/fhir/tools")) || fetcher.resolveURL(appContext, path, url); - } catch (IOException e1) { - found = false; + if (isCanonicalURLElement(e)) { + // for now, no validation. Need to think about authority. + } else { + // now, do we check the URI target? + if (fetcher != null) { + boolean found; + try { + found = isDefinitionURL(url) || (allowExamples && (url.contains("example.org") || url.contains("acme.com")) || url.contains("acme.org")) || (url.startsWith("http://hl7.org/fhir/tools")) || fetcher.resolveURL(appContext, path, url); + } catch (IOException e1) { + found = false; + } + rule(errors, IssueType.INVALID, e.line(), e.col(), path, found, I18nConstants.TYPE_SPECIFIC_CHECKS_DT_URL_RESOLVE, url); } - rule(errors, IssueType.INVALID, e.line(), e.col(), path, found, I18nConstants.TYPE_SPECIFIC_CHECKS_DT_URL_RESOLVE, url); } } if (type.equals(ID)) { @@ -2009,6 +2013,24 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat // for nothing to check } + private boolean isCanonicalURLElement(Element e) { + if (e.getProperty() == null || e.getProperty().getDefinition() == null) { + return false; + } + String path = e.getProperty().getDefinition().getBase().getPath(); + if (path == null) { + return false; + } + String[] p = path.split("\\."); + if (p.length != 2) { + return false; + } + if (!"url".equals(p[1])) { + return false; + } + return Utilities.existsInList(p[0], VersionUtilities.getCanonicalResourceNames(context.getVersion())); + } + private boolean containsHtmlTags(String cnt) { int i = cnt.indexOf("<"); while (i > -1) { diff --git a/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/validation/tests/ValidationTestSuite.java b/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/validation/tests/ValidationTestSuite.java index e1bd5dece..f9af15a9c 100644 --- a/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/validation/tests/ValidationTestSuite.java +++ b/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/validation/tests/ValidationTestSuite.java @@ -457,7 +457,7 @@ public class ValidationTestSuite implements IEvaluationContext, IValidatorResour @Override public boolean resolveURL(Object appContext, String path, String url) throws IOException, FHIRException { - return !url.contains("example.org"); + return !url.contains("example.org") && !url.startsWith("http://hl7.org/fhir/invalid"); } @Override