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:
parent
34d29ed614
commit
624ce59c83
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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 {
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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}'')
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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++;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue