* 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 * look for references inside other parameters in Parameters resource
This commit is contained in:
parent
7616b55213
commit
5299bbe16b
|
@ -0,0 +1,18 @@
|
|||
Validator Fixes:
|
||||
* 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
|
||||
|
||||
Other Code changes:
|
||||
* Rendering: add rendering for Parameters resources
|
||||
* Rendering: refactor of resource resolution code to support Parameters
|
||||
* General clean up of rendering consistency & implement additional details when rendering (including patient summary)
|
||||
* Rendering: major overhaul of DiagnosticReport rendering
|
||||
* Fix NPE bug in value set comparison
|
||||
|
||||
|
||||
TODO before commit:
|
||||
* check version of contained resources
|
||||
* review validation of CanonicalResource.url
|
||||
|
|
@ -267,6 +267,11 @@ public class SimpleWorkerContext extends BaseWorkerContext implements IWorkerCon
|
|||
return res;
|
||||
}
|
||||
|
||||
public static SimpleWorkerContext fromNothing() throws FileNotFoundException, FHIRException, IOException {
|
||||
SimpleWorkerContext res = new SimpleWorkerContext();
|
||||
return res;
|
||||
}
|
||||
|
||||
private void loadDefinitionItem(String name, InputStream stream, IContextResourceLoader loader, ILoadFilter filter, PackageVersion pi) throws IOException, FHIRException {
|
||||
if (name.endsWith(".xml"))
|
||||
loadFromFile(stream, name, loader, filter);
|
||||
|
|
|
@ -3,46 +3,58 @@ package org.hl7.fhir.r5.renderers.utils;
|
|||
import org.hl7.fhir.r5.model.Bundle;
|
||||
import org.hl7.fhir.r5.model.Bundle.BundleEntryComponent;
|
||||
import org.hl7.fhir.r5.model.DomainResource;
|
||||
import org.hl7.fhir.r5.model.Parameters;
|
||||
import org.hl7.fhir.r5.model.Parameters.ParametersParameterComponent;
|
||||
import org.hl7.fhir.r5.model.Resource;
|
||||
import org.hl7.fhir.r5.renderers.utils.BaseWrappers.ResourceWrapper;
|
||||
import org.hl7.fhir.r5.renderers.utils.Resolver.ResourceContextType;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
public class Resolver {
|
||||
|
||||
public enum ResourceContextType {
|
||||
PARAMETERS, BUNDLE
|
||||
}
|
||||
|
||||
public interface IReferenceResolver {
|
||||
ResourceWithReference resolve(RenderingContext context, String url);
|
||||
}
|
||||
|
||||
public static class ResourceContext {
|
||||
Bundle bundleResource;
|
||||
org.hl7.fhir.r5.elementmodel.Element bundleElement;
|
||||
private ResourceContextType type;
|
||||
private Resource containerResource;
|
||||
private org.hl7.fhir.r5.elementmodel.Element containerElement;
|
||||
|
||||
DomainResource resourceResource;
|
||||
org.hl7.fhir.r5.elementmodel.Element resourceElement;
|
||||
|
||||
public ResourceContext(Bundle bundle, DomainResource dr) {
|
||||
public ResourceContext(ResourceContextType type, Resource bundle, DomainResource dr) {
|
||||
super();
|
||||
this.bundleResource = bundle;
|
||||
this.type = type;
|
||||
this.containerResource = bundle;
|
||||
this.resourceResource = dr;
|
||||
}
|
||||
|
||||
public ResourceContext(org.hl7.fhir.r5.elementmodel.Element bundle, org.hl7.fhir.r5.elementmodel.Element dr) {
|
||||
this.bundleElement = bundle;
|
||||
public ResourceContext(ResourceContextType type, org.hl7.fhir.r5.elementmodel.Element bundle, org.hl7.fhir.r5.elementmodel.Element dr) {
|
||||
super();
|
||||
this.type = type;
|
||||
this.containerElement = bundle;
|
||||
this.resourceElement = dr;
|
||||
}
|
||||
|
||||
public ResourceContext(Object bundle, Element doc) {
|
||||
// TODO Auto-generated constructor stub
|
||||
}
|
||||
// public ResourceContext(Object bundle, Element doc) {
|
||||
// // TODO Auto-generated constructor stub
|
||||
// }
|
||||
|
||||
public Bundle getBundleResource() {
|
||||
return bundleResource;
|
||||
}
|
||||
// public Bundle getBundleResource() {
|
||||
// return containerResource;
|
||||
// }
|
||||
|
||||
public org.hl7.fhir.r5.elementmodel.Element getBundleElement() {
|
||||
return bundleElement;
|
||||
}
|
||||
|
||||
// public org.hl7.fhir.r5.elementmodel.Element getBundleElement() {
|
||||
// return containerElement;
|
||||
// }
|
||||
//
|
||||
public DomainResource getResourceResource() {
|
||||
return resourceResource;
|
||||
}
|
||||
|
@ -64,13 +76,27 @@ public class Resolver {
|
|||
}
|
||||
return null;
|
||||
}
|
||||
if (bundleResource != null) {
|
||||
for (BundleEntryComponent be : bundleResource.getEntry()) {
|
||||
if (be.getFullUrl().equals(value))
|
||||
return be;
|
||||
if (value.equals(be.getResource().fhirType()+"/"+be.getResource().getId()))
|
||||
return be;
|
||||
}
|
||||
if (type == ResourceContextType.BUNDLE) {
|
||||
if (containerResource != null) {
|
||||
for (BundleEntryComponent be : ((Bundle) containerResource).getEntry()) {
|
||||
if (be.getFullUrl().equals(value))
|
||||
return be;
|
||||
if (value.equals(be.getResource().fhirType()+"/"+be.getResource().getId()))
|
||||
return be;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (type == ResourceContextType.PARAMETERS) {
|
||||
if (containerResource != null) {
|
||||
for (ParametersParameterComponent p : ((Parameters) containerResource).getParameter()) {
|
||||
if (p.getResource() != null && value.equals(p.getResource().fhirType()+"/"+p.getResource().getId())) {
|
||||
BundleEntryComponent be = new BundleEntryComponent();
|
||||
be.setResource(p.getResource());
|
||||
return be;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -85,13 +111,24 @@ public class Resolver {
|
|||
}
|
||||
return null;
|
||||
}
|
||||
if (bundleElement != null) {
|
||||
for (org.hl7.fhir.r5.elementmodel.Element be : bundleElement.getChildren("entry")) {
|
||||
org.hl7.fhir.r5.elementmodel.Element res = be.getNamedChild("resource");
|
||||
if (value.equals(be.getChildValue("fullUrl")))
|
||||
return be;
|
||||
if (value.equals(res.fhirType()+"/"+res.getChildValue("id")))
|
||||
return be;
|
||||
if (type == ResourceContextType.BUNDLE) {
|
||||
if (containerElement != null) {
|
||||
for (org.hl7.fhir.r5.elementmodel.Element be : containerElement.getChildren("entry")) {
|
||||
org.hl7.fhir.r5.elementmodel.Element res = be.getNamedChild("resource");
|
||||
if (value.equals(be.getChildValue("fullUrl")))
|
||||
return be;
|
||||
if (value.equals(res.fhirType()+"/"+res.getChildValue("id")))
|
||||
return be;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (type == ResourceContextType.PARAMETERS) {
|
||||
if (containerElement != null) {
|
||||
for (org.hl7.fhir.r5.elementmodel.Element p : containerElement.getChildren("parameter")) {
|
||||
org.hl7.fhir.r5.elementmodel.Element res = p.getNamedChild("resource");
|
||||
if (value.equals(res.fhirType()+"/"+res.getChildValue("id")))
|
||||
return p;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package org.hl7.fhir.utilities;
|
||||
|
||||
import org.hl7.fhir.exceptions.FHIRException;
|
||||
import org.hl7.fhir.utilities.cache.NpmPackage;
|
||||
|
||||
/*
|
||||
Copyright (c) 2011+, HL7, Inc.
|
||||
|
@ -35,6 +36,22 @@ import org.hl7.fhir.exceptions.FHIRException;
|
|||
public class VersionUtilities {
|
||||
|
||||
|
||||
public static class VersionURLInfo {
|
||||
private String version;
|
||||
private String url;
|
||||
public VersionURLInfo(String version, String url) {
|
||||
super();
|
||||
this.version = version;
|
||||
this.url = url;
|
||||
}
|
||||
public String getVersion() {
|
||||
return version;
|
||||
}
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
}
|
||||
|
||||
public static final String CURRENT_VERSION = "4.4";
|
||||
public static final String CURRENT_FULL_VERSION = "4.4.0";
|
||||
|
||||
|
@ -225,4 +242,18 @@ public class VersionUtilities {
|
|||
throw new FHIRException("Unknown version "+version);
|
||||
}
|
||||
|
||||
public static VersionURLInfo parseVersionUrl(String url) {
|
||||
if (url.length() < 24) {
|
||||
return null;
|
||||
}
|
||||
String v = url.substring(20, 24);
|
||||
if (v.endsWith("/")) {
|
||||
v = v.substring(0, v.length()-1);
|
||||
if (Utilities.existsInList(v, "1.0", "1.4", "3.0", "4.0", "5.0", CURRENT_VERSION)) {
|
||||
return new VersionURLInfo(v, "http://hl7.org/fhir/"+url.substring(24));
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
|
@ -1057,6 +1057,26 @@ public class NpmPackage {
|
|||
public boolean isCore() {
|
||||
return "fhir.core".equals(JSONUtil.str(npm, "type"));
|
||||
}
|
||||
|
||||
public boolean hasCanonical(String url) {
|
||||
if (url == null) {
|
||||
return false;
|
||||
}
|
||||
String u = url.contains("|") ? url.substring(0, url.indexOf("|")) : url;
|
||||
String v = url.contains("|") ? url.substring(url.indexOf("|")+1) : null;
|
||||
NpmPackageFolder folder = folders.get("package");
|
||||
if (folder != null) {
|
||||
for (JsonElement e : folder.index.getAsJsonArray("files")) {
|
||||
JsonObject o = (JsonObject) e;
|
||||
if (u.equals(JSONUtil.str(o, "url"))) {
|
||||
if (v == null || v.equals(JSONUtil.str(o, "version"))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -25,6 +25,7 @@ public class I18nConstants {
|
|||
public static final String BUNDLE_BUNDLE_ENTRY_NOFIRSTRESOURCE = "Bundle_BUNDLE_Entry_NoFirstResource";
|
||||
public static final String BUNDLE_BUNDLE_ENTRY_NOFULLURL = "Bundle_BUNDLE_Entry_NoFullUrl";
|
||||
public static final String BUNDLE_BUNDLE_ENTRY_NOPROFILE = "Bundle_BUNDLE_Entry_NoProfile";
|
||||
public static final String BUNDLE_BUNDLE_ENTRY_MULTIPLE_PROFILES = "BUNDLE_BUNDLE_ENTRY_MULTIPLE_PROFILES";
|
||||
public static final String BUNDLE_BUNDLE_ENTRY_NOTFOUND = "Bundle_BUNDLE_Entry_NotFound";
|
||||
public static final String BUNDLE_BUNDLE_ENTRY_ORPHAN = "Bundle_BUNDLE_Entry_Orphan";
|
||||
public static final String BUNDLE_BUNDLE_ENTRY_TYPE = "Bundle_BUNDLE_Entry_Type";
|
||||
|
@ -543,10 +544,14 @@ public class I18nConstants {
|
|||
public static final String VALIDATION_VAL_PROFILE_SIGNPOST_GLOBAL = "VALIDATION_VAL_PROFILE_SIGNPOST_GLOBAL";
|
||||
public static final String VALIDATION_VAL_PROFILE_SIGNPOST_META = "VALIDATION_VAL_PROFILE_SIGNPOST_META";
|
||||
public static final String VALIDATION_VAL_PROFILE_SLICEORDER = "Validation_VAL_Profile_SliceOrder";
|
||||
public static final String VALIDATION_VAL_PROFILE_OTHER_VERSION = "VALIDATION_VAL_PROFILE_OTHER_VERSION";
|
||||
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_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";
|
||||
|
||||
public static final String VALUESET_INCLUDE_INVALID_CONCEPT_CODE = "VALUESET_INCLUDE_INVALID_CONCEPT_CODE";
|
||||
public static final String VALUESET_INCLUDE_INVALID_CONCEPT_CODE_VER = "VALUESET_INCLUDE_INVALID_CONCEPT_CODE_VER";
|
||||
public static final String VALUESET_NO_SYSTEM_WARNING = "VALUESET_NO_SYSTEM_WARNING";
|
||||
|
|
|
@ -571,3 +571,7 @@ PACKAGE_VERSION_MISMATCH = FHIR Version mismatch in package {0}: version is {2}
|
|||
VALUESET_REFERENCE_UNKNOWN = The value set import {0} could not be found so cannot be checked
|
||||
VALUESET_REFERENCE_INVALID_TYPE = The value set import {0} points to a resource of type {1} which is not valid
|
||||
SD_MUST_HAVE_DERIVATION = StructureDefinition {0} must have a derivation, since it has a baseDefinition
|
||||
VALIDATION_VAL_PROFILE_OTHER_VERSION = Profile is for a different version of FHIR ({0}) so has been ignored
|
||||
VALIDATION_VAL_PROFILE_THIS_VERSION_OK = Profile for this version of FHIR - all OK
|
||||
VALIDATION_VAL_PROFILE_THIS_VERSION_OTHER = Profile is for this version of FHIR, but is an invalid type {0}
|
||||
BUNDLE_BUNDLE_ENTRY_MULTIPLE_PROFILES = Multiple profiles found for contained resource. This is not supported at this time. (Type {0}: {1})
|
||||
|
|
|
@ -34,6 +34,7 @@ import org.hl7.fhir.r5.utils.*;
|
|||
import org.hl7.fhir.r5.utils.IResourceValidator.*;
|
||||
import org.hl7.fhir.r5.utils.StructureMapUtilities.ITransformerServices;
|
||||
import org.hl7.fhir.utilities.i18n.I18nConstants;
|
||||
import org.hl7.fhir.validation.cli.services.StandAloneValidatorFetcher.IPackageInstaller;
|
||||
import org.hl7.fhir.validation.instance.InstanceValidator;
|
||||
import org.hl7.fhir.utilities.IniFile;
|
||||
import org.hl7.fhir.utilities.TextFile;
|
||||
|
@ -163,7 +164,42 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
* @author Grahame Grieve
|
||||
*
|
||||
*/
|
||||
public class ValidationEngine implements IValidatorResourceFetcher {
|
||||
public class ValidationEngine implements IValidatorResourceFetcher, IPackageInstaller {
|
||||
|
||||
public static class VersionSourceInformation {
|
||||
|
||||
private List<String> report = new ArrayList<>();
|
||||
private List<String> versions = new ArrayList<>();
|
||||
|
||||
public void see(String version, String src) {
|
||||
version = VersionUtilities.getMajMin(version);
|
||||
report.add(src+": "+version);
|
||||
if (!versions.contains(version)) {
|
||||
versions.add(version);
|
||||
Collections.sort(versions);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return versions.isEmpty();
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return versions.size();
|
||||
}
|
||||
|
||||
public String version() {
|
||||
return versions.get(0);
|
||||
}
|
||||
|
||||
public List<String> getReport() {
|
||||
if (report.isEmpty()) {
|
||||
report.add("(nothing found)");
|
||||
}
|
||||
return report;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class ScanOutputItem {
|
||||
private String ref;
|
||||
|
@ -311,9 +347,10 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
|||
|
||||
public ValidationEngine() throws IOException {
|
||||
pcm = new FilesystemPackageCacheManager(true, ToolsVersion.TOOLS_VERSION);
|
||||
context = SimpleWorkerContext.fromNothing();
|
||||
}
|
||||
|
||||
public void setTerminologyServer(String src, String log, FhirPublication version) throws Exception {
|
||||
public void setTerminologyServer(String src, String log, FhirPublication version) throws FHIRException, URISyntaxException {
|
||||
connectToTSServer(src, log, version);
|
||||
}
|
||||
|
||||
|
@ -342,7 +379,7 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
|||
this.showTimes = showTimes;
|
||||
}
|
||||
|
||||
public ValidationEngine(String src, String txsrvr, String txLog, FhirPublication version, boolean canRunWithoutTerminologyServer, String vString) throws Exception {
|
||||
public ValidationEngine(String src, String txsrvr, String txLog, FhirPublication version, boolean canRunWithoutTerminologyServer, String vString) throws FHIRException, IOException, URISyntaxException {
|
||||
pcm = new FilesystemPackageCacheManager(true, ToolsVersion.TOOLS_VERSION);
|
||||
loadCoreDefinitions(src, false);
|
||||
context.setCanRunWithoutTerminology(canRunWithoutTerminologyServer);
|
||||
|
@ -350,14 +387,14 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
|||
this.version = vString;
|
||||
}
|
||||
|
||||
public ValidationEngine(String src, String txsrvr, String txLog, FhirPublication version, String vString) throws Exception {
|
||||
public ValidationEngine(String src, String txsrvr, String txLog, FhirPublication version, String vString) throws FHIRException, IOException, URISyntaxException {
|
||||
pcm = new FilesystemPackageCacheManager(true, ToolsVersion.TOOLS_VERSION);
|
||||
loadCoreDefinitions(src, false);
|
||||
setTerminologyServer(txsrvr, txLog, version);
|
||||
this.version = vString;
|
||||
}
|
||||
|
||||
public ValidationEngine(String src) throws Exception {
|
||||
public ValidationEngine(String src) throws FHIRException, IOException {
|
||||
loadCoreDefinitions(src, false);
|
||||
pcm = new FilesystemPackageCacheManager(true, ToolsVersion.TOOLS_VERSION);
|
||||
}
|
||||
|
@ -370,7 +407,7 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
|||
this.language = language;
|
||||
}
|
||||
|
||||
private void loadCoreDefinitions(String src, boolean recursive) throws Exception {
|
||||
private void loadCoreDefinitions(String src, boolean recursive) throws FHIRException, IOException {
|
||||
if (pcm == null) {
|
||||
pcm = new FilesystemPackageCacheManager(true, ToolsVersion.TOOLS_VERSION);
|
||||
}
|
||||
|
@ -435,7 +472,7 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
|||
return ep;
|
||||
}
|
||||
|
||||
private byte[] loadProfileSource(String src) throws Exception {
|
||||
private byte[] loadProfileSource(String src) throws FHIRException, FileNotFoundException, IOException {
|
||||
if (Utilities.noString(src)) {
|
||||
throw new FHIRException("Profile Source '" + src + "' could not be processed");
|
||||
} else if (src.startsWith("https:") || src.startsWith("http:")) {
|
||||
|
@ -447,13 +484,13 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
|||
}
|
||||
}
|
||||
|
||||
private byte[] loadProfileFromUrl(String src) throws Exception {
|
||||
private byte[] loadProfileFromUrl(String src) throws FHIRException {
|
||||
try {
|
||||
URL url = new URL(src+"?nocache=" + System.currentTimeMillis());
|
||||
URLConnection c = url.openConnection();
|
||||
return IOUtils.toByteArray(c.getInputStream());
|
||||
} catch (Exception e) {
|
||||
throw new Exception("Unable to find definitions at URL '"+src+"': "+e.getMessage(), e);
|
||||
throw new FHIRException("Unable to find definitions at URL '"+src+"': "+e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -464,9 +501,10 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
|||
return TextFile.fileToBytes(src);
|
||||
}
|
||||
|
||||
/** explore should be true if we're trying to load an -ig parameter, and false if we're loading source **/
|
||||
/** explore should be true if we're trying to load an -ig parameter, and false if we're loading source
|
||||
* @throws IOException **/
|
||||
|
||||
private Map<String, byte[]> loadIgSource(String src, boolean recursive, boolean explore) throws Exception {
|
||||
private Map<String, byte[]> loadIgSource(String src, boolean recursive, boolean explore) throws FHIRException, IOException {
|
||||
// src can be one of the following:
|
||||
// - a canonical url for an ig - this will be converted to a package id and loaded into the cache
|
||||
// - a package id for an ig - this will be loaded into the cache
|
||||
|
@ -510,11 +548,60 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
|||
} else if ((src.matches(FilesystemPackageCacheManager.PACKAGE_REGEX) || src.matches(FilesystemPackageCacheManager.PACKAGE_VERSION_REGEX)) && !src.endsWith(".zip") && !src.endsWith(".tgz")) {
|
||||
return fetchByPackage(src);
|
||||
}
|
||||
throw new Exception("Unable to find/resolve/read -ig "+src);
|
||||
throw new FHIRException("Unable to find/resolve/read -ig "+src);
|
||||
}
|
||||
|
||||
private Map<String, byte[]> loadIgSourceForVersion(String src, boolean recursive, boolean explore, VersionSourceInformation versions) throws FHIRException, IOException {
|
||||
if (src.startsWith("https:") || src.startsWith("http:")) {
|
||||
String v = null;
|
||||
if (src.contains("|")) {
|
||||
v = src.substring(src.indexOf("|")+1);
|
||||
src = src.substring(0, src.indexOf("|"));
|
||||
}
|
||||
String pid = pcm.getPackageId(src);
|
||||
if (!Utilities.noString(pid)) {
|
||||
versions.see(fetchVersionByPackage(pid+(v == null ? "" : "#"+v)), "Package "+src);
|
||||
return null;
|
||||
} else {
|
||||
return fetchVersionFromUrl(src+(v == null ? "" : "|"+v), explore, versions);
|
||||
}
|
||||
}
|
||||
|
||||
File f = new File(Utilities.path(src));
|
||||
if (f.exists()) {
|
||||
if (f.isDirectory() && new File(Utilities.path(src, "package.tgz")).exists()) {
|
||||
versions.see(loadPackageForVersion(new FileInputStream(Utilities.path(src, "package.tgz")), Utilities.path(src, "package.tgz")), "Package "+src);
|
||||
return null;
|
||||
}
|
||||
if (f.isDirectory() && new File(Utilities.path(src, "igpack.zip")).exists())
|
||||
return readZip(new FileInputStream(Utilities.path(src, "igpack.zip")));
|
||||
if (f.isDirectory() && new File(Utilities.path(src, "validator.pack")).exists())
|
||||
return readZip(new FileInputStream(Utilities.path(src, "validator.pack")));
|
||||
if (f.isDirectory())
|
||||
return scanDirectory(f, recursive);
|
||||
if (src.endsWith(".tgz")) {
|
||||
versions.see(loadPackageForVersion(new FileInputStream(src), src), "Package "+src);
|
||||
return null;
|
||||
}
|
||||
if (src.endsWith(".pack"))
|
||||
return readZip(new FileInputStream(src));
|
||||
if (src.endsWith("igpack.zip"))
|
||||
return readZip(new FileInputStream(src));
|
||||
FhirFormat fmt = checkIsResource(src);
|
||||
if (fmt != null) {
|
||||
Map<String, byte[]> res = new HashMap<String, byte[]>();
|
||||
res.put(Utilities.changeFileExt(src, "."+fmt.getExtension()), TextFile.fileToBytesNCS(src));
|
||||
return res;
|
||||
}
|
||||
} else if ((src.matches(FilesystemPackageCacheManager.PACKAGE_REGEX) || src.matches(FilesystemPackageCacheManager.PACKAGE_VERSION_REGEX)) && !src.endsWith(".zip") && !src.endsWith(".tgz")) {
|
||||
versions.see(fetchVersionByPackage(src), "Package "+src);
|
||||
return null;
|
||||
}
|
||||
throw new FHIRException("Unable to find/resolve/read -ig "+src);
|
||||
}
|
||||
|
||||
|
||||
private Map<String, byte[]> fetchFromUrl(String src, boolean explore) throws Exception {
|
||||
private Map<String, byte[]> fetchFromUrl(String src, boolean explore) throws FHIRException, IOException {
|
||||
if (src.endsWith(".tgz"))
|
||||
return loadPackage(fetchFromUrlSpecific(src, false), src);
|
||||
if (src.endsWith(".pack"))
|
||||
|
@ -551,15 +638,59 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
|||
res.put(Utilities.changeFileExt(src, "."+fmt.getExtension()), cnt);
|
||||
return res;
|
||||
}
|
||||
throw new Exception("Unable to find/resolve/read -ig "+src);
|
||||
throw new FHIRException("Unable to find/resolve/read -ig "+src);
|
||||
}
|
||||
|
||||
private InputStream fetchFromUrlSpecific(String source, boolean optional) throws Exception {
|
||||
private Map<String, byte[]> fetchVersionFromUrl(String src, boolean explore, VersionSourceInformation versions) throws FHIRException, IOException {
|
||||
if (src.endsWith(".tgz")) {
|
||||
versions.see(loadPackageForVersion(fetchFromUrlSpecific(src, false), src), "From Package "+src);
|
||||
return null;
|
||||
}
|
||||
if (src.endsWith(".pack"))
|
||||
return readZip(fetchFromUrlSpecific(src, false));
|
||||
if (src.endsWith("igpack.zip"))
|
||||
return readZip(fetchFromUrlSpecific(src, false));
|
||||
|
||||
InputStream stream = null;
|
||||
if (explore) {
|
||||
stream = fetchFromUrlSpecific(Utilities.pathURL(src, "package.tgz"), true);
|
||||
if (stream != null) {
|
||||
versions.see(loadPackageForVersion(stream, Utilities.pathURL(src, "package.tgz")), "From Package at "+src);
|
||||
return null;
|
||||
}
|
||||
// todo: these options are deprecated - remove once all IGs have been rebuilt post R4 technical correction
|
||||
stream = fetchFromUrlSpecific(Utilities.pathURL(src, "igpack.zip"), true);
|
||||
if (stream != null)
|
||||
return readZip(stream);
|
||||
stream = fetchFromUrlSpecific(Utilities.pathURL(src, "validator.pack"), true);
|
||||
if (stream != null)
|
||||
return readZip(stream);
|
||||
stream = fetchFromUrlSpecific(Utilities.pathURL(src, "validator.pack"), true);
|
||||
//// -----
|
||||
}
|
||||
|
||||
// ok, having tried all that... now we'll just try to access it directly
|
||||
byte[] cnt;
|
||||
if (stream == null)
|
||||
cnt = fetchFromUrlSpecific(src, "application/json", true);
|
||||
else
|
||||
cnt = TextFile.streamToBytes(stream);
|
||||
|
||||
FhirFormat fmt = checkIsResource(cnt, src);
|
||||
if (fmt != null) {
|
||||
Map<String, byte[]> res = new HashMap<String, byte[]>();
|
||||
res.put(Utilities.changeFileExt(src, "."+fmt.getExtension()), cnt);
|
||||
return res;
|
||||
}
|
||||
throw new FHIRException("Unable to find/resolve/read -ig "+src);
|
||||
}
|
||||
|
||||
private InputStream fetchFromUrlSpecific(String source, boolean optional) throws FHIRException, IOException {
|
||||
try {
|
||||
URL url = new URL(source+"?nocache=" + System.currentTimeMillis());
|
||||
URLConnection c = url.openConnection();
|
||||
return c.getInputStream();
|
||||
} catch (Exception e) {
|
||||
} catch (IOException e) {
|
||||
if (optional)
|
||||
return null;
|
||||
else
|
||||
|
@ -567,13 +698,13 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
|||
}
|
||||
}
|
||||
|
||||
private byte[] fetchFromUrlSpecific(String source, String contentType, boolean optional) throws Exception {
|
||||
private byte[] fetchFromUrlSpecific(String source, String contentType, boolean optional) throws FHIRException, IOException {
|
||||
try {
|
||||
URL url = new URL(source+"?nocache=" + System.currentTimeMillis());
|
||||
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
|
||||
conn.setRequestProperty("Accept", contentType);
|
||||
return TextFile.streamToBytes(conn.getInputStream());
|
||||
} catch (Exception e) {
|
||||
} catch (IOException e) {
|
||||
if (optional)
|
||||
return null;
|
||||
else
|
||||
|
@ -604,11 +735,15 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
|||
return Utilities.existsInList(Utilities.getFileExtension(ff.getName()).toLowerCase(), "md", "css", "js", "png", "gif", "jpg", "html", "tgz", "pack", "zip");
|
||||
}
|
||||
|
||||
private Map<String, byte[]> loadPackage(InputStream stream, String name) throws Exception {
|
||||
private Map<String, byte[]> loadPackage(InputStream stream, String name) throws FHIRException, IOException {
|
||||
return loadPackage(NpmPackage.fromPackage(stream));
|
||||
}
|
||||
|
||||
public Map<String, byte[]> loadPackage(NpmPackage pi) throws Exception {
|
||||
private String loadPackageForVersion(InputStream stream, String name) throws FHIRException, IOException {
|
||||
return NpmPackage.fromPackage(stream).fhirVersion();
|
||||
}
|
||||
|
||||
public Map<String, byte[]> loadPackage(NpmPackage pi) throws FHIRException, IOException {
|
||||
context.getLoadedPackages().add(pi.name()+"#"+pi.version());
|
||||
Map<String, byte[]> res = new HashMap<String, byte[]>();
|
||||
for (String s : pi.dependencies()) {
|
||||
|
@ -652,7 +787,7 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
|||
System.out.println(message);
|
||||
}
|
||||
|
||||
private Map<String, byte[]> fetchByPackage(String src) throws Exception {
|
||||
private Map<String, byte[]> fetchByPackage(String src) throws FHIRException, IOException {
|
||||
String id = src;
|
||||
String version = null;
|
||||
if (src.contains("#")) {
|
||||
|
@ -679,13 +814,46 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
|||
return loadPackage(pi);
|
||||
}
|
||||
|
||||
private Map<String, byte[]> resolvePackage(String id, String v) throws Exception {
|
||||
private String fetchVersionByPackage(String src) throws FHIRException, IOException {
|
||||
String id = src;
|
||||
String version = null;
|
||||
if (src.contains("#")) {
|
||||
id = src.substring(0, src.indexOf("#"));
|
||||
version = src.substring(src.indexOf("#")+1);
|
||||
}
|
||||
if (pcm == null) {
|
||||
log("Creating Package manager?");
|
||||
pcm = new FilesystemPackageCacheManager(true, ToolsVersion.TOOLS_VERSION);
|
||||
}
|
||||
if (version == null) {
|
||||
version = pcm.getLatestVersion(id);
|
||||
}
|
||||
NpmPackage pi = null;
|
||||
if (version == null) {
|
||||
pi = pcm.loadPackageFromCacheOnly(id);
|
||||
if (pi != null)
|
||||
log(" ... Using version "+pi.version());
|
||||
} else
|
||||
pi = pcm.loadPackageFromCacheOnly(id, version);
|
||||
if (pi == null) {
|
||||
return resolvePackageForVersion(id, version);
|
||||
} else {
|
||||
return pi.fhirVersion();
|
||||
}
|
||||
}
|
||||
|
||||
private Map<String, byte[]> resolvePackage(String id, String v) throws FHIRException, IOException {
|
||||
NpmPackage pi = pcm.loadPackage(id, v);
|
||||
if (pi != null && v == null)
|
||||
log(" ... Using version "+pi.version());
|
||||
return loadPackage(pi);
|
||||
}
|
||||
|
||||
private String resolvePackageForVersion(String id, String v) throws FHIRException, IOException {
|
||||
NpmPackage pi = pcm.loadPackage(id, v);
|
||||
return pi.fhirVersion();
|
||||
}
|
||||
|
||||
public SimpleWorkerContext getContext() {
|
||||
return context;
|
||||
}
|
||||
|
@ -758,7 +926,7 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
|||
}
|
||||
}
|
||||
|
||||
public void loadProfile(String src) throws Exception {
|
||||
public void loadProfile(String src) throws FHIRException, IOException {
|
||||
if (context.hasResource(StructureDefinition.class, src))
|
||||
return;
|
||||
if (context.hasResource(ImplementationGuide.class, src))
|
||||
|
@ -770,7 +938,13 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
|||
context.cacheResource(r);
|
||||
}
|
||||
|
||||
public void loadIg(String src, boolean recursive) throws IOException, FHIRException, Exception {
|
||||
public void scanForIgVersion(String src, boolean recursive, VersionSourceInformation versions) throws IOException, FHIRException, Exception {
|
||||
Map<String, byte[]> source = loadIgSourceForVersion(src, recursive, true, versions);
|
||||
if (source != null && source.containsKey("version.info"))
|
||||
versions.see(readInfoVersion(source.get("version.info")), "version.info in "+src);
|
||||
}
|
||||
|
||||
public void loadIg(String src, boolean recursive) throws IOException, FHIRException {
|
||||
NpmPackage npm = src.matches(FilesystemPackageCacheManager.PACKAGE_REGEX) ? pcm.loadPackage(src, null) : null;
|
||||
if (npm != null) {
|
||||
for (String s : npm.dependencies()) {
|
||||
|
@ -834,7 +1008,7 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
|||
return r;
|
||||
}
|
||||
|
||||
public Resource loadResourceByVersion(String version, byte[] content, String fn) throws IOException, Exception {
|
||||
public Resource loadResourceByVersion(String version, byte[] content, String fn) throws IOException, FHIRException {
|
||||
Resource r;
|
||||
if (version.startsWith("3.0")) {
|
||||
org.hl7.fhir.dstu3.model.Resource res;
|
||||
|
@ -845,7 +1019,7 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
|||
else if (fn.endsWith(".txt") || fn.endsWith(".map") )
|
||||
res = new org.hl7.fhir.dstu3.utils.StructureMapUtilities(null).parse(new String(content));
|
||||
else
|
||||
throw new Exception("Unsupported format for "+fn);
|
||||
throw new FHIRException("Unsupported format for "+fn);
|
||||
r = VersionConvertor_30_50.convertResource(res, false);
|
||||
} else if (version.startsWith("4.0")) {
|
||||
org.hl7.fhir.r4.model.Resource res;
|
||||
|
@ -856,7 +1030,7 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
|||
else if (fn.endsWith(".txt") || fn.endsWith(".map") )
|
||||
res = new org.hl7.fhir.r4.utils.StructureMapUtilities(null).parse(new String(content), fn);
|
||||
else
|
||||
throw new Exception("Unsupported format for "+fn);
|
||||
throw new FHIRException("Unsupported format for "+fn);
|
||||
r = VersionConvertor_40_50.convertResource(res);
|
||||
} else if (version.startsWith("1.4")) {
|
||||
org.hl7.fhir.dstu2016may.model.Resource res;
|
||||
|
@ -865,7 +1039,7 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
|||
else if (fn.endsWith(".json") && !fn.endsWith("template.json"))
|
||||
res = new org.hl7.fhir.dstu2016may.formats.JsonParser().parse(new ByteArrayInputStream(content));
|
||||
else
|
||||
throw new Exception("Unsupported format for "+fn);
|
||||
throw new FHIRException("Unsupported format for "+fn);
|
||||
r = VersionConvertor_14_50.convertResource(res);
|
||||
} else if (version.startsWith("1.0")) {
|
||||
org.hl7.fhir.dstu2.model.Resource res;
|
||||
|
@ -874,7 +1048,7 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
|||
else if (fn.endsWith(".json") && !fn.endsWith("template.json"))
|
||||
res = new org.hl7.fhir.dstu2.formats.JsonParser().parse(new ByteArrayInputStream(content));
|
||||
else
|
||||
throw new Exception("Unsupported format for "+fn);
|
||||
throw new FHIRException("Unsupported format for "+fn);
|
||||
VersionConvertorAdvisor50 advisor = new org.hl7.fhir.convertors.misc.IGR2ConvertorAdvisor5();
|
||||
r = VersionConvertor_10_50.convertResource(res, advisor);
|
||||
} else if (version.equals(Constants.VERSION) || "current".equals(version)) {
|
||||
|
@ -887,9 +1061,9 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
|||
else if (fn.endsWith(".txt") || fn.endsWith(".map") )
|
||||
r = new org.hl7.fhir.r5.utils.StructureMapUtilities(null).parse(new String(content), fn);
|
||||
else
|
||||
throw new Exception("Unsupported format for "+fn);
|
||||
throw new FHIRException("Unsupported format for "+fn);
|
||||
} else
|
||||
throw new Exception("Unsupported version "+version);
|
||||
throw new FHIRException("Unsupported version "+version);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -923,11 +1097,11 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
|||
FhirFormat cntType = null;
|
||||
}
|
||||
|
||||
public Content loadContent(String source, String opName) throws Exception {
|
||||
public Content loadContent(String source, String opName) throws FHIRException, IOException {
|
||||
Map<String, byte[]> s = loadIgSource(source, false, false);
|
||||
Content res = new Content();
|
||||
if (s.size() != 1)
|
||||
throw new Exception("Unable to find resource " + source + " to "+opName);
|
||||
throw new FHIRException("Unable to find resource " + source + " to "+opName);
|
||||
for (Entry<String, byte[]> t: s.entrySet()) {
|
||||
res.focus = t.getValue();
|
||||
if (t.getKey().endsWith(".json"))
|
||||
|
@ -939,13 +1113,13 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
|||
else if (t.getKey().endsWith(".txt") || t.getKey().endsWith(".map"))
|
||||
res.cntType = FhirFormat.TEXT;
|
||||
else
|
||||
throw new Exception("Todo: Determining resource type is not yet done");
|
||||
throw new FHIRException("Todo: Determining resource type is not yet done");
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
// testing entry point
|
||||
public OperationOutcome validate(FhirFormat format, InputStream stream, List<String> profiles) throws Exception {
|
||||
public OperationOutcome validate(FhirFormat format, InputStream stream, List<String> profiles) throws FHIRException, IOException, EOperationOutcome {
|
||||
List<ValidationMessage> messages = new ArrayList<ValidationMessage>();
|
||||
InstanceValidator validator = getValidator();
|
||||
validator.validate(null, messages, stream, format, asSdList(profiles));
|
||||
|
@ -966,13 +1140,13 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
|||
return list;
|
||||
}
|
||||
|
||||
public OperationOutcome validate(String source, List<String> profiles) throws Exception {
|
||||
public OperationOutcome validate(String source, List<String> profiles) throws FHIRException, IOException {
|
||||
List<String> l = new ArrayList<String>();
|
||||
l.add(source);
|
||||
return (OperationOutcome)validate(l, profiles);
|
||||
}
|
||||
|
||||
public List<ScanOutputItem> validateScan(List<String> sources, Set<String> guides) throws Exception {
|
||||
public List<ScanOutputItem> validateScan(List<String> sources, Set<String> guides) throws FHIRException, IOException, EOperationOutcome {
|
||||
List<String> refs = new ArrayList<String>();
|
||||
handleSources(sources, refs);
|
||||
|
||||
|
@ -1048,7 +1222,28 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
|||
return null;
|
||||
}
|
||||
|
||||
public Resource validate(List<String> sources, List<String> profiles) throws Exception {
|
||||
public void scanForVersions(List<String> sources, VersionSourceInformation versions) throws FHIRException, IOException {
|
||||
List<String> refs = new ArrayList<String>();
|
||||
handleSources(sources, refs);
|
||||
for (String ref : refs) {
|
||||
Content cnt = loadContent(ref, "validate");
|
||||
String s = TextFile.bytesToString(cnt.focus);
|
||||
if (s.contains("http://hl7.org/fhir/3.0")) {
|
||||
versions.see("3.0", "Profile in "+ref);
|
||||
}
|
||||
if (s.contains("http://hl7.org/fhir/1.0")) {
|
||||
versions.see("1.0", "Profile in "+ref);
|
||||
}
|
||||
if (s.contains("http://hl7.org/fhir/4.0")) {
|
||||
versions.see("4.0", "Profile in "+ref);
|
||||
}
|
||||
if (s.contains("http://hl7.org/fhir/1.4")) {
|
||||
versions.see("1.4", "Profile in "+ref);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Resource validate(List<String> sources, List<String> profiles) throws FHIRException, IOException {
|
||||
List<String> refs = new ArrayList<String>();
|
||||
boolean asBundle = handleSources(sources, refs);
|
||||
Bundle results = new Bundle();
|
||||
|
@ -1065,7 +1260,7 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
|||
results.addEntry().setResource(outcome);
|
||||
} catch (Exception e) {
|
||||
System.out.println("Validation Infrastructure fail validating "+ref+": "+e.getMessage());
|
||||
throw e;
|
||||
throw new FHIRException(e);
|
||||
}
|
||||
}
|
||||
if (asBundle)
|
||||
|
@ -1082,7 +1277,7 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
|||
}
|
||||
}
|
||||
|
||||
public OperationOutcome validateString(String location, String source, FhirFormat format, List<String> profiles) throws Exception {
|
||||
public OperationOutcome validateString(String location, String source, FhirFormat format, List<String> profiles) throws FHIRException, IOException, EOperationOutcome, SAXException {
|
||||
return validate(location, source.getBytes(), format, profiles);
|
||||
}
|
||||
|
||||
|
@ -1136,14 +1331,14 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
|||
return isBundle;
|
||||
}
|
||||
|
||||
public OperationOutcome validate(byte[] source, FhirFormat cntType, List<String> profiles) throws Exception {
|
||||
public OperationOutcome validate(byte[] source, FhirFormat cntType, List<String> profiles) throws FHIRException, IOException, EOperationOutcome {
|
||||
List<ValidationMessage> messages = new ArrayList<ValidationMessage>();
|
||||
InstanceValidator validator = getValidator();
|
||||
validator.validate(null, messages, new ByteArrayInputStream(source), cntType, asSdList(profiles));
|
||||
return messagesToOutcome(messages);
|
||||
}
|
||||
|
||||
public OperationOutcome validate(String location, byte[] source, FhirFormat cntType, List<String> profiles) throws Exception {
|
||||
public OperationOutcome validate(String location, byte[] source, FhirFormat cntType, List<String> profiles) throws FHIRException, IOException, EOperationOutcome, SAXException {
|
||||
List<ValidationMessage> messages = new ArrayList<ValidationMessage>();
|
||||
if (doNative) {
|
||||
if (cntType == FhirFormat.JSON)
|
||||
|
@ -1161,7 +1356,7 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
|||
return messagesToOutcome(messages);
|
||||
}
|
||||
|
||||
public OperationOutcome validate(String location, byte[] source, FhirFormat cntType, List<String> profiles, IdStatus resourceIdRule, boolean anyExtensionsAllowed, BestPracticeWarningLevel bpWarnings, CheckDisplayOption displayOption) throws Exception {
|
||||
public OperationOutcome validate(String location, byte[] source, FhirFormat cntType, List<String> profiles, IdStatus resourceIdRule, boolean anyExtensionsAllowed, BestPracticeWarningLevel bpWarnings, CheckDisplayOption displayOption) throws FHIRException, IOException, EOperationOutcome, SAXException {
|
||||
List<ValidationMessage> messages = new ArrayList<ValidationMessage>();
|
||||
if (doNative) {
|
||||
if (cntType == FhirFormat.JSON)
|
||||
|
@ -1254,12 +1449,12 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
|||
return issue.getSeverity().toString()+" @ "+issue.getLocation() + " " +issue.getDetails().getText() +(source != null ? " (src = "+source+")" : "");
|
||||
}
|
||||
|
||||
public org.hl7.fhir.r5.elementmodel.Element transform(String source, String map) throws Exception {
|
||||
public org.hl7.fhir.r5.elementmodel.Element transform(String source, String map) throws FHIRException, IOException {
|
||||
Content cnt = loadContent(source, "validate");
|
||||
return transform(cnt.focus, cnt.cntType, map);
|
||||
}
|
||||
|
||||
public org.hl7.fhir.r5.elementmodel.Element transform(byte[] source, FhirFormat cntType, String mapUri) throws Exception {
|
||||
public org.hl7.fhir.r5.elementmodel.Element transform(byte[] source, FhirFormat cntType, String mapUri) throws FHIRException, IOException {
|
||||
List<Base> outputs = new ArrayList<Base>();
|
||||
|
||||
StructureMapUtilities scu = new StructureMapUtilities(context, new TransformSupportServices(outputs));
|
||||
|
@ -1299,7 +1494,7 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
|||
return Manager.build(getContext(), structureDefinition);
|
||||
}
|
||||
|
||||
public DomainResource generate(String source, String version) throws Exception {
|
||||
public DomainResource generate(String source, String version) throws FHIRException, IOException, EOperationOutcome {
|
||||
Content cnt = loadContent(source, "validate");
|
||||
Resource res = loadResourceByVersion(version, cnt.focus, source);
|
||||
RenderingContext rc = new RenderingContext(context, null, null, "http://hl7.org/fhir", "", null, ResourceRendererMode.RESOURCE);
|
||||
|
@ -1307,25 +1502,25 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
|||
return (DomainResource) res;
|
||||
}
|
||||
|
||||
public void convert(String source, String output) throws Exception {
|
||||
public void convert(String source, String output) throws FHIRException, IOException {
|
||||
Content cnt = loadContent(source, "validate");
|
||||
Element e = Manager.parse(context, new ByteArrayInputStream(cnt.focus), cnt.cntType);
|
||||
Manager.compose(context, e, new FileOutputStream(output), (output.endsWith(".json") ? FhirFormat.JSON : FhirFormat.XML), OutputStyle.PRETTY, null);
|
||||
}
|
||||
|
||||
public String evaluateFhirPath(String source, String expression) throws Exception {
|
||||
public String evaluateFhirPath(String source, String expression) throws FHIRException, IOException {
|
||||
Content cnt = loadContent(source, "validate");
|
||||
FHIRPathEngine fpe = new FHIRPathEngine(context);
|
||||
Element e = Manager.parse(context, new ByteArrayInputStream(cnt.focus), cnt.cntType);
|
||||
return fpe.evaluateToString(e, expression);
|
||||
}
|
||||
|
||||
public StructureDefinition snapshot(String source, String version) throws Exception {
|
||||
public StructureDefinition snapshot(String source, String version) throws FHIRException, IOException {
|
||||
Content cnt = loadContent(source, "validate");
|
||||
Resource res = loadResourceByVersion(version, cnt.focus, Utilities.getFileNameForName(source));
|
||||
|
||||
if (!(res instanceof StructureDefinition))
|
||||
throw new Exception("Require a StructureDefinition for generating a snapshot");
|
||||
throw new FHIRException("Require a StructureDefinition for generating a snapshot");
|
||||
StructureDefinition sd = (StructureDefinition) res;
|
||||
StructureDefinition base = context.fetchResource(StructureDefinition.class, sd.getBaseDefinition());
|
||||
|
||||
|
@ -1670,8 +1865,9 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
|||
|
||||
@Override
|
||||
public boolean resolveURL(Object appContext, String path, String url) throws IOException, FHIRException {
|
||||
if (!url.startsWith("http://hl7.org/fhir"))
|
||||
return true; // we don't bother with those.
|
||||
if (!url.startsWith("http://") && !url.startsWith("https://")) { // ignore these
|
||||
return true;
|
||||
}
|
||||
if (context.fetchResource(Resource.class, url) != null)
|
||||
return true;
|
||||
if (Utilities.existsInList(url, "http://hl7.org/fhir/sid/us-ssn", "http://hl7.org/fhir/sid/cvx", "http://hl7.org/fhir/sid/ndc", "http://hl7.org/fhir/sid/us-npi", "http://hl7.org/fhir/sid/icd-10",
|
||||
|
@ -1679,6 +1875,9 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
|||
"http://hl7.org/fhir/workflow", "http://hl7.org/fhir/ConsentPolicy/opt-out", "http://hl7.org/fhir/ConsentPolicy/opt-in")) {
|
||||
return true;
|
||||
}
|
||||
if (Utilities.existsInList(url, "http://loinc.org", "http://unitsofmeasure.org", "http://snomed.info/sct")) {
|
||||
return true;
|
||||
}
|
||||
if (fetcher != null) {
|
||||
return fetcher.resolveURL(appContext, path, url);
|
||||
};
|
||||
|
@ -1690,7 +1889,7 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
|||
this.locale = locale;
|
||||
}
|
||||
|
||||
public void handleOutput(Resource r, String output, String version) throws Exception {
|
||||
public void handleOutput(Resource r, String output, String version) throws FHIRException, IOException {
|
||||
if (output.startsWith("http://") || output.startsWith("http://")) {
|
||||
ByteArrayOutputStream bs = new ByteArrayOutputStream();
|
||||
handleOutputToStream(r, output, bs, version);
|
||||
|
@ -1719,7 +1918,7 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
|||
}
|
||||
}
|
||||
|
||||
private void handleOutputToStream(Resource r, String fn, OutputStream s, String version) throws Exception {
|
||||
private void handleOutputToStream(Resource r, String fn, OutputStream s, String version) throws FHIRException, IOException {
|
||||
if (fn.endsWith(".html") || fn.endsWith(".htm") && r instanceof DomainResource)
|
||||
new XhtmlComposer(XhtmlComposer.HTML, true).compose(s, ((DomainResource) r).getText().getDiv());
|
||||
else if (version.startsWith("3.0")) {
|
||||
|
@ -1731,7 +1930,7 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
|||
else if (fn.endsWith(".txt") || fn.endsWith(".map") )
|
||||
TextFile.stringToStream(org.hl7.fhir.dstu3.utils.StructureMapUtilities.render((org.hl7.fhir.dstu3.model.StructureMap) res), s, false);
|
||||
else
|
||||
throw new Exception("Unsupported format for "+fn);
|
||||
throw new FHIRException("Unsupported format for "+fn);
|
||||
} else if (version.startsWith("4.0")) {
|
||||
org.hl7.fhir.r4.model.Resource res = VersionConvertor_40_50.convertResource(r);
|
||||
if (fn.endsWith(".xml") && !fn.endsWith("template.xml"))
|
||||
|
@ -1741,7 +1940,7 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
|||
else if (fn.endsWith(".txt") || fn.endsWith(".map") )
|
||||
TextFile.stringToStream(org.hl7.fhir.r4.utils.StructureMapUtilities.render((org.hl7.fhir.r4.model.StructureMap) res), s, false);
|
||||
else
|
||||
throw new Exception("Unsupported format for "+fn);
|
||||
throw new FHIRException("Unsupported format for "+fn);
|
||||
} else if (version.startsWith("1.4")) {
|
||||
org.hl7.fhir.dstu2016may.model.Resource res = VersionConvertor_14_50.convertResource(r);
|
||||
if (fn.endsWith(".xml") && !fn.endsWith("template.xml"))
|
||||
|
@ -1749,7 +1948,7 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
|||
else if (fn.endsWith(".json") && !fn.endsWith("template.json"))
|
||||
new org.hl7.fhir.dstu2016may.formats.JsonParser().setOutputStyle(org.hl7.fhir.dstu2016may.formats.IParser.OutputStyle.PRETTY).compose(s, res);
|
||||
else
|
||||
throw new Exception("Unsupported format for "+fn);
|
||||
throw new FHIRException("Unsupported format for "+fn);
|
||||
} else if (version.startsWith("1.0")) {
|
||||
VersionConvertorAdvisor50 advisor = new org.hl7.fhir.convertors.misc.IGR2ConvertorAdvisor5();
|
||||
org.hl7.fhir.dstu2.model.Resource res = VersionConvertor_10_50.convertResource(r, advisor);
|
||||
|
@ -1758,7 +1957,7 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
|||
else if (fn.endsWith(".json") && !fn.endsWith("template.json"))
|
||||
new org.hl7.fhir.dstu2.formats.JsonParser().setOutputStyle(org.hl7.fhir.dstu2.formats.IParser.OutputStyle.PRETTY).compose(s, res);
|
||||
else
|
||||
throw new Exception("Unsupported format for "+fn);
|
||||
throw new FHIRException("Unsupported format for "+fn);
|
||||
} else if (version.equals(Constants.VERSION)) {
|
||||
if (fn.endsWith(".xml") && !fn.endsWith("template.xml"))
|
||||
new XmlParser().setOutputStyle(org.hl7.fhir.r5.formats.IParser.OutputStyle.PRETTY).compose(s, r);
|
||||
|
@ -1767,9 +1966,9 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
|||
else if (fn.endsWith(".txt") || fn.endsWith(".map") )
|
||||
TextFile.stringToStream(org.hl7.fhir.r5.utils.StructureMapUtilities.render((org.hl7.fhir.r5.model.StructureMap) r), s, false);
|
||||
else
|
||||
throw new Exception("Unsupported format for "+fn);
|
||||
throw new FHIRException("Unsupported format for "+fn);
|
||||
} else
|
||||
throw new Exception("Encounted unsupported configured version "+version+" loading "+fn);
|
||||
throw new FHIRException("Encounted unsupported configured version "+version+" loading "+fn);
|
||||
|
||||
s.close();
|
||||
}
|
||||
|
@ -1833,7 +2032,7 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
|||
} else if (VersionUtilities.isR4Ver(version)) {
|
||||
return convertVersionNativeR4(targetVer, cnt, format);
|
||||
} else {
|
||||
throw new Exception("Source version not supported yet: "+version);
|
||||
throw new FHIRException("Source version not supported yet: "+version);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
System.out.println("Conversion failed using Java convertor: "+e.getMessage());
|
||||
|
@ -1940,7 +2139,7 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
|||
throw new FHIRException("Unsupported output format: "+cnt.cntType.toString());
|
||||
}
|
||||
} else {
|
||||
throw new Exception("Target Version not supported yet: "+targetVer);
|
||||
throw new FHIRException("Target Version not supported yet: "+targetVer);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2009,7 +2208,7 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
|||
throw new FHIRException("Unsupported output format: "+cnt.cntType.toString());
|
||||
}
|
||||
} else {
|
||||
throw new Exception("Target Version not supported yet: "+targetVer);
|
||||
throw new FHIRException("Target Version not supported yet: "+targetVer);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2078,7 +2277,7 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
|||
throw new FHIRException("Unsupported output format: "+cnt.cntType.toString());
|
||||
}
|
||||
} else {
|
||||
throw new Exception("Target Version not supported yet: "+targetVer);
|
||||
throw new FHIRException("Target Version not supported yet: "+targetVer);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2147,7 +2346,7 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
|||
throw new FHIRException("Unsupported output format: "+cnt.cntType.toString());
|
||||
}
|
||||
} else {
|
||||
throw new Exception("Target Version not supported yet: "+targetVer);
|
||||
throw new FHIRException("Target Version not supported yet: "+targetVer);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2165,5 +2364,10 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
public FilesystemPackageCacheManager getPcm() {
|
||||
return pcm;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -65,6 +65,7 @@ import org.hl7.fhir.r5.model.ImplementationGuide;
|
|||
import org.hl7.fhir.r5.model.StructureDefinition;
|
||||
import org.hl7.fhir.utilities.Utilities;
|
||||
import org.hl7.fhir.utilities.VersionUtilities;
|
||||
import org.hl7.fhir.validation.ValidationEngine.VersionSourceInformation;
|
||||
import org.hl7.fhir.validation.cli.ValidatorGui;
|
||||
import org.hl7.fhir.validation.cli.services.ComparisonService;
|
||||
import org.hl7.fhir.validation.cli.services.ValidationService;
|
||||
|
@ -171,6 +172,10 @@ public class Validator {
|
|||
Display.printCliArgumentsAndInfo(args);
|
||||
cliContext = Params.loadCliContext(args);
|
||||
|
||||
if (cliContext.getSv() == null) {
|
||||
cliContext.setSv(determineVersion(cliContext));
|
||||
}
|
||||
|
||||
// Comment this out because definitions filename doesn't necessarily contain version (and many not even be 14 characters long). Version gets spit out a couple of lines later after we've loaded the context
|
||||
String definitions = VersionUtilities.packageForVersion(cliContext.getSv()) + "#" + VersionUtilities.getCurrentVersion(cliContext.getSv());
|
||||
ValidationEngine validator = ValidationService.getValidator(cliContext, definitions);
|
||||
|
@ -204,5 +209,27 @@ public class Validator {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static String determineVersion(CliContext cliContext) throws Exception {
|
||||
if (cliContext.getMode() != EngineMode.VALIDATION) {
|
||||
return "current";
|
||||
}
|
||||
System.out.println("Scanning for versions (no -version parameter):");
|
||||
VersionSourceInformation versions = ValidationService.scanForVersions(cliContext);
|
||||
for (String s : versions.getReport()) {
|
||||
System.out.println(" "+s);
|
||||
}
|
||||
if (versions.isEmpty()) {
|
||||
System.out.println("-> Using Default version '"+VersionUtilities.CURRENT_VERSION+"'");
|
||||
return "current";
|
||||
}
|
||||
if (versions.size() == 1) {
|
||||
System.out.println("-> use version "+versions.version());
|
||||
return versions.version();
|
||||
}
|
||||
throw new Exception("-> Multiple versions found. Specify a particular version using the -version parameter");
|
||||
}
|
||||
|
||||
}
|
|
@ -36,7 +36,7 @@ public class CliContext {
|
|||
@JsonProperty("txServer")
|
||||
private String txServer = "http://tx.fhir.org";
|
||||
@JsonProperty("sv")
|
||||
private String sv = "current";
|
||||
private String sv = null;
|
||||
@JsonProperty("txLog")
|
||||
private String txLog = null;
|
||||
@JsonProperty("mapLog")
|
||||
|
|
|
@ -0,0 +1,109 @@
|
|||
package org.hl7.fhir.validation.cli.services;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.hl7.fhir.exceptions.DefinitionException;
|
||||
import org.hl7.fhir.exceptions.FHIRException;
|
||||
import org.hl7.fhir.exceptions.FHIRFormatError;
|
||||
import org.hl7.fhir.r5.context.IWorkerContext;
|
||||
import org.hl7.fhir.r5.elementmodel.Element;
|
||||
import org.hl7.fhir.r5.utils.IResourceValidator.IValidatorResourceFetcher;
|
||||
import org.hl7.fhir.r5.utils.IResourceValidator.ReferenceValidationPolicy;
|
||||
import org.hl7.fhir.utilities.Utilities;
|
||||
import org.hl7.fhir.utilities.VersionUtilities;
|
||||
import org.hl7.fhir.utilities.VersionUtilities.VersionURLInfo;
|
||||
import org.hl7.fhir.utilities.cache.BasePackageCacheManager;
|
||||
import org.hl7.fhir.utilities.cache.FilesystemPackageCacheManager;
|
||||
import org.hl7.fhir.utilities.cache.NpmPackage;
|
||||
import org.hl7.fhir.validation.cli.services.StandAloneValidatorFetcher.IPackageInstaller;
|
||||
|
||||
public class StandAloneValidatorFetcher implements IValidatorResourceFetcher {
|
||||
|
||||
public interface IPackageInstaller {
|
||||
public void loadIg(String src, boolean recursive) throws IOException, FHIRException;
|
||||
}
|
||||
|
||||
private BasePackageCacheManager pcm;
|
||||
private IWorkerContext context;
|
||||
private IPackageInstaller installer;
|
||||
|
||||
public StandAloneValidatorFetcher(FilesystemPackageCacheManager pcm, IWorkerContext context, IPackageInstaller installer) {
|
||||
super();
|
||||
this.pcm = pcm;
|
||||
this.context = context;
|
||||
this.installer = installer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Element fetch(Object appContext, String url) throws FHIRFormatError, DefinitionException, FHIRException, IOException {
|
||||
throw new Error("Not done yet");
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReferenceValidationPolicy validationPolicy(Object appContext, String path, String url) {
|
||||
throw new Error("Not done yet");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean resolveURL(Object appContext, String path, String url) throws IOException, FHIRException {
|
||||
if (!Utilities.isAbsoluteUrl(url)) {
|
||||
return false;
|
||||
}
|
||||
// if we've got to here, it's a reference to a FHIR URL. We're going to try to resolve it on the fly
|
||||
|
||||
// first possibility: it's a reference to a version specific URL http://hl7.org/fhir/X.X/...
|
||||
VersionURLInfo vu = VersionUtilities.parseVersionUrl(url);
|
||||
if (vu != null) {
|
||||
NpmPackage pi = pcm.loadPackage(VersionUtilities.packageForVersion(vu.getVersion()), VersionUtilities.getCurrentVersion(vu.getVersion()));
|
||||
return pi.hasCanonical(vu.getUrl());
|
||||
}
|
||||
|
||||
// ok maybe it's a reference to a package we know
|
||||
String base = findBaseUrl(url);
|
||||
String pid = pcm.getPackageId(base);
|
||||
if (url.contains("|")) {
|
||||
pid = pid+"#"+url.substring(url.indexOf("|")+1);
|
||||
}
|
||||
if (pid != null) {
|
||||
installer.loadIg(pid, false);
|
||||
NpmPackage pi = pcm.loadPackage(pid);
|
||||
return pi.hasCanonical(url);
|
||||
}
|
||||
|
||||
if (!url.startsWith("http://hl7.org/fhir")) {
|
||||
return true; // we don't bother with those in the standalone validator - we assume they are valid
|
||||
}
|
||||
|
||||
// we assume it's invalid at this point
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
private String findBaseUrl(String url) {
|
||||
String[] p = url.split("\\/");
|
||||
for (int i = 1; i< p.length; i++) {
|
||||
if (Utilities.existsInList(p[i], context.getResourceNames())) {
|
||||
StringBuilder b = new StringBuilder(p[0]);
|
||||
for (int j = 1; j < i; j++) {
|
||||
b.append("/");
|
||||
b.append(p[j]);
|
||||
}
|
||||
return b.toString();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] fetchRaw(String url) throws MalformedURLException, IOException {
|
||||
throw new Error("Not done yet");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLocale(Locale locale) {
|
||||
throw new Error("Not done yet");
|
||||
}
|
||||
|
||||
}
|
|
@ -11,6 +11,7 @@ import org.hl7.fhir.r5.utils.ToolingExtensions;
|
|||
import org.hl7.fhir.utilities.TextFile;
|
||||
import org.hl7.fhir.utilities.Utilities;
|
||||
import org.hl7.fhir.validation.ValidationEngine;
|
||||
import org.hl7.fhir.validation.ValidationEngine.VersionSourceInformation;
|
||||
import org.hl7.fhir.validation.cli.model.*;
|
||||
|
||||
import java.io.File;
|
||||
|
@ -52,6 +53,15 @@ public class ValidationService {
|
|||
return response;
|
||||
}
|
||||
|
||||
public static VersionSourceInformation scanForVersions(CliContext cliContext) throws Exception {
|
||||
VersionSourceInformation versions = new VersionSourceInformation();
|
||||
ValidationEngine ve = new ValidationEngine();
|
||||
for (String src : cliContext.getIgs()) {
|
||||
ve.scanForIgVersion(src, cliContext.isRecursive(), versions);
|
||||
}
|
||||
ve.scanForVersions(cliContext.getSources(), versions);
|
||||
return versions;
|
||||
}
|
||||
public static void validateSources(CliContext cliContext, ValidationEngine validator, long loadStart) throws Exception {
|
||||
validator.doneLoading(loadStart);
|
||||
if (cliContext.getProfiles().size() > 0) {
|
||||
|
@ -205,6 +215,7 @@ public class ValidationService {
|
|||
validator.setSecurityChecks(cliContext.isSecurityChecks());
|
||||
validator.setCrumbTrails(cliContext.isCrumbTrails());
|
||||
validator.setShowTimes(cliContext.isShowTimes());
|
||||
validator.setFetcher(new StandAloneValidatorFetcher(validator.getPcm(), validator.getContext(), validator));
|
||||
TerminologyCache.setNoCaching(cliContext.isNoInternalCaching());
|
||||
return validator;
|
||||
}
|
||||
|
|
|
@ -151,6 +151,7 @@ import org.hl7.fhir.utilities.CommaSeparatedStringBuilder;
|
|||
import org.hl7.fhir.utilities.Utilities;
|
||||
import org.hl7.fhir.utilities.Utilities.DecimalStatus;
|
||||
import org.hl7.fhir.utilities.VersionUtilities;
|
||||
import org.hl7.fhir.utilities.VersionUtilities.VersionURLInfo;
|
||||
import org.hl7.fhir.utilities.validation.ValidationOptions;
|
||||
import org.hl7.fhir.utilities.validation.ValidationMessage;
|
||||
import org.hl7.fhir.utilities.validation.ValidationMessage.IssueSeverity;
|
||||
|
@ -592,8 +593,9 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
throw new FHIRException(e1);
|
||||
}
|
||||
timeTracker.load(t);
|
||||
if (e != null)
|
||||
if (e != null) {
|
||||
validate(appContext, errors, e, profiles);
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
|
@ -1856,7 +1858,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
if (fetcher != null) {
|
||||
boolean found;
|
||||
try {
|
||||
found = isDefinitionURL(url) || (allowExamples && (url.contains("example.org") || url.contains("acme.com"))) || (url.startsWith("http://hl7.org/fhir/tools")) || fetcher.resolveURL(appContext, path, url);
|
||||
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;
|
||||
}
|
||||
|
@ -2928,7 +2930,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
return rr;
|
||||
}
|
||||
}
|
||||
if (stack.getElement().getSpecial() == SpecialElement.BUNDLE_ENTRY) {
|
||||
if (stack.getElement().getSpecial() == SpecialElement.BUNDLE_ENTRY || stack.getElement().getSpecial() == SpecialElement.PARAMETER) {
|
||||
return null; // we don't try to resolve contained references across this boundary
|
||||
}
|
||||
stack = stack.getParent();
|
||||
|
@ -2963,6 +2965,18 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
return rr;
|
||||
}
|
||||
}
|
||||
if (stack.getElement().getSpecial() == SpecialElement.PARAMETER && stack.getParent() != null) {
|
||||
NodeStack tgt = findInParams(stack.getParent().getParent(), ref);
|
||||
if (tgt != null) {
|
||||
ResolvedReference rr = new ResolvedReference();
|
||||
rr.setResource(tgt.getElement());
|
||||
rr.setFocus(tgt.getElement());
|
||||
rr.setExternal(false);
|
||||
rr.setStack(tgt);
|
||||
rr.getStack().qualifyPath(".ofType("+tgt.getElement().fhirType()+")");
|
||||
return rr;
|
||||
}
|
||||
}
|
||||
stack = stack.getParent();
|
||||
}
|
||||
// we can get here if we got called via FHIRPath conformsTo which breaks the stack continuity.
|
||||
|
@ -2989,6 +3003,42 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
return null;
|
||||
}
|
||||
|
||||
private NodeStack findInParams(NodeStack params, String ref) {
|
||||
int i = 0;
|
||||
for (Element child : params.getElement().getChildren("parameter")) {
|
||||
NodeStack p = params.push(child, i, child.getProperty().getDefinition(), child.getProperty().getDefinition());
|
||||
if (child.hasChild("resource")) {
|
||||
Element res = child.getNamedChild("resource");
|
||||
if ((res.fhirType()+"/"+res.getIdBase()).equals(ref)) {
|
||||
return p.push(res, -1, res.getProperty().getDefinition(), res.getProperty().getDefinition());
|
||||
}
|
||||
}
|
||||
NodeStack pc = findInParamParts(p, child, ref);
|
||||
if (pc != null) {
|
||||
return pc;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private NodeStack findInParamParts(NodeStack pp, Element param, String ref) {
|
||||
int i = 0;
|
||||
for (Element child : param.getChildren("part")) {
|
||||
NodeStack p = pp.push(child, i, child.getProperty().getDefinition(), child.getProperty().getDefinition());
|
||||
if (child.hasChild("resource")) {
|
||||
Element res = child.getNamedChild("resource");
|
||||
if ((res.fhirType()+"/"+res.getIdBase()).equals(ref)) {
|
||||
return p.push(res, -1, res.getProperty().getDefinition(), res.getProperty().getDefinition());
|
||||
}
|
||||
}
|
||||
NodeStack pc = findInParamParts(p, child, ref);
|
||||
if (pc != null) {
|
||||
return pc;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private Element getEntryForSource(Element bundle, Element element) {
|
||||
List<Element> entries = new ArrayList<Element>();
|
||||
bundle.getNamedChildren(ENTRY, entries);
|
||||
|
@ -3432,7 +3482,18 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
for (Element profile : profiles) {
|
||||
StructureDefinition sd = context.fetchResource(StructureDefinition.class, profile.primitiveValue());
|
||||
if (!defn.getUrl().equals(profile.primitiveValue())) {
|
||||
if (warning(errors, IssueType.STRUCTURE, element.line(), element.col(), stack.getLiteralPath() + ".meta.profile[" + i + "]", sd != null, I18nConstants.VALIDATION_VAL_PROFILE_UNKNOWN, profile.primitiveValue())) {
|
||||
// is this a version specific reference?
|
||||
VersionURLInfo vu = VersionUtilities.parseVersionUrl(profile.primitiveValue());
|
||||
if (vu != null) {
|
||||
if (!VersionUtilities.versionsCompatible(vu.getVersion(), context.getVersion())) {
|
||||
hint(errors, IssueType.STRUCTURE, element.line(), element.col(), stack.getLiteralPath() + ".meta.profile[" + i + "]", false, I18nConstants.VALIDATION_VAL_PROFILE_OTHER_VERSION, vu.getVersion());
|
||||
} else if (vu.getUrl().equals(defn.getUrl())) {
|
||||
hint(errors, IssueType.STRUCTURE, element.line(), element.col(), stack.getLiteralPath() + ".meta.profile[" + i + "]", false, I18nConstants.VALIDATION_VAL_PROFILE_THIS_VERSION_OK);
|
||||
} else {
|
||||
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);
|
||||
|
@ -3658,9 +3719,6 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
if (trr == null) {
|
||||
rule(errors, IssueType.INFORMATIONAL, element.line(), element.col(), stack.getLiteralPath(), false, I18nConstants.BUNDLE_BUNDLE_ENTRY_TYPE, resourceName);
|
||||
} else if (isValidResourceType(resourceName, trr)) {
|
||||
long t = System.nanoTime();
|
||||
StructureDefinition profile = this.context.fetchResource(StructureDefinition.class, "http://hl7.org/fhir/StructureDefinition/" + resourceName);
|
||||
timeTracker.sd(t);
|
||||
// special case: resource wrapper is reset if we're crossing a bundle boundary, but not otherwise
|
||||
ValidatorHostContext hc = null;
|
||||
if (element.getSpecial() == SpecialElement.BUNDLE_ENTRY || element.getSpecial() == SpecialElement.BUNDLE_OUTCOME || element.getSpecial() == SpecialElement.PARAMETER) {
|
||||
|
@ -3669,10 +3727,29 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
} else {
|
||||
hc = hostContext.forContained(element);
|
||||
}
|
||||
trackUsage(profile, hostContext, element);
|
||||
stack.resetIds();
|
||||
if (rule(errors, IssueType.INVALID, element.line(), element.col(), stack.getLiteralPath(), profile != null, I18nConstants.BUNDLE_BUNDLE_ENTRY_NOPROFILE, resourceName)) {
|
||||
validateResource(hc, errors, resource, element, profile, idstatus, stack);
|
||||
if (trr.getProfile().size() == 1) {
|
||||
long t = System.nanoTime();
|
||||
StructureDefinition profile = this.context.fetchResource(StructureDefinition.class, trr.getProfile().get(0).asStringValue());
|
||||
timeTracker.sd(t);
|
||||
trackUsage(profile, hostContext, element);
|
||||
if (rule(errors, IssueType.INVALID, element.line(), element.col(), stack.getLiteralPath(), profile != null, I18nConstants.BUNDLE_BUNDLE_ENTRY_NOPROFILE, resourceName)) {
|
||||
validateResource(hc, errors, resource, element, profile, idstatus, stack);
|
||||
}
|
||||
} else if (trr.getProfile().size() == 0) {
|
||||
long t = System.nanoTime();
|
||||
StructureDefinition profile = this.context.fetchResource(StructureDefinition.class, "http://hl7.org/fhir/StructureDefinition/" + resourceName);
|
||||
timeTracker.sd(t);
|
||||
trackUsage(profile, hostContext, element);
|
||||
if (rule(errors, IssueType.INVALID, element.line(), element.col(), stack.getLiteralPath(), profile != null, I18nConstants.BUNDLE_BUNDLE_ENTRY_NOPROFILE, resourceName)) {
|
||||
validateResource(hc, errors, resource, element, profile, idstatus, stack);
|
||||
}
|
||||
} else {
|
||||
CommaSeparatedStringBuilder b = new CommaSeparatedStringBuilder();
|
||||
for (CanonicalType u : trr.getProfile()) {
|
||||
b.append(u.asStringValue());
|
||||
}
|
||||
rule(errors, IssueType.INVALID, element.line(), element.col(), stack.getLiteralPath(), false, I18nConstants.BUNDLE_BUNDLE_ENTRY_MULTIPLE_PROFILES, trr.getCode(), b.toString());
|
||||
}
|
||||
} else {
|
||||
List<String> types = new ArrayList<>();
|
||||
|
|
Loading…
Reference in New Issue