Add on the fly retrieval of profiles in the validator, and fix bug where validator reported 'not done yet' for invalid contained references.

This commit is contained in:
Grahame Grieve 2020-11-27 10:34:43 +11:00
parent 34d29ed614
commit 624ce59c83
15 changed files with 253 additions and 25 deletions

View File

@ -36,6 +36,7 @@ import java.net.URISyntaxException;
import org.hl7.fhir.r5.model.FhirPublication;
import org.hl7.fhir.r5.terminologies.TerminologyClient;
import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.VersionUtilities;
public class TerminologyClientFactory {
@ -53,6 +54,20 @@ public class TerminologyClientFactory {
}
}
public static TerminologyClient makeClient(String url, String v) throws URISyntaxException {
if (v == null)
return new TerminologyClientR5(checkEndsWith("/r4", url));
v = VersionUtilities.getMajMin(v);
switch (v) {
case "1.0": return new TerminologyClientR2(checkEndsWith("/r2", url));
case "1.4": return new TerminologyClientR3(checkEndsWith("/r3", url)); // r3 is the least worst match
case "3.0": return new TerminologyClientR3(checkEndsWith("/r3", url));
case "4.0": return new TerminologyClientR4(checkEndsWith("/r4", url));
case "4.5": return new TerminologyClientR5(checkEndsWith("/r4", url)); // r4 for now, since the terminology is currently the same
default: throw new Error("The version "+v.toString()+" is not currently supported");
}
}
private static String checkEndsWith(String term, String url) {
if (url.endsWith(term))
return url;

View File

@ -36,15 +36,19 @@ import java.util.Map;
import org.hl7.fhir.convertors.VersionConvertor_10_50;
import org.hl7.fhir.convertors.VersionConvertor_40_50;
import org.hl7.fhir.dstu2.model.Resource;
import org.hl7.fhir.dstu2.utils.client.FHIRToolingClient;
import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.exceptions.TerminologyServiceException;
import org.hl7.fhir.r5.model.Bundle;
import org.hl7.fhir.r5.model.CanonicalResource;
import org.hl7.fhir.r5.model.CapabilityStatement;
import org.hl7.fhir.r5.model.Parameters;
import org.hl7.fhir.r5.model.TerminologyCapabilities;
import org.hl7.fhir.r5.model.ValueSet;
import org.hl7.fhir.r5.terminologies.TerminologyClient;
import org.hl7.fhir.utilities.ToolingClientLogger;
import org.hl7.fhir.utilities.Utilities;
public class TerminologyClientR2 implements TerminologyClient {
@ -124,5 +128,27 @@ public class TerminologyClientR2 implements TerminologyClient {
return (Bundle) VersionConvertor_10_50.convertResource(client.transaction((org.hl7.fhir.dstu2.model.Bundle) VersionConvertor_10_50.convertResource(batch)));
}
@Override
public CanonicalResource read(String type, String id) {
Class<Resource> t;
try {
t = (Class<Resource>) Class.forName("org.hl7.fhir.dstu2.model."+type);// todo: do we have to deal with any resource renaming? Use cases are limited...
} catch (ClassNotFoundException e) {
throw new FHIRException("Unable to fetch resources of type "+type+" in R2");
}
org.hl7.fhir.dstu2.model.Resource r2 = client.read(t, id);
if (r2 == null) {
throw new FHIRException("Unable to fetch resource "+Utilities.pathURL(getAddress(), type, id));
}
org.hl7.fhir.r5.model.Resource r5 = VersionConvertor_10_50.convertResource(r2);
if (r5 != null) {
throw new FHIRException("Unable to convert resource "+Utilities.pathURL(getAddress(), type, id)+" to R5 (internal representation)");
}
if (!(r5 instanceof CanonicalResource)) {
throw new FHIRException("Unable to convert resource "+Utilities.pathURL(getAddress(), type, id)+" to R5 canonical resource (internal representation)");
}
return (CanonicalResource) r5;
}
}

View File

@ -34,17 +34,21 @@ package org.hl7.fhir.convertors.txClient;
import java.net.URISyntaxException;
import java.util.Map;
import org.hl7.fhir.convertors.VersionConvertor_10_50;
import org.hl7.fhir.convertors.VersionConvertor_30_50;
import org.hl7.fhir.convertors.VersionConvertor_40_50;
import org.hl7.fhir.dstu3.model.Resource;
import org.hl7.fhir.dstu3.utils.client.FHIRToolingClient;
import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.r5.model.Bundle;
import org.hl7.fhir.r5.model.CanonicalResource;
import org.hl7.fhir.r5.model.CapabilityStatement;
import org.hl7.fhir.r5.model.Parameters;
import org.hl7.fhir.r5.model.TerminologyCapabilities;
import org.hl7.fhir.r5.model.ValueSet;
import org.hl7.fhir.r5.terminologies.TerminologyClient;
import org.hl7.fhir.utilities.ToolingClientLogger;
import org.hl7.fhir.utilities.Utilities;
public class TerminologyClientR3 implements TerminologyClient {
@ -124,5 +128,27 @@ public class TerminologyClientR3 implements TerminologyClient {
return (Bundle) VersionConvertor_30_50.convertResource(client.transaction((org.hl7.fhir.dstu3.model.Bundle) VersionConvertor_30_50.convertResource(batch, false)), false);
}
@Override
public CanonicalResource read(String type, String id) {
Class<Resource> t;
try {
t = (Class<Resource>) Class.forName("org.hl7.fhir.dstu3.model."+type);// todo: do we have to deal with any resource renaming? Use cases are limited...
} catch (ClassNotFoundException e) {
throw new FHIRException("Unable to fetch resources of type "+type+" in R2");
}
org.hl7.fhir.dstu3.model.Resource r3 = client.read(t, id);
if (r3 == null) {
throw new FHIRException("Unable to fetch resource "+Utilities.pathURL(getAddress(), type, id));
}
org.hl7.fhir.r5.model.Resource r5 = VersionConvertor_30_50.convertResource(r3, false);
if (r5 != null) {
throw new FHIRException("Unable to convert resource "+Utilities.pathURL(getAddress(), type, id)+" to R5 (internal representation)");
}
if (!(r5 instanceof CanonicalResource)) {
throw new FHIRException("Unable to convert resource "+Utilities.pathURL(getAddress(), type, id)+" to R5 canonical resource (internal representation)");
}
return (CanonicalResource) r5;
}
}

View File

@ -34,17 +34,21 @@ package org.hl7.fhir.convertors.txClient;
import java.net.URISyntaxException;
import java.util.Map;
import org.hl7.fhir.convertors.VersionConvertor_30_50;
import org.hl7.fhir.convertors.VersionConvertor_40_50;
import org.hl7.fhir.convertors.conv40_50.TerminologyCapabilities40_50;
import org.hl7.fhir.r4.model.Resource;
import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.r4.utils.client.FHIRToolingClient;
import org.hl7.fhir.r5.model.Bundle;
import org.hl7.fhir.r5.model.CanonicalResource;
import org.hl7.fhir.r5.model.CapabilityStatement;
import org.hl7.fhir.r5.model.Parameters;
import org.hl7.fhir.r5.model.TerminologyCapabilities;
import org.hl7.fhir.r5.model.ValueSet;
import org.hl7.fhir.r5.terminologies.TerminologyClient;
import org.hl7.fhir.utilities.ToolingClientLogger;
import org.hl7.fhir.utilities.Utilities;
public class TerminologyClientR4 implements TerminologyClient {
@ -124,4 +128,26 @@ public class TerminologyClientR4 implements TerminologyClient {
return (Bundle) VersionConvertor_40_50.convertResource(client.transaction((org.hl7.fhir.r4.model.Bundle) VersionConvertor_40_50.convertResource(batch)));
}
@Override
public CanonicalResource read(String type, String id) {
Class<Resource> t;
try {
t = (Class<Resource>) Class.forName("org.hl7.fhir.r4.model."+type);// todo: do we have to deal with any resource renaming? Use cases are limited...
} catch (ClassNotFoundException e) {
throw new FHIRException("Unable to fetch resources of type "+type+" in R2");
}
org.hl7.fhir.r4.model.Resource r4 = client.read(t, id);
if (r4 == null) {
throw new FHIRException("Unable to fetch resource "+Utilities.pathURL(getAddress(), type, id));
}
org.hl7.fhir.r5.model.Resource r5 = VersionConvertor_40_50.convertResource(r4);
if (r5 != null) {
throw new FHIRException("Unable to convert resource "+Utilities.pathURL(getAddress(), type, id)+" to R5 (internal representation)");
}
if (!(r5 instanceof CanonicalResource)) {
throw new FHIRException("Unable to convert resource "+Utilities.pathURL(getAddress(), type, id)+" to R5 canonical resource (internal representation)");
}
return (CanonicalResource) r5;
}
}

View File

@ -34,8 +34,11 @@ package org.hl7.fhir.convertors.txClient;
import java.net.URISyntaxException;
import java.util.Map;
import org.hl7.fhir.convertors.VersionConvertor_40_50;
import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.r5.model.Resource;
import org.hl7.fhir.r5.model.Bundle;
import org.hl7.fhir.r5.model.CanonicalResource;
import org.hl7.fhir.r5.model.CapabilityStatement;
import org.hl7.fhir.r5.model.CodeSystem;
import org.hl7.fhir.r5.model.Parameters;
@ -44,6 +47,7 @@ import org.hl7.fhir.r5.model.ValueSet;
import org.hl7.fhir.r5.terminologies.TerminologyClient;
import org.hl7.fhir.r5.utils.client.FHIRToolingClient;
import org.hl7.fhir.utilities.ToolingClientLogger;
import org.hl7.fhir.utilities.Utilities;
public class TerminologyClientR5 implements TerminologyClient {
@ -116,4 +120,22 @@ public class TerminologyClientR5 implements TerminologyClient {
return client.transaction(batch);
}
@Override
public CanonicalResource read(String type, String id) {
Class<Resource> t;
try {
t = (Class<Resource>) Class.forName("org.hl7.fhir.r5.model."+type);// todo: do we have to deal with any resource renaming? Use cases are limited...
} catch (ClassNotFoundException e) {
throw new FHIRException("Unable to fetch resources of type "+type+" in R5");
}
org.hl7.fhir.r5.model.Resource r5 = client.read(t, id);
if (r5 != null) {
throw new FHIRException("Unable to convert resource "+Utilities.pathURL(getAddress(), type, id)+" to R5 (internal representation)");
}
if (!(r5 instanceof CanonicalResource)) {
throw new FHIRException("Unable to convert resource "+Utilities.pathURL(getAddress(), type, id)+" to R5 canonical resource (internal representation)");
}
return (CanonicalResource) r5;
}
}

View File

@ -35,6 +35,7 @@ import java.util.Map;
import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.r5.model.Bundle;
import org.hl7.fhir.r5.model.CanonicalResource;
import org.hl7.fhir.r5.model.CapabilityStatement;
import org.hl7.fhir.r5.model.Parameters;
import org.hl7.fhir.r5.model.TerminologyCapabilities;
@ -54,4 +55,5 @@ public interface TerminologyClient {
public CapabilityStatement getCapabilitiesStatementQuick() throws FHIRException;
public Parameters lookupCode(Map<String, String> params) throws FHIRException;
public Bundle validateBatch(Bundle batch);
public CanonicalResource read(String type, String id);
}

View File

@ -34,6 +34,7 @@ package org.hl7.fhir.r5.utils;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.util.List;
import java.util.Locale;
@ -42,6 +43,7 @@ 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;
@ -102,6 +104,7 @@ public interface IResourceValidator {
void recordProfileUsage(StructureDefinition profile, Object appContext, Element element);
}
public interface IValidatorResourceFetcher {
Element fetch(Object appContext, String url) throws FHIRFormatError, DefinitionException, FHIRException, IOException;
@ -111,6 +114,29 @@ public interface IResourceValidator {
byte[] fetchRaw(String url) throws MalformedURLException, IOException; // for attachment checking
void 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(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(String url);
}
public enum BestPracticeWarningLevel {

View File

@ -1,5 +1,7 @@
package org.hl7.fhir.r5.utils.client;
import org.hl7.fhir.exceptions.FHIRException;
/*
Copyright (c) 2011+, HL7, Inc.
All rights reserved.
@ -151,7 +153,7 @@ public class FHIRToolingClient {
capabilities = (CapabilityStatement) client.issueGetResourceRequest(resourceAddress.resolveMetadataUri(true),
getPreferredResourceFormat(), "CapabilitiesStatement-Quick", TIMEOUT_NORMAL).getReference();
} catch (Exception e) {
handleException("An error has occurred while trying to fetch the server's conformance statement", e);
handleException("An error fetching the server's capability statement: "+e.getMessage(), e);
}
return capabilities;
}
@ -165,7 +167,7 @@ public class FHIRToolingClient {
throw new EFhirClientException("Server returned error code " + result.getHttpStatus(), (OperationOutcome) result.getPayload());
}
} catch (Exception e) {
handleException("An error has occurred while trying to read this resource", e);
throw new FHIRException(e);
}
return result.getPayload();
}

View File

@ -3,6 +3,7 @@ package org.hl7.fhir.r5.utils.client.network;
import kotlin.Pair;
import okhttp3.*;
import org.apache.commons.lang3.StringUtils;
import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.r5.formats.IParser;
import org.hl7.fhir.r5.formats.JsonParser;
import org.hl7.fhir.r5.formats.XmlParser;
@ -209,9 +210,9 @@ public class FhirRequestBuilder {
return new ResourceRequest<T>(resource, response.code(), getLocationHeader(response.headers()));
} catch (IOException e) {
e.printStackTrace();
throw new FHIRException(e);
}
return null;
}
public Bundle executeAsBatch() {

View File

@ -572,6 +572,8 @@ public class I18nConstants {
public static final String VALIDATION_VAL_PROFILE_THIS_VERSION_OK = "VALIDATION_VAL_PROFILE_THIS_VERSION_OK";
public static final String VALIDATION_VAL_PROFILE_THIS_VERSION_OTHER = "VALIDATION_VAL_PROFILE_THIS_VERSION_OTHER";
public static final String VALIDATION_VAL_PROFILE_UNKNOWN = "Validation_VAL_Profile_Unknown";
public static final String VALIDATION_VAL_PROFILE_UNKNOWN_NOT_POLICY = "VALIDATION_VAL_PROFILE_UNKNOWN_NOT_POLICY";
public static final String VALIDATION_VAL_PROFILE_UNKNOWN_ERROR = "VALIDATION_VAL_PROFILE_UNKNOWN_ERROR";
public static final String VALIDATION_VAL_PROFILE_WRONGTYPE = "Validation_VAL_Profile_WrongType";
public static final String VALIDATION_VAL_PROFILE_WRONGTYPE2 = "Validation_VAL_Profile_WrongType2";
public static final String VALIDATION_VAL_UNKNOWN_PROFILE = "Validation_VAL_Unknown_Profile";

View File

@ -223,7 +223,9 @@ Validation_VAL_Profile_NotAllowed = This element is not allowed by the profile {
Validation_VAL_Profile_NotSlice = This element does not match any known slice {0} and slicing is CLOSED: {1}
Validation_VAL_Profile_OutOfOrder = As specified by profile {0}, Element ''{1}'' is out of order
Validation_VAL_Profile_SliceOrder = As specified by profile {0}, Element ''{1}'' is out of order in ordered slice
Validation_VAL_Profile_Unknown = Profile reference ''{0}'' could not be resolved, so has not been checked
Validation_VAL_Profile_Unknown = Profile reference ''{0}'' has not been checked because it is unknown
VALIDATION_VAL_PROFILE_UNKNOWN_NOT_POLICY = Profile reference ''{0}'' has not been checked because it is unknown, and the validator is set to not fetch unknown profiles
VALIDATION_VAL_PROFILE_UNKNOWN_ERROR = Profile reference ''{0}'' has not been checked because it is unknown, and fetching it resulted in the error {1}
Validation_VAL_Profile_WrongType = Specified profile type was ''{0}'', but found type ''{1}''
Validation_VAL_Unknown_Profile = Unknown profile {0}
XHTML_XHTML_Attribute_Illegal = Illegal attribute name in the XHTML (''{0}'' on ''{1}'')

View File

@ -68,6 +68,7 @@ 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.CanonicalResource;
import org.hl7.fhir.r5.model.Coding;
import org.hl7.fhir.r5.model.Constants;
import org.hl7.fhir.r5.model.DomainResource;
@ -1907,6 +1908,17 @@ public class ValidationEngine implements IValidatorResourceFetcher, IPackageInst
this.locale = locale;
}
@Override
public CanonicalResource fetchCanonicalResource(String url) throws URISyntaxException {
return fetcher != null ? fetcher.fetchCanonicalResource(url) : null;
}
@Override
public boolean fetchesCanonicalResource(String url) {
return fetcher != null ? fetcher.fetchesCanonicalResource(url) : false;
}
public void handleOutput(Resource r, String output, String version) throws FHIRException, IOException {
if (output.startsWith("http://") || output.startsWith("http://")) {
ByteArrayOutputStream bs = new ByteArrayOutputStream();

View File

@ -2,13 +2,17 @@ package org.hl7.fhir.validation.cli.services;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.util.Locale;
import org.hl7.fhir.convertors.txClient.TerminologyClientFactory;
import org.hl7.fhir.exceptions.DefinitionException;
import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.exceptions.FHIRFormatError;
import org.hl7.fhir.r5.context.IWorkerContext;
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.IValidatorResourceFetcher;
import org.hl7.fhir.r5.utils.IResourceValidator.ReferenceValidationPolicy;
import org.hl7.fhir.utilities.Utilities;
@ -119,4 +123,32 @@ public class StandAloneValidatorFetcher implements IValidatorResourceFetcher {
throw new Error("Not done yet");
}
@Override
public CanonicalResource fetchCanonicalResource(String url) throws URISyntaxException {
String[] p = url.split("\\/");
String root = getRoot(p, url);
if (root != null) {
TerminologyClient c;
c = TerminologyClientFactory.makeClient(root, context.getVersion());
return c.read(p[p.length-2], p[p.length-1]);
} else {
throw new FHIRException("Not done yet");
}
}
private String getRoot(String[] p, String url) {
if (p.length > 3 && Utilities.isValidId(p[p.length-1]) && context.getResourceNames().contains(p[p.length-2])) {
url = url.substring(0, url.lastIndexOf("/"));
return url.substring(0, url.lastIndexOf("/"));
} else {
return null;
}
}
@Override
public boolean fetchesCanonicalResource(String url) {
return true;
}
}

View File

@ -2446,25 +2446,26 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
if (pol.checkExists()) {
if (we == null) {
if (fetcher == null) {
if (!refType.equals("contained"))
if (!refType.equals("contained")) {
if (fetcher == null) {
throw new FHIRException(context.formatMessage(I18nConstants.RESOURCE_RESOLUTION_SERVICES_NOT_PROVIDED));
} else {
Element ext = null;
if (fetchCache.containsKey(ref)) {
ext = fetchCache.get(ref);
} else {
try {
ext = fetcher.fetch(hostContext.getAppContext(), ref);
} catch (IOException e) {
throw new FHIRException(e);
}
if (ext != null) {
setParents(ext);
fetchCache.put(ref, ext);
Element ext = null;
if (fetchCache.containsKey(ref)) {
ext = fetchCache.get(ref);
} else {
try {
ext = fetcher.fetch(hostContext.getAppContext(), ref);
} catch (IOException e) {
throw new FHIRException(e);
}
if (ext != null) {
setParents(ext);
fetchCache.put(ref, ext);
}
}
we = ext == null ? null : makeExternalRef(ext, path);
}
we = ext == null ? null : makeExternalRef(ext, path);
}
}
rule(errors, IssueType.STRUCTURE, element.line(), element.col(), path, (allowExamples && (ref.contains("example.org") || ref.contains("acme.com"))) || (we != null || pol == ReferenceValidationPolicy.CHECK_TYPE_IF_EXISTS), I18nConstants.REFERENCE_REF_CANTRESOLVE, ref);
@ -3760,10 +3761,29 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
StructureDefinition sdt = context.fetchResource(StructureDefinition.class, vu.getUrl());
rule(errors, IssueType.STRUCTURE, element.line(), element.col(), stack.getLiteralPath() + ".meta.profile[" + i + "]", false, I18nConstants.VALIDATION_VAL_PROFILE_THIS_VERSION_OTHER, sdt == null ? "null" : sdt.getType());
}
} else if (warning(errors, IssueType.STRUCTURE, element.line(), element.col(), stack.getLiteralPath() + ".meta.profile[" + i + "]", sd != null, I18nConstants.VALIDATION_VAL_PROFILE_UNKNOWN, profile.primitiveValue())) {
signpost(errors, IssueType.INFORMATIONAL, element.line(), element.col(), stack.getLiteralPath(), !crumbTrails, I18nConstants.VALIDATION_VAL_PROFILE_SIGNPOST_META, sd.getUrl());
stack.resetIds();
startInner(hostContext, errors, resource, element, sd, stack, false);
} else {
if (sd == null) {
// 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) {
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())) {
warning(errors, IssueType.STRUCTURE, element.line(), element.col(), stack.getLiteralPath() + ".meta.profile[" + i + "]", false, I18nConstants.VALIDATION_VAL_PROFILE_UNKNOWN_NOT_POLICY, profile.primitiveValue());
} else {
try {
sd = (StructureDefinition) fetcher.fetchCanonicalResource(profile.primitiveValue());
} 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());
}
if (sd != null) {
context.cacheResource(sd);
}
}
}
if (sd != null) {
signpost(errors, IssueType.INFORMATIONAL, element.line(), element.col(), stack.getLiteralPath(), !crumbTrails, I18nConstants.VALIDATION_VAL_PROFILE_SIGNPOST_META, sd.getUrl());
stack.resetIds();
startInner(hostContext, errors, resource, element, sd, stack, false);
}
}
}
i++;

View File

@ -57,6 +57,7 @@ import org.hl7.fhir.utilities.npm.NpmPackage;
import org.hl7.fhir.utilities.validation.ValidationMessage;
import org.hl7.fhir.utilities.validation.ValidationMessage.IssueSeverity;
import org.hl7.fhir.validation.ValidationEngine;
import org.hl7.fhir.validation.cli.services.StandAloneValidatorFetcher;
import org.hl7.fhir.validation.instance.InstanceValidator;
import org.junit.AfterClass;
import org.junit.Assert;
@ -147,7 +148,6 @@ public class ValidationTests implements IEvaluationContext, IValidatorResourceFe
throw new Exception("unknown version " + version);
}
vCurr = ve.get(version);
vCurr.setFetcher(this);
if (TestingUtilities.fcontexts == null) {
TestingUtilities.fcontexts = new HashMap<>();
}
@ -156,6 +156,11 @@ public class ValidationTests implements IEvaluationContext, IValidatorResourceFe
if (content.has("use-test") && !content.get("use-test").getAsBoolean())
return;
if (content.has("fetcher") && "standalone".equals(JSONUtil.str(content, "fetcher"))) {
vCurr.setFetcher(new StandAloneValidatorFetcher(vCurr.getPcm(), vCurr.getContext(), vCurr));
} else {
vCurr.setFetcher(this);
}
String testCaseContent = TestingUtilities.loadTestResource("validator", JSONUtil.str(content, "file"));
InstanceValidator val = vCurr.getValidator();
val.setWantCheckSnapshotUnchanged(true);
@ -170,7 +175,6 @@ public class ValidationTests implements IEvaluationContext, IValidatorResourceFe
val.setValidationLanguage(content.get("language").getAsString());
else
val.setValidationLanguage(null);
val.setFetcher(this);
if (content.has("packages")) {
for (JsonElement e : content.getAsJsonArray("packages")) {
String n = e.getAsString();
@ -526,4 +530,14 @@ public class ValidationTests implements IEvaluationContext, IValidatorResourceFe
URLConnection c = url.openConnection();
return TextFile.streamToBytes(c.getInputStream());
}
@Override
public CanonicalResource fetchCanonicalResource(String url) {
return null;
}
@Override
public boolean fetchesCanonicalResource(String url) {
return false;
}
}