Add -allow-example-urls option to the validator

This commit is contained in:
Grahame Grieve 2021-06-02 17:45:50 +10:00
parent e1f29ff29d
commit a371f5fe3e
13 changed files with 82 additions and 45 deletions

View File

@ -4,3 +4,5 @@
* add medication conversion from dstu2 to r4 * add medication conversion from dstu2 to r4
* Adding Maven exec to test validation cli jar * Adding Maven exec to test validation cli jar
* Validation of cardinality on address-line elements containing pattern elements fixed * Validation of cardinality on address-line elements containing pattern elements fixed
* Ensure that validator creates errors on example urls by default
* Add -allow-example-urls option to the validator

View File

@ -504,7 +504,7 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
cs = codeSystems.get(system); cs = codeSystems.get(system);
} }
if (cs == null && locator != null) { if (cs == null && locator != null) {
locator.findResource(system); locator.findResource(this, system);
synchronized (lock) { synchronized (lock) {
cs = codeSystems.get(system); cs = codeSystems.get(system);
} }

View File

@ -171,7 +171,7 @@ public interface IWorkerContext {
} }
public interface ICanonicalResourceLocator { public interface ICanonicalResourceLocator {
void findResource(String url); // if it can be found, put it in the context void findResource(Object caller, String url); // if it can be found, put it in the context
} }
public interface IContextResourceLoader { public interface IContextResourceLoader {

View File

@ -107,11 +107,11 @@ public interface IResourceValidator {
public interface IValidatorResourceFetcher { public interface IValidatorResourceFetcher {
Element fetch(Object appContext, String url) throws FHIRFormatError, DefinitionException, FHIRException, IOException; Element fetch(IResourceValidator validator, Object appContext, String url) throws FHIRFormatError, DefinitionException, FHIRException, IOException;
ReferenceValidationPolicy validationPolicy(Object appContext, String path, String url); ReferenceValidationPolicy validationPolicy(IResourceValidator validator, Object appContext, String path, String url);
boolean resolveURL(Object appContext, String path, String url, String type) throws IOException, FHIRException; boolean resolveURL(IResourceValidator validator, Object appContext, String path, String url, String type) throws IOException, FHIRException;
byte[] fetchRaw(String url) throws MalformedURLException, IOException; // for attachment checking byte[] fetchRaw(IResourceValidator validator, String url) throws MalformedURLException, IOException; // for attachment checking
IValidatorResourceFetcher setLocale(Locale locale); IValidatorResourceFetcher setLocale(Locale locale);
@ -126,7 +126,7 @@ public interface IResourceValidator {
* @return an R5 version of the resource * @return an R5 version of the resource
* @throws URISyntaxException * @throws URISyntaxException
*/ */
CanonicalResource fetchCanonicalResource(String url) 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. * 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.
@ -136,7 +136,7 @@ public interface IResourceValidator {
* @param url * @param url
* @return * @return
*/ */
boolean fetchesCanonicalResource(String url); boolean fetchesCanonicalResource(IResourceValidator validator, String url);
} }
public enum BestPracticeWarningLevel { public enum BestPracticeWarningLevel {

View File

@ -501,6 +501,7 @@ public class I18nConstants {
public static final String TYPE_SPECIFIC_CHECKS_DT_URI_UUID = "Type_Specific_Checks_DT_URI_UUID"; public static final String TYPE_SPECIFIC_CHECKS_DT_URI_UUID = "Type_Specific_Checks_DT_URI_UUID";
public static final String TYPE_SPECIFIC_CHECKS_DT_URI_WS = "Type_Specific_Checks_DT_URI_WS"; public static final String TYPE_SPECIFIC_CHECKS_DT_URI_WS = "Type_Specific_Checks_DT_URI_WS";
public static final String TYPE_SPECIFIC_CHECKS_DT_URL_RESOLVE = "Type_Specific_Checks_DT_URL_Resolve"; public static final String TYPE_SPECIFIC_CHECKS_DT_URL_RESOLVE = "Type_Specific_Checks_DT_URL_Resolve";
public static final String TYPE_SPECIFIC_CHECKS_DT_URL_EXAMPLE = "TYPE_SPECIFIC_CHECKS_DT_URL_EXAMPLE";
public static final String TYPE_SPECIFIC_CHECKS_DT_CANONICAL_TYPE = "TYPE_SPECIFIC_CHECKS_DT_CANONICAL_TYPE"; public static final String TYPE_SPECIFIC_CHECKS_DT_CANONICAL_TYPE = "TYPE_SPECIFIC_CHECKS_DT_CANONICAL_TYPE";
public static final String TYPE_SPECIFIC_CHECKS_DT_CANONICAL_RESOLVE = "TYPE_SPECIFIC_CHECKS_DT_CANONICAL_RESOLVE"; public static final String TYPE_SPECIFIC_CHECKS_DT_CANONICAL_RESOLVE = "TYPE_SPECIFIC_CHECKS_DT_CANONICAL_RESOLVE";
public static final String TYPE_SPECIFIC_CHECKS_DT_UUID_STRAT = "Type_Specific_Checks_DT_UUID_Strat"; public static final String TYPE_SPECIFIC_CHECKS_DT_UUID_STRAT = "Type_Specific_Checks_DT_UUID_Strat";

View File

@ -654,3 +654,4 @@ BUNDLE_SEARCH_ENTRY_WRONG_RESOURCE_TYPE_NO_MODE = This is not a matching resourc
BUNDLE_SEARCH_NO_MODE = SearchSet bundles should have search modes on the entries BUNDLE_SEARCH_NO_MODE = SearchSet bundles should have search modes on the entries
INV_FAILED = Rule {0} Failed INV_FAILED = Rule {0} Failed
PATTERN_CHECK_STRING = The pattern [{0}] defined in the profile {1} not found. Issues: {2} PATTERN_CHECK_STRING = The pattern [{0}] defined in the profile {1} not found. Issues: {2}
TYPE_SPECIFIC_CHECKS_DT_URL_EXAMPLE = Example URLs are not allowed in this context ({0})

View File

@ -26,6 +26,7 @@ import org.hl7.fhir.r5.renderers.utils.RenderingContext;
import org.hl7.fhir.r5.renderers.utils.RenderingContext.ResourceRendererMode; import org.hl7.fhir.r5.renderers.utils.RenderingContext.ResourceRendererMode;
import org.hl7.fhir.r5.utils.EOperationOutcome; import org.hl7.fhir.r5.utils.EOperationOutcome;
import org.hl7.fhir.r5.utils.FHIRPathEngine; 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.IResourceValidator.*;
import org.hl7.fhir.r5.utils.ToolingExtensions; import org.hl7.fhir.r5.utils.ToolingExtensions;
import org.hl7.fhir.r5.utils.structuremap.StructureMapUtilities; import org.hl7.fhir.r5.utils.structuremap.StructureMapUtilities;
@ -141,6 +142,7 @@ public class ValidationEngine implements IValidatorResourceFetcher, IPackageInst
@Getter @Setter private boolean noExtensibleBindingMessages; @Getter @Setter private boolean noExtensibleBindingMessages;
@Getter @Setter private boolean securityChecks; @Getter @Setter private boolean securityChecks;
@Getter @Setter private boolean crumbTrails; @Getter @Setter private boolean crumbTrails;
@Getter @Setter private boolean allowExampleUrls;
@Getter @Setter private Locale locale; @Getter @Setter private Locale locale;
@Getter @Setter private List<ImplementationGuide> igs = new ArrayList<>(); @Getter @Setter private List<ImplementationGuide> igs = new ArrayList<>();
@Getter @Setter private boolean showTimes; @Getter @Setter private boolean showTimes;
@ -486,6 +488,7 @@ public class ValidationEngine implements IValidatorResourceFetcher, IPackageInst
validator.setNoExtensibleWarnings(noExtensibleBindingMessages); validator.setNoExtensibleWarnings(noExtensibleBindingMessages);
validator.setSecurityChecks(securityChecks); validator.setSecurityChecks(securityChecks);
validator.setCrumbTrails(crumbTrails); validator.setCrumbTrails(crumbTrails);
validator.setAllowExamples(allowExampleUrls);
validator.getContext().setLocale(locale); validator.getContext().setLocale(locale);
validator.setFetcher(this); validator.setFetcher(this);
validator.getImplementationGuides().addAll(igs); validator.getImplementationGuides().addAll(igs);
@ -678,7 +681,7 @@ public class ValidationEngine implements IValidatorResourceFetcher, IPackageInst
} }
@Override @Override
public byte[] fetchRaw(String source) throws IOException { public byte[] fetchRaw(IResourceValidator validator, String source) throws IOException {
URL url = new URL(source); URL url = new URL(source);
URLConnection c = url.openConnection(); URLConnection c = url.openConnection();
return TextFile.streamToBytes(c.getInputStream()); return TextFile.streamToBytes(c.getInputStream());
@ -695,19 +698,19 @@ public class ValidationEngine implements IValidatorResourceFetcher, IPackageInst
} }
@Override @Override
public Element fetch(Object appContext, String url) throws FHIRException, IOException { public Element fetch(IResourceValidator validator, Object appContext, String url) throws FHIRException, IOException {
Resource resource = context.fetchResource(Resource.class, url); Resource resource = context.fetchResource(Resource.class, url);
if (resource != null) { if (resource != null) {
return new ObjectConverter(context).convert(resource); return new ObjectConverter(context).convert(resource);
} }
if (fetcher != null) { if (fetcher != null) {
return fetcher.fetch(appContext, url); return fetcher.fetch(validator, appContext, url);
} }
return null; return null;
} }
@Override @Override
public ReferenceValidationPolicy validationPolicy(Object appContext, String path, String url) { public ReferenceValidationPolicy validationPolicy(IResourceValidator validator, Object appContext, String path, String url) {
Resource resource = context.fetchResource(StructureDefinition.class, url); Resource resource = context.fetchResource(StructureDefinition.class, url);
if (resource != null) { if (resource != null) {
return ReferenceValidationPolicy.CHECK_VALID; return ReferenceValidationPolicy.CHECK_VALID;
@ -715,14 +718,14 @@ public class ValidationEngine implements IValidatorResourceFetcher, IPackageInst
if (!(url.contains("hl7.org") || url.contains("fhir.org"))) { if (!(url.contains("hl7.org") || url.contains("fhir.org"))) {
return ReferenceValidationPolicy.IGNORE; return ReferenceValidationPolicy.IGNORE;
} else if (fetcher != null) { } else if (fetcher != null) {
return fetcher.validationPolicy(appContext, path, url); return fetcher.validationPolicy(validator, appContext, path, url);
} else { } else {
return ReferenceValidationPolicy.CHECK_EXISTS_AND_TYPE; return ReferenceValidationPolicy.CHECK_EXISTS_AND_TYPE;
} }
} }
@Override @Override
public boolean resolveURL(Object appContext, String path, String url, String type) throws IOException, FHIRException { public boolean resolveURL(IResourceValidator validator, Object appContext, String path, String url, String type) throws IOException, FHIRException {
if (!url.startsWith("http://") && !url.startsWith("https://")) { // ignore these if (!url.startsWith("http://") && !url.startsWith("https://")) { // ignore these
return true; return true;
} }
@ -735,9 +738,12 @@ public class ValidationEngine implements IValidatorResourceFetcher, IPackageInst
if (Utilities.existsInList(url, "http://loinc.org", "http://unitsofmeasure.org", "http://snomed.info/sct")) { if (Utilities.existsInList(url, "http://loinc.org", "http://unitsofmeasure.org", "http://snomed.info/sct")) {
return true; return true;
} }
if (url.contains("example.org") || url.contains("acme.com")) {
return false; // todo... how to access settings from here?
}
if (fetcher != null) { if (fetcher != null) {
try { try {
return fetcher.resolveURL(appContext, path, url, type); return fetcher.resolveURL(validator, appContext, path, url, type);
} catch (Exception e) { } catch (Exception e) {
return false; return false;
} }
@ -746,7 +752,7 @@ public class ValidationEngine implements IValidatorResourceFetcher, IPackageInst
} }
@Override @Override
public CanonicalResource fetchCanonicalResource(String url) throws URISyntaxException { public CanonicalResource fetchCanonicalResource(IResourceValidator validator, String url) throws URISyntaxException {
Resource res = context.fetchResource(Resource.class, url); Resource res = context.fetchResource(Resource.class, url);
if (res != null) { if (res != null) {
if (res instanceof CanonicalResource) { if (res instanceof CanonicalResource) {
@ -755,11 +761,11 @@ public class ValidationEngine implements IValidatorResourceFetcher, IPackageInst
return null; return null;
} }
} }
return fetcher != null ? fetcher.fetchCanonicalResource(url) : null; return fetcher != null ? fetcher.fetchCanonicalResource(validator, url) : null;
} }
@Override @Override
public boolean fetchesCanonicalResource(String url) { public boolean fetchesCanonicalResource(IResourceValidator validator, String url) {
return fetcher != null && fetcher.fetchesCanonicalResource(url); return fetcher != null && fetcher.fetchesCanonicalResource(validator, url);
} }
} }

View File

@ -83,6 +83,9 @@ public class CliContext {
@JsonProperty("crumbTrails") @JsonProperty("crumbTrails")
private boolean crumbTrails = false; private boolean crumbTrails = false;
@JsonProperty("allowExampleUrls")
private boolean allowExampleUrls = false;
@JsonProperty("showTimes") @JsonProperty("showTimes")
private boolean showTimes = false; private boolean showTimes = false;
@ -485,6 +488,14 @@ public class CliContext {
this.crumbTrails = crumbTrails; this.crumbTrails = crumbTrails;
} }
public boolean isAllowExampleUrls() {
return allowExampleUrls;
}
public void setAllowExampleUrls(boolean allowExampleUrls) {
this.allowExampleUrls = allowExampleUrls;
}
public boolean isShowTimes() { public boolean isShowTimes() {
return showTimes; return showTimes;
} }
@ -525,6 +536,7 @@ public class CliContext {
Objects.equals(profiles, that.profiles) && Objects.equals(profiles, that.profiles) &&
Objects.equals(sources, that.sources) && Objects.equals(sources, that.sources) &&
Objects.equals(crumbTrails, that.crumbTrails) && Objects.equals(crumbTrails, that.crumbTrails) &&
Objects.equals(allowExampleUrls, that.allowExampleUrls) &&
Objects.equals(showTimes, that.showTimes) && Objects.equals(showTimes, that.showTimes) &&
mode == that.mode && mode == that.mode &&
Objects.equals(locale, that.locale) && Objects.equals(locale, that.locale) &&
@ -533,7 +545,7 @@ public class CliContext {
@Override @Override
public int hashCode() { public int hashCode() {
return Objects.hash(doNative, anyExtensionsAllowed, hintAboutNonMustSupport, recursive, doDebug, assumeValidRestReferences, canDoNative, noInternalCaching, noExtensibleBindingMessages, noInvariants, wantInvariantsInMessages, map, output, htmlOutput, txServer, sv, txLog, mapLog, lang, fhirpath, snomedCT, targetVer, igs, questionnaireMode, profiles, sources, mode, locale, locations, crumbTrails, showTimes); return Objects.hash(doNative, anyExtensionsAllowed, hintAboutNonMustSupport, recursive, doDebug, assumeValidRestReferences, canDoNative, noInternalCaching, noExtensibleBindingMessages, noInvariants, wantInvariantsInMessages, map, output, htmlOutput, txServer, sv, txLog, mapLog, lang, fhirpath, snomedCT, targetVer, igs, questionnaireMode, profiles, sources, mode, locale, locations, crumbTrails, showTimes, allowExampleUrls);
} }
@Override @Override
@ -568,6 +580,7 @@ public class CliContext {
", mode=" + mode + ", mode=" + mode +
", securityChecks=" + securityChecks + ", securityChecks=" + securityChecks +
", crumbTrails=" + crumbTrails + ", crumbTrails=" + crumbTrails +
", allowExampleUrls=" + allowExampleUrls +
", showTimes=" + showTimes + ", showTimes=" + showTimes +
", locale='" + locale + '\'' + ", locale='" + locale + '\'' +
", locations=" + locations + ", locations=" + locations +

View File

@ -8,6 +8,7 @@ import org.hl7.fhir.r5.context.IWorkerContext.ICanonicalResourceLocator;
import org.hl7.fhir.r5.elementmodel.Element; import org.hl7.fhir.r5.elementmodel.Element;
import org.hl7.fhir.r5.model.CanonicalResource; import org.hl7.fhir.r5.model.CanonicalResource;
import org.hl7.fhir.r5.terminologies.TerminologyClient; 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.IValidatorResourceFetcher;
import org.hl7.fhir.r5.utils.IResourceValidator.ReferenceValidationPolicy; import org.hl7.fhir.r5.utils.IResourceValidator.ReferenceValidationPolicy;
import org.hl7.fhir.utilities.Utilities; import org.hl7.fhir.utilities.Utilities;
@ -45,17 +46,17 @@ public class StandAloneValidatorFetcher implements IValidatorResourceFetcher, IC
} }
@Override @Override
public Element fetch(Object appContext, String url) throws FHIRException { public Element fetch(IResourceValidator validator, Object appContext, String url) throws FHIRException {
throw new FHIRException("The URL '" + url + "' is not known to the FHIR validator, and has not been provided as part of the setup / parameters"); throw new FHIRException("The URL '" + url + "' is not known to the FHIR validator, and has not been provided as part of the setup / parameters");
} }
@Override @Override
public ReferenceValidationPolicy validationPolicy(Object appContext, String path, String url) { public ReferenceValidationPolicy validationPolicy(IResourceValidator validator, Object appContext, String path, String url) {
return ReferenceValidationPolicy.CHECK_TYPE_IF_EXISTS; return ReferenceValidationPolicy.CHECK_TYPE_IF_EXISTS;
} }
@Override @Override
public boolean resolveURL(Object appContext, String path, String url, String type) throws IOException, FHIRException { public boolean resolveURL(IResourceValidator validator, Object appContext, String path, String url, String type) throws IOException, FHIRException {
if (!Utilities.isAbsoluteUrl(url)) { if (!Utilities.isAbsoluteUrl(url)) {
return false; return false;
} }
@ -213,7 +214,7 @@ public class StandAloneValidatorFetcher implements IValidatorResourceFetcher, IC
} }
@Override @Override
public byte[] fetchRaw(String url) throws MalformedURLException, IOException { public byte[] fetchRaw(IResourceValidator validator, String url) throws MalformedURLException, IOException {
throw new FHIRException("The URL '" + url + "' is not known to the FHIR validator, and has not been provided as part of the setup / parameters"); throw new FHIRException("The URL '" + url + "' is not known to the FHIR validator, and has not been provided as part of the setup / parameters");
} }
@ -225,7 +226,7 @@ public class StandAloneValidatorFetcher implements IValidatorResourceFetcher, IC
} }
@Override @Override
public CanonicalResource fetchCanonicalResource(String url) throws URISyntaxException { public CanonicalResource fetchCanonicalResource(IResourceValidator validator, String url) throws URISyntaxException {
String[] p = url.split("\\/"); String[] p = url.split("\\/");
String root = getRoot(p, url); String root = getRoot(p, url);
if (root != null) { if (root != null) {
@ -247,14 +248,14 @@ public class StandAloneValidatorFetcher implements IValidatorResourceFetcher, IC
} }
@Override @Override
public boolean fetchesCanonicalResource(String url) { public boolean fetchesCanonicalResource(IResourceValidator validator, String url) {
return true; return true;
} }
@Override @Override
public void findResource(String url) { public void findResource(Object validator, String url) {
try { try {
resolveURL(null, null, url, null); resolveURL((IResourceValidator) validator, null, null, url, null);
} catch (Exception e) { } catch (Exception e) {
} }
} }

View File

@ -248,6 +248,7 @@ public class ValidationService {
validator.setSecurityChecks(cliContext.isSecurityChecks()); validator.setSecurityChecks(cliContext.isSecurityChecks());
validator.setCrumbTrails(cliContext.isCrumbTrails()); validator.setCrumbTrails(cliContext.isCrumbTrails());
validator.setShowTimes(cliContext.isShowTimes()); validator.setShowTimes(cliContext.isShowTimes());
validator.setAllowExampleUrls(cliContext.isAllowExampleUrls());
StandAloneValidatorFetcher fetcher = new StandAloneValidatorFetcher(validator.getPcm(), validator.getContext(), validator); StandAloneValidatorFetcher fetcher = new StandAloneValidatorFetcher(validator.getPcm(), validator.getContext(), validator);
validator.setFetcher(fetcher); validator.setFetcher(fetcher);
validator.getContext().setLocator(fetcher); validator.getContext().setLocator(fetcher);

View File

@ -57,6 +57,7 @@ public class Params {
public static final String SECURITY_CHECKS = "-security-checks"; public static final String SECURITY_CHECKS = "-security-checks";
public static final String CRUMB_TRAIL = "-crumb-trails"; public static final String CRUMB_TRAIL = "-crumb-trails";
public static final String SHOW_TIMES = "-show-times"; public static final String SHOW_TIMES = "-show-times";
public static final String ALLOW_EXAMPLE_URLS = "-allow-example-urls";
/** /**
* Checks the list of passed in params to see if it contains the passed in param. * Checks the list of passed in params to see if it contains the passed in param.
@ -182,6 +183,15 @@ public class Params {
cliContext.setSecurityChecks(true); cliContext.setSecurityChecks(true);
} else if (args[i].equals(CRUMB_TRAIL)) { } else if (args[i].equals(CRUMB_TRAIL)) {
cliContext.setCrumbTrails(true); cliContext.setCrumbTrails(true);
} else if (args[i].equals(ALLOW_EXAMPLE_URLS)) {
String bl = args[++i];
if ("true".equals(bl)) {
cliContext.setAllowExampleUrls(true);
} else if ("false".equals(bl)) {
cliContext.setAllowExampleUrls(false);
} else {
throw new Error("Value for "+ALLOW_EXAMPLE_URLS+" not understood: "+bl);
}
} else if (args[i].equals(SHOW_TIMES)) { } else if (args[i].equals(SHOW_TIMES)) {
cliContext.setShowTimes(true); cliContext.setShowTimes(true);
} else if (args[i].equals(SCAN)) { } else if (args[i].equals(SCAN)) {

View File

@ -267,7 +267,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
return externalHostServices.resolveReference(c.getAppContext(), url, refContext); return externalHostServices.resolveReference(c.getAppContext(), url, refContext);
} else if (fetcher != null) { } else if (fetcher != null) {
try { try {
return fetcher.fetch(c.getAppContext(), url); return fetcher.fetch(InstanceValidator.this, c.getAppContext(), url);
} catch (IOException e) { } catch (IOException e) {
throw new FHIRException(e); throw new FHIRException(e);
} }
@ -2007,13 +2007,13 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
boolean found; boolean found;
try { try {
found = isDefinitionURL(url) || (allowExamples && (url.contains("example.org") || url.contains("acme.com")) || url.contains("acme.org")) || (url.startsWith("http://hl7.org/fhir/tools")) || found = isDefinitionURL(url) || (allowExamples && (url.contains("example.org") || url.contains("acme.com")) || url.contains("acme.org")) || (url.startsWith("http://hl7.org/fhir/tools")) ||
SpecialExtensions.isKnownExtension(url) || isXverUrl(url) || fetcher.resolveURL(appContext, path, url, type); SpecialExtensions.isKnownExtension(url) || isXverUrl(url) || fetcher.resolveURL(this, appContext, path, url, type);
} catch (IOException e1) { } catch (IOException e1) {
found = false; found = false;
} }
if (!found) { if (!found) {
if (type.equals("canonical")) { if (type.equals("canonical")) {
ReferenceValidationPolicy rp = fetcher.validationPolicy(appContext, path, url); ReferenceValidationPolicy rp = fetcher.validationPolicy(this, appContext, path, url);
if (rp == ReferenceValidationPolicy.CHECK_EXISTS || rp == ReferenceValidationPolicy.CHECK_EXISTS_AND_TYPE) { 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); rule(errors, IssueType.INVALID, e.line(), e.col(), path, found, I18nConstants.TYPE_SPECIFIC_CHECKS_DT_CANONICAL_RESOLVE, url);
} else { } else {
@ -2022,16 +2022,18 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
} else { } else {
if (url.contains("hl7.org") || url.contains("fhir.org")) { if (url.contains("hl7.org") || url.contains("fhir.org")) {
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);
} else if (url.contains("example.org") || url.contains("acme.com")) {
rule(errors, IssueType.INVALID, e.line(), e.col(), path, found, I18nConstants.TYPE_SPECIFIC_CHECKS_DT_URL_EXAMPLE, url);
} else { } else {
warning(errors, IssueType.INVALID, e.line(), e.col(), path, found, I18nConstants.TYPE_SPECIFIC_CHECKS_DT_URL_RESOLVE, url); warning(errors, IssueType.INVALID, e.line(), e.col(), path, found, I18nConstants.TYPE_SPECIFIC_CHECKS_DT_URL_RESOLVE, url);
} }
} }
} else { } else {
if (type.equals("canonical")) { if (type.equals("canonical")) {
ReferenceValidationPolicy rp = fetcher.validationPolicy(appContext, path, url); ReferenceValidationPolicy rp = fetcher.validationPolicy(this, appContext, path, url);
if (rp == ReferenceValidationPolicy.CHECK_EXISTS_AND_TYPE || rp == ReferenceValidationPolicy.CHECK_TYPE_IF_EXISTS || rp == ReferenceValidationPolicy.CHECK_VALID) { if (rp == ReferenceValidationPolicy.CHECK_EXISTS_AND_TYPE || rp == ReferenceValidationPolicy.CHECK_TYPE_IF_EXISTS || rp == ReferenceValidationPolicy.CHECK_VALID) {
try { try {
Resource r = fetcher.fetchCanonicalResource(url); Resource r = fetcher.fetchCanonicalResource(this, url);
if (r == null) { if (r == null) {
rule(errors, IssueType.INVALID, e.line(), e.col(), path, found, I18nConstants.TYPE_SPECIFIC_CHECKS_DT_CANONICAL_RESOLVE, url); rule(errors, IssueType.INVALID, e.line(), e.col(), path, found, I18nConstants.TYPE_SPECIFIC_CHECKS_DT_CANONICAL_RESOLVE, url);
} else if (rule(errors, IssueType.INVALID, e.line(), e.col(), path, isCorrectCanonicalType(r, context), I18nConstants.TYPE_SPECIFIC_CHECKS_DT_CANONICAL_TYPE, url, r.fhirType(), listExpectedCanonicalTypes(context))) { } else if (rule(errors, IssueType.INVALID, e.line(), e.col(), path, isCorrectCanonicalType(r, context), I18nConstants.TYPE_SPECIFIC_CHECKS_DT_CANONICAL_TYPE, url, r.fhirType(), listExpectedCanonicalTypes(context))) {
@ -2546,7 +2548,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
if (fetcher == null) { if (fetcher == null) {
fetchError = context.formatMessage(I18nConstants.TYPE_SPECIFIC_CHECKS_DT_ATT_NO_FETCHER, url); fetchError = context.formatMessage(I18nConstants.TYPE_SPECIFIC_CHECKS_DT_ATT_NO_FETCHER, url);
} else { } else {
byte[] cnt = fetcher.fetchRaw(url); byte[] cnt = fetcher.fetchRaw(this, url);
size = cnt.length; size = cnt.length;
} }
} else if (url.startsWith("file:")) { } else if (url.startsWith("file:")) {
@ -2609,7 +2611,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
refType = "bundled"; refType = "bundled";
} }
} }
ReferenceValidationPolicy pol = refType.equals("contained") || refType.equals("bundled") ? ReferenceValidationPolicy.CHECK_VALID : fetcher == null ? ReferenceValidationPolicy.IGNORE : fetcher.validationPolicy(hostContext.getAppContext(), path, ref); ReferenceValidationPolicy pol = refType.equals("contained") || refType.equals("bundled") ? ReferenceValidationPolicy.CHECK_VALID : fetcher == null ? ReferenceValidationPolicy.IGNORE : fetcher.validationPolicy(this, hostContext.getAppContext(), path, ref);
if (pol.checkExists()) { if (pol.checkExists()) {
if (we == null) { if (we == null) {
@ -2622,7 +2624,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
ext = fetchCache.get(ref); ext = fetchCache.get(ref);
} else { } else {
try { try {
ext = fetcher.fetch(hostContext.getAppContext(), ref); ext = fetcher.fetch(this, hostContext.getAppContext(), ref);
} catch (IOException e) { } catch (IOException e) {
throw new FHIRException(e); throw new FHIRException(e);
} }
@ -3421,7 +3423,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
if (fetchCache.containsKey(ref)) { if (fetchCache.containsKey(ref)) {
return fetchCache.get(ref); return fetchCache.get(ref);
} else { } else {
Element res = fetcher.fetch(appContext, ref); Element res = fetcher.fetch(this, appContext, ref);
setParents(res); setParents(res);
fetchCache.put(ref, res); fetchCache.put(ref, res);
return res; return res;
@ -3960,11 +3962,11 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
// we'll try fetching it directly from it's source, but this is likely to fail later even if the resolution succeeds // we'll try fetching it directly from it's source, but this is likely to fail later even if the resolution succeeds
if (fetcher == null) { if (fetcher == null) {
warning(errors, IssueType.STRUCTURE, element.line(), element.col(), stack.getLiteralPath() + ".meta.profile[" + i + "]", false, I18nConstants.VALIDATION_VAL_PROFILE_UNKNOWN, profile.primitiveValue()); warning(errors, IssueType.STRUCTURE, element.line(), element.col(), stack.getLiteralPath() + ".meta.profile[" + i + "]", false, I18nConstants.VALIDATION_VAL_PROFILE_UNKNOWN, profile.primitiveValue());
} else if (!fetcher.fetchesCanonicalResource(profile.primitiveValue())) { } else if (!fetcher.fetchesCanonicalResource(this, profile.primitiveValue())) {
warning(errors, IssueType.STRUCTURE, element.line(), element.col(), stack.getLiteralPath() + ".meta.profile[" + i + "]", false, I18nConstants.VALIDATION_VAL_PROFILE_UNKNOWN_NOT_POLICY, profile.primitiveValue()); warning(errors, IssueType.STRUCTURE, element.line(), element.col(), stack.getLiteralPath() + ".meta.profile[" + i + "]", false, I18nConstants.VALIDATION_VAL_PROFILE_UNKNOWN_NOT_POLICY, profile.primitiveValue());
} else { } else {
try { try {
sd = (StructureDefinition) fetcher.fetchCanonicalResource(profile.primitiveValue()); sd = (StructureDefinition) fetcher.fetchCanonicalResource(this, profile.primitiveValue());
} catch (Exception e) { } catch (Exception e) {
warning(errors, IssueType.STRUCTURE, element.line(), element.col(), stack.getLiteralPath() + ".meta.profile[" + i + "]", false, I18nConstants.VALIDATION_VAL_PROFILE_UNKNOWN_ERROR, profile.primitiveValue(), e.getMessage()); warning(errors, IssueType.STRUCTURE, element.line(), element.col(), stack.getLiteralPath() + ".meta.profile[" + i + "]", false, I18nConstants.VALIDATION_VAL_PROFILE_UNKNOWN_ERROR, profile.primitiveValue(), e.getMessage());
} }

View File

@ -463,7 +463,7 @@ public class ValidationTests implements IEvaluationContext, IValidatorResourceFe
} }
@Override @Override
public Element fetch(Object appContext, String url) throws FHIRFormatError, DefinitionException, IOException, FHIRException { public Element fetch(IResourceValidator validator, Object appContext, String url) throws FHIRFormatError, DefinitionException, IOException, FHIRException {
Element res = null; Element res = null;
if (url.equals("Patient/test")) { if (url.equals("Patient/test")) {
res = new ObjectConverter(TestingUtilities.context(version)).convert(new Patient()); res = new ObjectConverter(TestingUtilities.context(version)).convert(new Patient());
@ -484,7 +484,7 @@ public class ValidationTests implements IEvaluationContext, IValidatorResourceFe
} }
@Override @Override
public ReferenceValidationPolicy validationPolicy(Object appContext, String path, String url) { public ReferenceValidationPolicy validationPolicy(IResourceValidator validator, Object appContext, String path, String url) {
if (content.has("validate")) if (content.has("validate"))
return ReferenceValidationPolicy.valueOf(content.get("validate").getAsString()); return ReferenceValidationPolicy.valueOf(content.get("validate").getAsString());
else else
@ -492,7 +492,7 @@ public class ValidationTests implements IEvaluationContext, IValidatorResourceFe
} }
@Override @Override
public boolean resolveURL(Object appContext, String path, String url, String type) throws IOException, FHIRException { 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"); return !url.contains("example.org") && !url.startsWith("http://hl7.org/fhir/invalid");
} }
@ -529,19 +529,19 @@ public class ValidationTests implements IEvaluationContext, IValidatorResourceFe
} }
@Override @Override
public byte[] fetchRaw(String source) throws MalformedURLException, IOException { public byte[] fetchRaw(IResourceValidator validator, String source) throws MalformedURLException, IOException {
URL url = new URL(source); URL url = new URL(source);
URLConnection c = url.openConnection(); URLConnection c = url.openConnection();
return TextFile.streamToBytes(c.getInputStream()); return TextFile.streamToBytes(c.getInputStream());
} }
@Override @Override
public CanonicalResource fetchCanonicalResource(String url) { public CanonicalResource fetchCanonicalResource(IResourceValidator validator, String url) {
return null; return null;
} }
@Override @Override
public boolean fetchesCanonicalResource(String url) { public boolean fetchesCanonicalResource(IResourceValidator validator, String url) {
return false; return false;
} }
} }