diff --git a/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/context/VersionConvertorContext.java b/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/context/VersionConvertorContext.java index dc6166e73..6d66422fb 100644 --- a/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/context/VersionConvertorContext.java +++ b/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/context/VersionConvertorContext.java @@ -126,7 +126,9 @@ public class VersionConvertorContext { */ public T getVersionConvertor() { T result = threadLocalVersionConverter.get(); - logger.debug(result.toString()); + if (result != null && logger != null) { + logger.debug(result.toString()); + } return result; } } \ No newline at end of file diff --git a/org.hl7.fhir.dstu2/src/main/java/org/hl7/fhir/dstu2/utils/client/FHIRToolingClient.java b/org.hl7.fhir.dstu2/src/main/java/org/hl7/fhir/dstu2/utils/client/FHIRToolingClient.java index 3ccdd546f..ad7fb0bf6 100644 --- a/org.hl7.fhir.dstu2/src/main/java/org/hl7/fhir/dstu2/utils/client/FHIRToolingClient.java +++ b/org.hl7.fhir.dstu2/src/main/java/org/hl7/fhir/dstu2/utils/client/FHIRToolingClient.java @@ -516,7 +516,7 @@ public class FHIRToolingClient { return p_out; } } catch (Exception e) { - handleException("Error performing operation '"+name+": "+e.getMessage()+"' (parameters = \"" + ps+"\")", e); + handleException("Error performing tx2 operation '"+name+": "+e.getMessage()+"' (parameters = \"" + ps+"\")", e); } return null; } diff --git a/org.hl7.fhir.dstu2016may/src/main/java/org/hl7/fhir/dstu2016may/utils/client/FHIRToolingClient.java b/org.hl7.fhir.dstu2016may/src/main/java/org/hl7/fhir/dstu2016may/utils/client/FHIRToolingClient.java index 4941c78e6..af955e0fb 100644 --- a/org.hl7.fhir.dstu2016may/src/main/java/org/hl7/fhir/dstu2016may/utils/client/FHIRToolingClient.java +++ b/org.hl7.fhir.dstu2016may/src/main/java/org/hl7/fhir/dstu2016may/utils/client/FHIRToolingClient.java @@ -488,39 +488,39 @@ public class FHIRToolingClient { // } - public Parameters operateType(Class resourceClass, String name, Parameters params) { - boolean complex = false; - for (ParametersParameterComponent p : params.getParameter()) - complex = complex || !(p.getValue() instanceof PrimitiveType); - Parameters searchResults = null; - String ps = ""; - try { - if (!complex) - for (ParametersParameterComponent p : params.getParameter()) - if (p.getValue() instanceof PrimitiveType) - ps += p.getName() + "=" + Utilities.encodeUri(((PrimitiveType) p.getValue()).asStringValue())+"&"; - ResourceRequest result; - if (complex) - result = utils.issuePostRequest(resourceAddress.resolveOperationURLFromClass(resourceClass, name, ps), utils.getResourceAsByteArray(params, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), TIMEOUT_OPERATION_LONG); - else - result = utils.issueGetResourceRequest(resourceAddress.resolveOperationURLFromClass(resourceClass, name, ps), getPreferredResourceFormat(), TIMEOUT_OPERATION_LONG); - result.addErrorStatus(410);//gone - result.addErrorStatus(404);//unknown - result.addSuccessStatus(200);//Only one for now - if(result.isUnsuccessfulRequest()) - throw new EFhirClientException("Server returned error code " + result.getHttpStatus(), (OperationOutcome)result.getPayload()); - if (result.getPayload() instanceof Parameters) - return (Parameters) result.getPayload(); - else { - Parameters p_out = new Parameters(); - p_out.addParameter().setName("return").setResource(result.getPayload()); - return p_out; - } - } catch (Exception e) { - handleException("Error performing operation '"+name+": "+e.getMessage()+"' (parameters = \"" + ps+"\")", e); - } - return null; - } + public Parameters operateType(Class resourceClass, String name, Parameters params) { + boolean complex = false; + for (ParametersParameterComponent p : params.getParameter()) + complex = complex || !(p.getValue() instanceof PrimitiveType); + Parameters searchResults = null; + String ps = ""; + try { + if (!complex) + for (ParametersParameterComponent p : params.getParameter()) + if (p.getValue() instanceof PrimitiveType) + ps += p.getName() + "=" + Utilities.encodeUri(((PrimitiveType) p.getValue()).asStringValue())+"&"; + ResourceRequest result; + if (complex) + result = utils.issuePostRequest(resourceAddress.resolveOperationURLFromClass(resourceClass, name, ps), utils.getResourceAsByteArray(params, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), TIMEOUT_OPERATION_LONG); + else + result = utils.issueGetResourceRequest(resourceAddress.resolveOperationURLFromClass(resourceClass, name, ps), getPreferredResourceFormat(), TIMEOUT_OPERATION_LONG); + result.addErrorStatus(410);//gone + result.addErrorStatus(404);//unknown + result.addSuccessStatus(200);//Only one for now + if(result.isUnsuccessfulRequest()) + throw new EFhirClientException("Server returned error code " + result.getHttpStatus(), (OperationOutcome)result.getPayload()); + if (result.getPayload() instanceof Parameters) + return (Parameters) result.getPayload(); + else { + Parameters p_out = new Parameters(); + p_out.addParameter().setName("return").setResource(result.getPayload()); + return p_out; + } + } catch (Exception e) { + handleException("Error performing 2b operation '"+name+": "+e.getMessage()+"' (parameters = \"" + ps+"\")", e); + } + return null; + } public Bundle transaction(Bundle batch) { diff --git a/org.hl7.fhir.dstu3/src/main/java/org/hl7/fhir/dstu3/utils/client/FHIRToolingClient.java b/org.hl7.fhir.dstu3/src/main/java/org/hl7/fhir/dstu3/utils/client/FHIRToolingClient.java index e9fa37ede..d09faeaef 100644 --- a/org.hl7.fhir.dstu3/src/main/java/org/hl7/fhir/dstu3/utils/client/FHIRToolingClient.java +++ b/org.hl7.fhir.dstu3/src/main/java/org/hl7/fhir/dstu3/utils/client/FHIRToolingClient.java @@ -277,11 +277,15 @@ public class FHIRToolingClient { URI url = resourceAddress.resolveOperationURLFromClass(resourceClass, name, ps); if (complex) { byte[] body = ByteUtils.resourceToByteArray(params, false, isJson(getPreferredResourceFormat())); - client.getLogger().logRequest("POST", url.toString(), null, body); + if (client.getLogger() != null) { + client.getLogger().logRequest("POST", url.toString(), null, body); + } result = client.issuePostRequest(url, body, getPreferredResourceFormat(), "POST " + resourceClass.getName() + "/$" + name, TIMEOUT_OPERATION_LONG); } else { - client.getLogger().logRequest("GET", url.toString(), null, null); + if (client.getLogger() != null) { + client.getLogger().logRequest("GET", url.toString(), null, null); + } result = client.issueGetResourceRequest(url, getPreferredResourceFormat(), generateHeaders(), "GET " + resourceClass.getName() + "/$" + name, TIMEOUT_OPERATION_LONG); } if (result.isUnsuccessfulRequest()) { @@ -295,7 +299,7 @@ public class FHIRToolingClient { return p_out; } } catch (Exception e) { - handleException("Error performing operation '"+name+": "+e.getMessage()+"' (parameters = \"" + ps+"\")", e); + handleException("Error performing tx3 operation '"+name+": "+e.getMessage()+"' (parameters = \"" + ps+"\")", e); } return null; } diff --git a/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/utils/client/FHIRToolingClient.java b/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/utils/client/FHIRToolingClient.java index eff092b62..8ec5c4abc 100644 --- a/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/utils/client/FHIRToolingClient.java +++ b/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/utils/client/FHIRToolingClient.java @@ -267,32 +267,36 @@ public class FHIRToolingClient { String ps = ""; try { if (!complex) - for (ParametersParameterComponent p : params.getParameter()) - if (p.getValue() instanceof PrimitiveType) - ps += p.getName() + "=" + Utilities.encodeUri(((PrimitiveType) p.getValue()).asStringValue()) + "&"; - ResourceRequest result; - URI url = resourceAddress.resolveOperationURLFromClass(resourceClass, name, ps); - if (complex) { - byte[] body = ByteUtils.resourceToByteArray(params, false, isJson(getPreferredResourceFormat())); - client.getLogger().logRequest("POST", url.toString(), null, body); - result = client.issuePostRequest(url, body, getPreferredResourceFormat(), - "POST " + resourceClass.getName() + "/$" + name, TIMEOUT_OPERATION_LONG); - } else { - client.getLogger().logRequest("GET", url.toString(), null, null); - result = client.issueGetResourceRequest(url, getPreferredResourceFormat(), generateHeaders(), "GET " + resourceClass.getName() + "/$" + name, TIMEOUT_OPERATION_LONG); - } - if (result.isUnsuccessfulRequest()) { - throw new EFhirClientException("Server returned error code " + result.getHttpStatus(), (OperationOutcome) result.getPayload()); - } - if (result.getPayload() instanceof Parameters) { - return (Parameters) result.getPayload(); - } else { - Parameters p_out = new Parameters(); - p_out.addParameter().setName("return").setResource(result.getPayload()); - return p_out; - } + for (ParametersParameterComponent p : params.getParameter()) + if (p.getValue() instanceof PrimitiveType) + ps += p.getName() + "=" + Utilities.encodeUri(((PrimitiveType) p.getValue()).asStringValue()) + "&"; + ResourceRequest result; + URI url = resourceAddress.resolveOperationURLFromClass(resourceClass, name, ps); + if (complex) { + byte[] body = ByteUtils.resourceToByteArray(params, false, isJson(getPreferredResourceFormat())); + if (client.getLogger() != null) { + client.getLogger().logRequest("POST", url.toString(), null, body); + } + result = client.issuePostRequest(url, body, getPreferredResourceFormat(), + "POST " + resourceClass.getName() + "/$" + name, TIMEOUT_OPERATION_LONG); + } else { + if (client.getLogger() != null) { + client.getLogger().logRequest("GET", url.toString(), null, null); + } + result = client.issueGetResourceRequest(url, getPreferredResourceFormat(), generateHeaders(), "GET " + resourceClass.getName() + "/$" + name, TIMEOUT_OPERATION_LONG); + } + if (result.isUnsuccessfulRequest()) { + throw new EFhirClientException("Server returned error code " + result.getHttpStatus(), (OperationOutcome) result.getPayload()); + } + if (result.getPayload() instanceof Parameters) { + return (Parameters) result.getPayload(); + } else { + Parameters p_out = new Parameters(); + p_out.addParameter().setName("return").setResource(result.getPayload()); + return p_out; + } } catch (Exception e) { - handleException("Error performing operation '"+name+": "+e.getMessage()+"' (parameters = \"" + ps+"\")", e); + handleException("Error performing tx4 operation '"+name+": "+e.getMessage()+"' (parameters = \"" + ps+"\")", e); } return null; } diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/conformance/ProfileUtilities.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/conformance/ProfileUtilities.java index 65852093e..64d7a010c 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/conformance/ProfileUtilities.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/conformance/ProfileUtilities.java @@ -2452,19 +2452,19 @@ public class ProfileUtilities extends TranslatingUtilities { if (webUrl != null) { // also, must touch up the markdown if (element.hasDefinition()) - element.setDefinition(processRelativeUrls(element.getDefinition(), webUrl)); + element.setDefinition(processRelativeUrls(element.getDefinition(), webUrl, baseSpecUrl())); if (element.hasComment()) - element.setComment(processRelativeUrls(element.getComment(), webUrl)); + element.setComment(processRelativeUrls(element.getComment(), webUrl, baseSpecUrl())); if (element.hasRequirements()) - element.setRequirements(processRelativeUrls(element.getRequirements(), webUrl)); + element.setRequirements(processRelativeUrls(element.getRequirements(), webUrl, baseSpecUrl())); if (element.hasMeaningWhenMissing()) - element.setMeaningWhenMissing(processRelativeUrls(element.getMeaningWhenMissing(), webUrl)); + element.setMeaningWhenMissing(processRelativeUrls(element.getMeaningWhenMissing(), webUrl, baseSpecUrl())); } } return element; } - private String processRelativeUrls(String markdown, String webUrl) { + public static String processRelativeUrls(String markdown, String webUrl, String basePath) { StringBuilder b = new StringBuilder(); int i = 0; while (i < markdown.length()) { @@ -2487,7 +2487,7 @@ public class ProfileUtilities extends TranslatingUtilities { // if (isLikelySourceURLReference(url)) { b.append("]("); - b.append(baseSpecUrl()); + b.append(basePath); i = i + 1; } else { b.append("]("); @@ -2507,11 +2507,13 @@ public class ProfileUtilities extends TranslatingUtilities { } - private boolean isLikelySourceURLReference(String url) { + public static boolean isLikelySourceURLReference(String url) { return url.startsWith("extensibility.html") || + url.startsWith("terminologies.html") || url.startsWith("observation.html") || url.startsWith("datatypes.html") || + url.startsWith("narrative.html") || (url.startsWith("extension-") || url.contains(".html")) || url.startsWith("resource-definitions.html"); } diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/BaseWorkerContext.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/BaseWorkerContext.java index 661d7f566..9dfe7e7ee 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/BaseWorkerContext.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/BaseWorkerContext.java @@ -906,9 +906,9 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte pIn.addParameter().setName("implySystem").setValue(new BooleanType(true)); } setTerminologyOptions(options, pIn); - res = validateOnServer(vs, pIn); + res = validateOnServer(vs, pIn, options); } catch (Exception e) { - res = new ValidationResult(IssueSeverity.ERROR, e.getMessage() == null ? e.getClass().getName() : e.getMessage()).setTxLink(txLog == null ? null : txLog.getLastId()); + res = new ValidationResult(IssueSeverity.ERROR, e.getMessage() == null ? e.getClass().getName() : e.getMessage()).setTxLink(txLog == null ? null : txLog.getLastId()).setErrorClass(TerminologyServiceErrorClass.SERVER_ERROR); } if (res.getErrorClass() == TerminologyServiceErrorClass.CODESYSTEM_UNSUPPORTED) { unsupportedCodeSystems.add(code.getSystem()); @@ -967,7 +967,7 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte Parameters pIn = new Parameters(); pIn.addParameter().setName("codeableConcept").setValue(code); setTerminologyOptions(options, pIn); - res = validateOnServer(vs, pIn); + res = validateOnServer(vs, pIn, options); } catch (Exception e) { res = new ValidationResult(IssueSeverity.ERROR, e.getMessage() == null ? e.getClass().getName() : e.getMessage()).setTxLink(txLog.getLastId()); } @@ -975,7 +975,7 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte return res; } - private ValidationResult validateOnServer(ValueSet vs, Parameters pin) throws FHIRException { + private ValidationResult validateOnServer(ValueSet vs, Parameters pin, ValidationOptions options) throws FHIRException { boolean cache = false; if (vs != null) { for (ConceptSetComponent inc : vs.getCompose().getInclude()) { @@ -988,6 +988,8 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte if (vs != null) { if (isTxCaching && cacheId != null && cached.contains(vs.getUrl()+"|"+vs.getVersion())) { pin.addParameter().setName("url").setValue(new UriType(vs.getUrl()+(vs.hasVersion() ? "|"+vs.getVersion() : ""))); + } else if (options.getVsAsUrl()){ + pin.addParameter().setName("url").setValue(new StringType(vs.getUrl())); } else { pin.addParameter().setName("valueSet").setResource(vs); cached.add(vs.getUrl()+"|"+vs.getVersion()); diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/IWorkerContext.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/IWorkerContext.java index 2d1c648af..0c189fb18 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/IWorkerContext.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/IWorkerContext.java @@ -613,6 +613,11 @@ public interface IWorkerContext { return this; } + public ValidationResult setErrorClass(TerminologyServiceErrorClass errorClass) { + this.errorClass = errorClass; + return this; + } + public String getTxLink() { return txLink; } diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/Element.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/Element.java index d306c414b..c46e85c01 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/Element.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/Element.java @@ -634,7 +634,14 @@ public class Element extends Base { @Override public String toString() { - return name+"="+fhirType() + "["+(children == null || hasValue() ? value : Integer.toString(children.size())+" children")+"]"; + if (name.equals(fhirType()) && isResource()) { + return fhirType()+"/"+getIdBase() + "["+(children == null || hasValue() ? value : Integer.toString(children.size())+" children")+"]"; + + } else if (isResource()) { + return name+"="+fhirType()+"/"+getIdBase()+ "["+(children == null || hasValue() ? value : Integer.toString(children.size())+" children")+"]"; + } else { + return name+"="+fhirType() + "["+(children == null || hasValue() ? value : Integer.toString(children.size())+" children")+"]"; + } } @Override diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/Manager.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/Manager.java index be9918f74..0bfcf8f90 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/Manager.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/Manager.java @@ -62,6 +62,8 @@ public class Manager { return "txt"; case VBAR: return "hl7"; + case SHC: + return "shc"; } return null; } diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/CodeSystemRenderer.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/CodeSystemRenderer.java index 7af63b922..f9618e79f 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/CodeSystemRenderer.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/CodeSystemRenderer.java @@ -422,7 +422,7 @@ public class CodeSystemRenderer extends TerminologyRenderer { if (first) first = false; else td.addText(", "); if (pcv.hasValueCoding()) { td.addText(pcv.getValueCoding().getCode()); - } else if (pcv.hasValueStringType() && Utilities.isAbsoluteUrl(pcv.getValue().primitiveValue())) { + } else if (pcv.hasValueStringType() && Utilities.isAbsoluteUrlLinkable(pcv.getValue().primitiveValue())) { td.ah(pcv.getValue().primitiveValue()).tx(pcv.getValue().primitiveValue()); } else { td.addText(pcv.getValue().primitiveValue()); diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/ProfileDrivenRenderer.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/ProfileDrivenRenderer.java index c7420060a..6eb2606ef 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/ProfileDrivenRenderer.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/ProfileDrivenRenderer.java @@ -450,8 +450,10 @@ public class ProfileDrivenRenderer extends ResourceRenderer { x.addText(((Enumeration) e).getValue().toString()); // todo: look up a display name if there is one return true; } else if (e instanceof BooleanType) { - if (((BooleanType) e).getValue()) { + if (((BooleanType) e).hasValue()) { x.addText(name); + x.addText(": "); + x.addText(((BooleanType) e).getValueAsString()); return true; } } else if (e instanceof CodeableReference) { diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/QuestionnaireRenderer.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/QuestionnaireRenderer.java index 4c9769072..3bb0e805c 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/QuestionnaireRenderer.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/QuestionnaireRenderer.java @@ -1013,7 +1013,7 @@ public class QuestionnaireRenderer extends TerminologyRenderer { private void defn(XhtmlNode tbl, String name, String url, Resource res) throws UnsupportedEncodingException, IOException { if (res != null && res.hasUserData("path")) { defn(tbl, "Definition", RendererFactory.factory(res, context).display(res), res.getUserString("path")); - } else if (Utilities.isAbsoluteUrl(url)) { + } else if (Utilities.isAbsoluteUrlLinkable(url)) { defn(tbl, "Definition", url, url); } { defn(tbl, "Definition", url); diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/spreadsheets/SpreadsheetGenerator.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/spreadsheets/SpreadsheetGenerator.java index 50318e3b9..49a50dc77 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/spreadsheets/SpreadsheetGenerator.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/spreadsheets/SpreadsheetGenerator.java @@ -84,7 +84,7 @@ public class SpreadsheetGenerator { if (name.length() > MAX_SENSITIVE_SHEET_NAME_LEN - 2) { name = name.substring(0, MAX_SENSITIVE_SHEET_NAME_LEN - 2); } - String s = name; + String s = fixSheetNameChars(name); if (sheetNames.contains(s)) { int i = 1; do { @@ -96,6 +96,26 @@ public class SpreadsheetGenerator { return wb.createSheet(s); } + private String fixSheetNameChars(String name) { + StringBuilder b = new StringBuilder(); + for (char ch : name.toCharArray()) { + switch (ch) { + case '/': + case '\\': + case '?': + case '*': + case ']': + case '[': + case ':': + b.append('_'); + break; + default: + b.append(ch); + } + } + return b.toString(); + } + private static Map createStyles(Workbook wb){ Map styles = new HashMap<>(); diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/spreadsheets/StructureDefinitionSpreadsheetGenerator.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/spreadsheets/StructureDefinitionSpreadsheetGenerator.java index 1d10c3f97..b7e34eca4 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/spreadsheets/StructureDefinitionSpreadsheetGenerator.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/spreadsheets/StructureDefinitionSpreadsheetGenerator.java @@ -82,9 +82,9 @@ public class StructureDefinitionSpreadsheetGenerator extends CanonicalSpreadshee "Slicing Discriminator", "Slicing Description", "Slicing Ordered", "Slicing Rules", "Base Path", "Base Min", "Base Max", "Condition(s)", "Constraint(s)"}; - public StructureDefinitionSpreadsheetGenerator(IWorkerContext context, boolean asXml, boolean hideMustSupportFalse) { + public StructureDefinitionSpreadsheetGenerator(IWorkerContext context, boolean valuesAsXml, boolean hideMustSupportFalse) { super(context); - this.asXml = asXml; + this.asXml = valuesAsXml; this.hideMustSupportFalse = hideMustSupportFalse; } diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/client/FHIRToolingClient.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/client/FHIRToolingClient.java index b0cadeb71..66e93dc91 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/client/FHIRToolingClient.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/client/FHIRToolingClient.java @@ -299,37 +299,40 @@ public class FHIRToolingClient { String ps = ""; try { if (!complex) - for (ParametersParameterComponent p : params.getParameter()) - if (p.getValue() instanceof PrimitiveType) - ps += p.getName() + "=" + Utilities.encodeUri(((PrimitiveType) p.getValue()).asStringValue()) + "&"; - ResourceRequest result; - URI url = resourceAddress.resolveOperationURLFromClass(resourceClass, name, ps); - if (complex) { - byte[] body = ByteUtils.resourceToByteArray(params, false, isJson(getPreferredResourceFormat())); - client.getLogger().logRequest("POST", url.toString(), null, body); - result = client.issuePostRequest(url, body, getPreferredResourceFormat(), - "POST " + resourceClass.getName() + "/$" + name, TIMEOUT_OPERATION_LONG); - } else { - client.getLogger().logRequest("GET", url.toString(), null, null); - result = client.issueGetResourceRequest(url, getPreferredResourceFormat(), generateHeaders(), "GET " + resourceClass.getName() + "/$" + name, TIMEOUT_OPERATION_LONG); - } - if (result.isUnsuccessfulRequest()) { - throw new EFhirClientException("Server returned error code " + result.getHttpStatus(), (OperationOutcome) result.getPayload()); - } - if (result.getPayload() instanceof Parameters) { - return (Parameters) result.getPayload(); - } else { - Parameters p_out = new Parameters(); - p_out.addParameter().setName("return").setResource(result.getPayload()); - return p_out; - } + for (ParametersParameterComponent p : params.getParameter()) + if (p.getValue() instanceof PrimitiveType) + ps += p.getName() + "=" + Utilities.encodeUri(((PrimitiveType) p.getValue()).asStringValue()) + "&"; + ResourceRequest result; + URI url = resourceAddress.resolveOperationURLFromClass(resourceClass, name, ps); + if (complex) { + byte[] body = ByteUtils.resourceToByteArray(params, false, isJson(getPreferredResourceFormat())); + if (client.getLogger() != null) { + client.getLogger().logRequest("POST", url.toString(), null, body); + } + result = client.issuePostRequest(url, body, getPreferredResourceFormat(), + "POST " + resourceClass.getName() + "/$" + name, TIMEOUT_OPERATION_LONG); + } else { + if (client.getLogger() != null) { + client.getLogger().logRequest("GET", url.toString(), null, null); + } + result = client.issueGetResourceRequest(url, getPreferredResourceFormat(), generateHeaders(), "GET " + resourceClass.getName() + "/$" + name, TIMEOUT_OPERATION_LONG); + } + if (result.isUnsuccessfulRequest()) { + throw new EFhirClientException("Server returned error code " + result.getHttpStatus(), (OperationOutcome) result.getPayload()); + } + if (result.getPayload() instanceof Parameters) { + return (Parameters) result.getPayload(); + } else { + Parameters p_out = new Parameters(); + p_out.addParameter().setName("return").setResource(result.getPayload()); + return p_out; + } } catch (Exception e) { - handleException("Error performing operation '"+name+": "+e.getMessage()+"' (parameters = \"" + ps+"\")", e); + handleException("Error performing tx5 operation '"+name+": "+e.getMessage()+"' (parameters = \"" + ps+"\")", e); } return null; } - public Bundle transaction(Bundle batch) { Bundle transactionResult = null; try { diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/Utilities.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/Utilities.java index 5679a06e0..9fce7c0f0 100644 --- a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/Utilities.java +++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/Utilities.java @@ -1098,7 +1098,17 @@ public class Utilities { if (ref != null && ref.contains(":")) { String scheme = ref.substring(0, ref.indexOf(":")); String details = ref.substring(ref.indexOf(":")+1); - return (existsInList(scheme, "http", "https", "urn") || isToken(scheme) || Utilities.startsWithInList(ref, "urn:iso:", "urn:iso-iec:", "urn:iso-cie:", "urn:iso-astm:", "urn:iso-ieee:", "urn:iec:")) + return (existsInList(scheme, "http", "https", "urn") || (isToken(scheme) && scheme.equals(scheme.toLowerCase())) || Utilities.startsWithInList(ref, "urn:iso:", "urn:iso-iec:", "urn:iso-cie:", "urn:iso-astm:", "urn:iso-ieee:", "urn:iec:")) + && details != null && details.length() > 0 && !details.contains(" "); // rfc5141 + } + return false; + } + + public static boolean isAbsoluteUrlLinkable(String ref) { + if (ref != null && ref.contains(":")) { + String scheme = ref.substring(0, ref.indexOf(":")); + String details = ref.substring(ref.indexOf(":")+1); + return (existsInList(scheme, "http", "https", "ftp")) && details != null && details.length() > 0 && !details.contains(" "); // rfc5141 } return false; diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/VersionUtilities.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/VersionUtilities.java index 5cba7179a..18640920f 100644 --- a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/VersionUtilities.java +++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/VersionUtilities.java @@ -135,7 +135,7 @@ public class VersionUtilities { } public static boolean isR5Ver(String ver) { - return ver != null && ver.startsWith(CURRENT_VERSION); + return ver != null && (ver.startsWith(CURRENT_VERSION) || ver.equals("current")); } public static boolean isR4BVer(String ver) { diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/npm/FilesystemPackageCacheManager.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/npm/FilesystemPackageCacheManager.java index f32a740f3..750e6cbb6 100644 --- a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/npm/FilesystemPackageCacheManager.java +++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/npm/FilesystemPackageCacheManager.java @@ -84,7 +84,7 @@ public class FilesystemPackageCacheManager extends BasePackageCacheManager imple public static final String SECONDARY_SERVER = "https://packages2.fhir.org/packages"; // private static final String SECONDARY_SERVER = "http://local.fhir.org:960/packages"; public static final String PACKAGE_REGEX = "^[a-zA-Z][A-Za-z0-9\\_\\-]*(\\.[A-Za-z0-9\\_\\-]+)+$"; - public static final String PACKAGE_VERSION_REGEX = "^[A-Za-z][A-Za-z0-9\\_\\-]*(\\.[A-Za-z0-9\\_\\-]+)+\\#[A-Za-z0-9\\-\\_]+(\\.[A-Za-z0-9\\-\\_]+)*$"; + public static final String PACKAGE_VERSION_REGEX = "^[A-Za-z][A-Za-z0-9\\_\\-]*(\\.[A-Za-z0-9\\_\\-]+)+\\#[A-Za-z0-9\\-\\_\\$]+(\\.[A-Za-z0-9\\-\\_\\$]+)*$"; public static final String PACKAGE_VERSION_REGEX_OPT = "^[A-Za-z][A-Za-z0-9\\_\\-]*(\\.[A-Za-z0-9\\_\\-]+)+(\\#[A-Za-z0-9\\-\\_]+(\\.[A-Za-z0-9\\-\\_]+)*)?$"; private static final Logger ourLog = LoggerFactory.getLogger(FilesystemPackageCacheManager.class); private static final String CACHE_VERSION = "3"; // second version - see wiki page @@ -195,7 +195,7 @@ public class FilesystemPackageCacheManager extends BasePackageCacheManager imple throw new FHIRException("Cannot add package " + id + " to the package cache - the version '" + version + "' is illegal in this context"); } for (char ch : version.toCharArray()) { - if (!Character.isAlphabetic(ch) && !Character.isDigit(ch) && !Utilities.existsInList(ch, '.', '-')) { + if (!Character.isAlphabetic(ch) && !Character.isDigit(ch) && !Utilities.existsInList(ch, '.', '-', '$')) { throw new FHIRException("Cannot add package " + id + " to the package cache - the version '" + version + "' is illegal (ch '" + ch + "'"); } } @@ -503,9 +503,9 @@ public class FilesystemPackageCacheManager extends BasePackageCacheManager imple // nup, don't have it locally (or it's expired) FilesystemPackageCacheManager.InputStreamWithSrc source; - if ("current".equals(version)) { + if ("current".equals(version) || version.startsWith("current$")) { // special case - fetch from ci-build server - source = loadFromCIBuild(id); + source = loadFromCIBuild(id, version.startsWith("current$") ? version.substring(8) : null); } else { source = loadFromPackageServer(id, version); } @@ -524,15 +524,20 @@ public class FilesystemPackageCacheManager extends BasePackageCacheManager imple if (optional) return null; else - throw new FHIRException(e.getMessage(), e); + throw new FHIRException("Unable to fetch: "+e.getMessage(), e); } } - private InputStreamWithSrc loadFromCIBuild(String id) throws IOException { + private InputStreamWithSrc loadFromCIBuild(String id, String branch) throws IOException { checkBuildLoaded(); if (ciList.containsKey(id)) { - InputStream stream = fetchFromUrlSpecific(Utilities.pathURL(ciList.get(id), "package.tgz"), false); - return new InputStreamWithSrc(stream, Utilities.pathURL(ciList.get(id), "package.tgz"), "current"); + if (branch == null) { + InputStream stream = fetchFromUrlSpecific(Utilities.pathURL(ciList.get(id), "package.tgz"), false); + return new InputStreamWithSrc(stream, Utilities.pathURL(ciList.get(id), "package.tgz"), "current"); + } else { + InputStream stream = fetchFromUrlSpecific(Utilities.pathURL(ciList.get(id), "branches", branch, "package.tgz"), false); + return new InputStreamWithSrc(stream, Utilities.pathURL(ciList.get(id), "branches", branch, "package.tgz"), "current$"+branch); + } } else if (id.startsWith("hl7.fhir.r5")) { InputStream stream = fetchFromUrlSpecific(Utilities.pathURL("http://build.fhir.org", id + ".tgz"), false); return new InputStreamWithSrc(stream, Utilities.pathURL("http://build.fhir.org", id + ".tgz"), "current"); diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/validation/ValidationMessage.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/validation/ValidationMessage.java index e54ad176a..f191bb0d0 100644 --- a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/validation/ValidationMessage.java +++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/validation/ValidationMessage.java @@ -514,6 +514,7 @@ public class ValidationMessage implements Comparator, Compara public String[] sliceText; private boolean slicingHint; private boolean signpost; + private boolean criticalSignpost; /** @@ -772,9 +773,10 @@ public class ValidationMessage implements Comparator, Compara return sliceHtml; } - public void setSliceHtml(String sliceHtml, String[] text) { + public ValidationMessage setSliceHtml(String sliceHtml, String[] text) { this.sliceHtml = sliceHtml; this.sliceText = text; + return this; } public String getMessageId() { @@ -795,5 +797,14 @@ public class ValidationMessage implements Comparator, Compara return this; } + public boolean isCriticalSignpost() { + return criticalSignpost; + } + + public ValidationMessage setCriticalSignpost(boolean criticalSignpost) { + this.criticalSignpost = criticalSignpost; + return this; + } + } \ No newline at end of file diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/validation/ValidationOptions.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/validation/ValidationOptions.java index ad4325d11..1da961eb1 100644 --- a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/validation/ValidationOptions.java +++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/validation/ValidationOptions.java @@ -11,6 +11,7 @@ public class ValidationOptions { private boolean useClient = true; private boolean guessSystem = false; private ValueSetMode valueSetMode = ValueSetMode.ALL_CHECKS; + private boolean vsAsUrl; public ValidationOptions() { super(); @@ -42,7 +43,8 @@ public class ValidationOptions { ValidationOptions n = new ValidationOptions(language); n.useServer = useServer; n.useClient = useClient; - n.guessSystem = guessSystem; + n.guessSystem = guessSystem; + n.vsAsUrl = vsAsUrl; return n; } @@ -96,5 +98,14 @@ public class ValidationOptions { return valueSetMode; } + public ValidationOptions setVsAsUrl() { + vsAsUrl = true; + return this; + } + + public boolean getVsAsUrl() { + return vsAsUrl; + } + } \ No newline at end of file diff --git a/org.hl7.fhir.utilities/src/main/resources/Messages.properties b/org.hl7.fhir.utilities/src/main/resources/Messages.properties index 11b60a0dd..a537bd170 100644 --- a/org.hl7.fhir.utilities/src/main/resources/Messages.properties +++ b/org.hl7.fhir.utilities/src/main/resources/Messages.properties @@ -229,7 +229,6 @@ Validation_VAL_Profile_SliceOrder = As specified by profile {0}, Element ''{1}'' 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}'') XHTML_XHTML_Element_Illegal = Illegal element name in the XHTML (''{0}'') @@ -503,7 +502,7 @@ TYPE_SPECIFIC_CHECKS_DT_ATT_TOO_LONG = Attachment size is {0} bytes which exceed TYPE_SPECIFIC_CHECKS_DT_ATT_NO_CONTENT = Attachments have data and/or url, or else SHOULD have either contentType and/or language TYPE_SPECIFIC_CHECKS_DT_BASE64_TOO_LONG = Base64 size is {0} bytes which exceeds the stated limit of {1} bytes TYPE_SPECIFIC_CHECKS_DT_DECIMAL_CHARS = Found {0} decimal places which exceeds the stated limit of {1} digits -Validation_VAL_Profile_WrongType = Specified profile type was ''{0}'', but found type ''{1}'' +Validation_VAL_Profile_WrongType = Specified profile type was ''{0}'' in profile ''{2}'', but found type ''{1}'' Validation_VAL_Profile_WrongType2 = Type mismatch processing profile {0} at path {1}: The element type is {4}, but the profile {3} is for a different type {2} VALIDATION_VAL_ILLEGAL_TYPE_CONSTRAINT = Illegal constraint in profile {0} at path {1} - cannot constrain to type {2} from base types {3} EXTENSION_EXT_CONTEXT_WRONG_XVER = The extension {0} from FHIR version {3} is not allowed to be used at this point (allowed = {1}; this element is [{2}; this is a warning since contexts may be renamed between FHIR versions) diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/BaseValidator.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/BaseValidator.java index 72c442f39..82d2b48a6 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/BaseValidator.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/BaseValidator.java @@ -2,7 +2,11 @@ package org.hl7.fhir.validation; import static org.apache.commons.lang3.StringUtils.isBlank; +import java.text.DateFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; import java.util.ArrayList; +import java.util.Date; import java.util.HashMap; /* @@ -262,9 +266,9 @@ public class BaseValidator { * @return Returns thePass (in other words, returns true if the rule did not fail validation) */ //FIXME: formatMessage should be done here - protected boolean slicingHint(List errors, IssueType type, int line, int col, String path, boolean thePass, String msg, String html, String[] text) { + protected boolean slicingHint(List errors, IssueType type, int line, int col, String path, boolean thePass, boolean isCritical, String msg, String html, String[] text) { if (!thePass) { - addValidationMessage(errors, type, line, col, path, msg, IssueSeverity.INFORMATION, null).setSlicingHint(true).setSliceHtml(html, text); + addValidationMessage(errors, type, line, col, path, msg, IssueSeverity.INFORMATION, null).setSlicingHint(true).setSliceHtml(html, text).setCriticalSignpost(isCritical); } return thePass; } diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/IgLoader.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/IgLoader.java index bcf4283f1..23629104d 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/IgLoader.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/IgLoader.java @@ -139,6 +139,8 @@ public class IgLoader { res.cntType = Manager.FhirFormat.XML; else if (t.getKey().endsWith(".ttl")) res.cntType = Manager.FhirFormat.TURTLE; + else if (t.getKey().endsWith(".shc")) + res.cntType = Manager.FhirFormat.SHC; else if (t.getKey().endsWith(".txt") || t.getKey().endsWith(".map")) res.cntType = Manager.FhirFormat.TEXT; else diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/ValidatorCli.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/ValidatorCli.java index adcd3bf30..bfdca65e4 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/ValidatorCli.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/ValidatorCli.java @@ -71,6 +71,8 @@ import org.hl7.fhir.validation.cli.utils.*; import java.io.File; import java.net.Authenticator; import java.net.PasswordAuthentication; +import java.util.ArrayList; +import java.util.List; /** * A executable class that will validate one or more FHIR resources against @@ -101,6 +103,8 @@ public class ValidatorCli { TimeTracker tt = new TimeTracker(); TimeTracker.Session tts = tt.start("Loading"); + args = preProcessArgs(args); + Display.displayVersion(); Display.displaySystemInfo(); @@ -160,6 +164,35 @@ public class ValidatorCli { } } + private static String[] preProcessArgs(String[] args) { + // ips$branch --> -version 4.0 -ig hl7.fhir.uv.ips#current$connectathon-2 -profile http://hl7.org/fhir/uv/ips/StructureDefinition/Bundle-uv-ips + List res = new ArrayList<>(); + for (String a : args) { + if (a.equals("-ips")) { + res.add("-version"); + res.add("4.0"); + res.add("-ig"); + res.add("hl7.fhir.uv.ips#current$connectathon-2"); + res.add("-profile"); + res.add("http://hl7.org/fhir/uv/ips/StructureDefinition/Bundle-uv-ips"); + } else if (a.startsWith("-ips$")) { + res.add("-version"); + res.add("4.0"); + res.add("-ig"); + res.add("hl7.fhir.uv.ips#current$"+a.substring(5)); + res.add("-profile"); + res.add("http://hl7.org/fhir/uv/ips/StructureDefinition/Bundle-uv-ips"); + } else { + res.add(a); + } + } + String[] r = new String[res.size()]; + for (int i = 0; i < res.size(); i++) { + r[i] = res.get(i); + } + return r; + } + private static boolean destinationDirectoryValid(String dest) { if (dest == null) { System.out.println("no -dest parameter provided"); diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/services/ValidationService.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/services/ValidationService.java index 877fd6be2..6f0e22679 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/services/ValidationService.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/services/ValidationService.java @@ -293,14 +293,10 @@ public class ValidationService { System.out.println((error == 0 ? "Success" : "*FAILURE*") + ": " + Integer.toString(error) + " errors, " + Integer.toString(warn) + " warnings, " + Integer.toString(info) + " notes"); for (OperationOutcome.OperationOutcomeIssueComponent issue : oo.getIssue()) { System.out.println(getIssueSummary(issue)); - if (crumbs) { - ValidationMessage vm = (ValidationMessage) issue.getUserData("source.msg"); - if (vm != null) { - if (vm.sliceText != null) { - for (String s : vm.sliceText) { - System.out.println(" slice info: "+s); - } - } + ValidationMessage vm = (ValidationMessage) issue.getUserData("source.msg"); + if (vm != null && vm.sliceText != null && (crumbs || vm.isCriticalSignpost())) { + for (String s : vm.sliceText) { + System.out.println(" slice info: "+s); } } } diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/InstanceValidator.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/InstanceValidator.java index 45d71ff96..192c9c902 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/InstanceValidator.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/InstanceValidator.java @@ -93,6 +93,7 @@ import org.hl7.fhir.r5.model.ElementDefinition.DiscriminatorType; import org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionBindingComponent; import org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionConstraintComponent; import org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionMappingComponent; +import org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionSlicingComponent; import org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionSlicingDiscriminatorComponent; import org.hl7.fhir.r5.model.ElementDefinition.PropertyRepresentation; import org.hl7.fhir.r5.model.ElementDefinition.TypeRefComponent; @@ -303,7 +304,11 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat } } else if (item instanceof Element) { Element e = (Element) item; - self.validateResource(new ValidatorHostContext(ctxt.getAppContext(), e), valerrors, e, e, sd, IdStatus.OPTIONAL, new NodeStack(context, null, e, validationLanguage)); + if (e.getName().equals("contained")) { + self.validateResource(new ValidatorHostContext(ctxt.getAppContext(), e, ctxt.getRootResource()), valerrors, e, e, sd, IdStatus.OPTIONAL, new NodeStack(context, null, e, validationLanguage)); + } else { + self.validateResource(new ValidatorHostContext(ctxt.getAppContext(), e), valerrors, e, e, sd, IdStatus.OPTIONAL, new NodeStack(context, null, e, validationLanguage)); + } } else throw new NotImplementedException(context.formatMessage(I18nConstants.NOT_DONE_YET_VALIDATORHOSTSERVICESCONFORMSTOPROFILE_WHEN_ITEM_IS_NOT_AN_ELEMENT)); boolean ok = true; @@ -2753,7 +2758,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat if (!isShowMessagesFromReferences()) { rule(errors, IssueType.STRUCTURE, element.line(), element.col(), path, areAllBaseProfiles(profiles), I18nConstants.REFERENCE_REF_CANTMATCHCHOICE, ref, asList(type.getTargetProfile())); for (StructureDefinition sd : badProfiles.keySet()) { - slicingHint(errors, IssueType.STRUCTURE, element.line(), element.col(), path, false, + slicingHint(errors, IssueType.STRUCTURE, element.line(), element.col(), path, false, false, context.formatMessage(I18nConstants.DETAILS_FOR__MATCHING_AGAINST_PROFILE_, ref, sd.getUrl()), errorSummaryForSlicingAsHtml(badProfiles.get(sd)), errorSummaryForSlicingAsText(badProfiles.get(sd))); } @@ -2771,7 +2776,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat if (!isShowMessagesFromReferences()) { warning(errors, IssueType.STRUCTURE, element.line(), element.col(), path, false, I18nConstants.REFERENCE_REF_MULTIPLEMATCHES, ref, asListByUrl(goodProfiles.keySet())); for (StructureDefinition sd : badProfiles.keySet()) { - slicingHint(errors, IssueType.STRUCTURE, element.line(), element.col(), path, false, context.formatMessage(I18nConstants.DETAILS_FOR__MATCHING_AGAINST_PROFILE_, ref, sd.getUrl()), + slicingHint(errors, IssueType.STRUCTURE, element.line(), element.col(), path, false, false, context.formatMessage(I18nConstants.DETAILS_FOR__MATCHING_AGAINST_PROFILE_, ref, sd.getUrl()), errorSummaryForSlicingAsHtml(badProfiles.get(sd)), errorSummaryForSlicingAsText(badProfiles.get(sd))); } } else { @@ -2898,6 +2903,15 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat return "
    " + b.toString() + "
"; } + private boolean isCritical(List list) { + for (ValidationMessage vm : list) { + if (vm.isSlicingHint() && vm.isCriticalSignpost()) { + return true; + } + } + return false; + } + private String[] errorSummaryForSlicingAsText(List list) { List res = new ArrayList(); for (ValidationMessage vm : list) { @@ -3305,7 +3319,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat rr.setExternal(false); rr.setStack(nstack); // rr.getStack().qualifyPath(".ofType("+nstack.getElement().fhirType()+")"); - System.out.println("-->"+nstack.getLiteralPath()); +// System.out.println("-->"+nstack.getLiteralPath()); return rr; } if (nstack.getElement().getSpecial() == SpecialElement.CONTAINED) { @@ -3675,9 +3689,9 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat ValidatorHostContext shc = hostContext.forSlicing(); boolean pass = evaluateSlicingExpression(shc, element, path, profile, n); if (!pass) { - slicingHint(sliceInfo, IssueType.STRUCTURE, element.line(), element.col(), path, false, (context.formatMessage(I18nConstants.DOES_NOT_MATCH_SLICE_, ed.getSliceName())), "discriminator = " + Utilities.escapeXml(n.toString()), null); + slicingHint(sliceInfo, IssueType.STRUCTURE, element.line(), element.col(), path, false, isProfile(slicer), (context.formatMessage(I18nConstants.DOES_NOT_MATCH_SLICE_, ed.getSliceName())), "discriminator = " + Utilities.escapeXml(n.toString()), null); for (String url : shc.getSliceRecords().keySet()) { - slicingHint(sliceInfo, IssueType.STRUCTURE, element.line(), element.col(), path, false, + slicingHint(sliceInfo, IssueType.STRUCTURE, element.line(), element.col(), path, false, isProfile(slicer), context.formatMessage(I18nConstants.DETAILS_FOR__MATCHING_AGAINST_PROFILE_, stack.getLiteralPath(), url), context.formatMessage(I18nConstants.PROFILE__DOES_NOT_MATCH_FOR__BECAUSE_OF_THE_FOLLOWING_PROFILE_ISSUES__, url, @@ -3687,6 +3701,18 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat return pass; } + private boolean isProfile(ElementDefinition slicer) { + if (slicer == null || !slicer.hasSlicing()) { + return false; + } + for (ElementDefinitionSlicingDiscriminatorComponent t : slicer.getSlicing().getDiscriminator()) { + if (t.getType() == DiscriminatorType.PROFILE) { + return true; + } + } + return false; + } + public boolean evaluateSlicingExpression(ValidatorHostContext hostContext, Element element, String path, StructureDefinition profile, ExpressionNode n) throws FHIRException { String msg; boolean ok; @@ -4898,7 +4924,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat if (ei.additionalSlice && ei.definition != null) { if (ei.definition.getSlicing().getRules().equals(ElementDefinition.SlicingRules.OPEN) || ei.definition.getSlicing().getRules().equals(ElementDefinition.SlicingRules.OPENATEND) && true /* TODO: replace "true" with condition to check that this element is at "end" */) { - slicingHint(errors, IssueType.INFORMATIONAL, ei.line(), ei.col(), ei.getPath(), false, + slicingHint(errors, IssueType.INFORMATIONAL, ei.line(), ei.col(), ei.getPath(), false, isProfile(slicer) || isCritical(ei.sliceInfo), context.formatMessage(I18nConstants.THIS_ELEMENT_DOES_NOT_MATCH_ANY_KNOWN_SLICE_, profile == null ? "" : " defined in the profile " + profile.getUrl()), context.formatMessage(I18nConstants.THIS_ELEMENT_DOES_NOT_MATCH_ANY_KNOWN_SLICE_, profile == null ? "" : I18nConstants.DEFINED_IN_THE_PROFILE + profile.getUrl()) + errorSummaryForSlicingAsHtml(ei.sliceInfo), @@ -4944,6 +4970,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat return problematicPaths; } + public List listChildren(Element element, NodeStack stack) { // 1. List the children, and remember their exact path (convenience) List children = new ArrayList(); @@ -5197,7 +5224,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat } // todo: validate everything in this bundle. } - ok = rule(errors, IssueType.INVALID, -1, -1, stack.getLiteralPath(), typeMatchesDefn(resourceName, defn), I18nConstants.VALIDATION_VAL_PROFILE_WRONGTYPE, defn.getName(), resourceName); + ok = rule(errors, IssueType.INVALID, -1, -1, stack.getLiteralPath(), typeMatchesDefn(resourceName, defn), I18nConstants.VALIDATION_VAL_PROFILE_WRONGTYPE, defn.getType(), resourceName, defn.getName()); if (ok) { if (idstatus == IdStatus.REQUIRED && (element.getNamedChild(ID) == null)) { diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/SpecialExtensions.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/SpecialExtensions.java index 483a417f3..587fd4e85 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/SpecialExtensions.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/SpecialExtensions.java @@ -13,12 +13,14 @@ public class SpecialExtensions { private static final String MUST_SUPPORT_SOURCE = "{\"resourceType\" : \"StructureDefinition\",\"id\" : \"elementdefinition-type-must-support\",\"extension\" : [{\"url\" : \"http://hl7.org/fhir/StructureDefinition/structuredefinition-wg\",\"valueCode\" : \"fhir\"},{\"url\" : \"http://hl7.org/fhir/StructureDefinition/structuredefinition-fmm\",\"valueInteger\" : 1}],\"url\" : \"http://hl7.org/fhir/StructureDefinition/elementdefinition-type-must-support\",\"version\" : \"4.5.0\",\"name\" : \"type-must-support\",\"status\" : \"draft\",\"date\" : \"2015-02-28\",\"publisher\" : \"Health Level Seven, Inc. - FHIR Core WG\",\"contact\" : [{\"telecom\" : [{\"system\" : \"url\",\"value\" : \"http://hl7.org/special/committees/FHIR\"}]}],\"description\" : \"If true indicates that the specified type, profile or targetProfile must be supported by implementations.\",\"fhirVersion\" : \"4.5.0\",\"mapping\" : [{\"identity\" : \"rim\",\"uri\" : \"http://hl7.org/v3\",\"name\" : \"RIM Mapping\"}],\"kind\" : \"complex-type\",\"abstract\" : false,\"context\" : [{\"type\" : \"element\",\"expression\" : \"ElementDefinition.type\"},{\"type\" : \"element\",\"expression\" : \"ElementDefinition.type.profile\"},{\"type\" : \"element\",\"expression\" : \"ElementDefinition.type.targetProfile\"}],\"type\" : \"Extension\",\"baseDefinition\" : \"http://hl7.org/fhir/StructureDefinition/Extension\",\"derivation\" : \"constraint\",\"snapshot\" : {\"element\" : [{\"id\" : \"Extension\",\"path\" : \"Extension\",\"short\" : \"The specified type/profile/target must be supported by implementations\",\"definition\" : \"If true indicates that the specified type, profile or targetProfile must be supported by implementations.\",\"comment\" : \"An element may be labelled as must support. This extension clarifies which types/profiles/targetProfiles are must-support. It has no meaning if the element itself is not must-support. If the element is labelled must-support, and none of the options are labelled as must support, then an application must support at least one of the possible options, but is not required to support all of them.\",\"min\" : 0,\"max\" : \"1\",\"base\" : {\"path\" : \"Extension\",\"min\" : 0,\"max\" : \"*\"},\"constraint\" : [{\"key\" : \"ele-1\",\"severity\" : \"error\",\"human\" : \"All FHIR elements must have a @value or children\",\"expression\" : \"hasValue() or (children().count() > id.count())\",\"xpath\" : \"@value|f:*|h:div\",\"source\" : \"http://hl7.org/fhir/StructureDefinition/Element\"},{\"key\" : \"ext-1\",\"severity\" : \"error\",\"human\" : \"Must have either extensions or value[x], not both\",\"expression\" : \"extension.exists() != value.exists()\",\"xpath\" : \"exists(f:extension)!=exists(f:*[starts-with(local-name(.), 'value')])\",\"source\" : \"http://hl7.org/fhir/StructureDefinition/Extension\"}],\"isModifier\" : false},{\"id\" : \"Extension.id\",\"path\" : \"Extension.id\",\"representation\" : [\"xmlAttr\"],\"short\" : \"Unique id for inter-element referencing\",\"definition\" : \"Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.\",\"min\" : 0,\"max\" : \"1\",\"base\" : {\"path\" : \"Element.id\",\"min\" : 0,\"max\" : \"1\"},\"type\" : [{\"extension\" : [{\"url\" : \"http://hl7.org/fhir/StructureDefinition/structuredefinition-fhir-type\",\"valueUri\" : \"string\"}],\"code\" : \"http://hl7.org/fhirpath/System.String\"}],\"isModifier\" : false,\"isSummary\" : false,\"mapping\" : [{\"identity\" : \"rim\",\"map\" : \"n/a\"}]},{\"id\" : \"Extension.extension\",\"path\" : \"Extension.extension\",\"slicing\" : {\"discriminator\" : [{\"type\" : \"value\",\"path\" : \"url\"}],\"description\" : \"Extensions are always sliced by (at least) url\",\"rules\" : \"open\"},\"short\" : \"Extension\",\"definition\" : \"An Extension\",\"min\" : 0,\"max\" : \"0\",\"base\" : {\"path\" : \"Element.extension\",\"min\" : 0,\"max\" : \"*\"},\"type\" : [{\"code\" : \"Extension\"}],\"constraint\" : [{\"key\" : \"ele-1\",\"severity\" : \"error\",\"human\" : \"All FHIR elements must have a @value or children\",\"expression\" : \"hasValue() or (children().count() > id.count())\",\"xpath\" : \"@value|f:*|h:div\",\"source\" : \"http://hl7.org/fhir/StructureDefinition/Element\"},{\"key\" : \"ext-1\",\"severity\" : \"error\",\"human\" : \"Must have either extensions or value[x], not both\",\"expression\" : \"extension.exists() != value.exists()\",\"xpath\" : \"exists(f:extension)!=exists(f:*[starts-with(local-name(.), \\\"value\\\")])\",\"source\" : \"http://hl7.org/fhir/StructureDefinition/Extension\"}],\"isModifier\" : false,\"isSummary\" : false},{\"id\" : \"Extension.url\",\"path\" : \"Extension.url\",\"representation\" : [\"xmlAttr\"],\"short\" : \"identifies the meaning of the extension\",\"definition\" : \"Source of the definition for the extension code - a logical name or a URL.\",\"comment\" : \"The definition may point directly to a computable or human-readable definition of the extensibility codes, or it may be a logical URI as declared in some other specification. The definition SHALL be a URI for the Structure Definition defining the extension.\",\"min\" : 1,\"max\" : \"1\",\"base\" : {\"path\" : \"Extension.url\",\"min\" : 1,\"max\" : \"1\"},\"type\" : [{\"extension\" : [{\"url\" : \"http://hl7.org/fhir/StructureDefinition/structuredefinition-fhir-type\",\"valueUri\" : \"uri\"}],\"code\" : \"http://hl7.org/fhirpath/System.String\"}],\"fixedUri\" : \"http://hl7.org/fhir/StructureDefinition/elementdefinition-type-must-support\",\"isModifier\" : false,\"isSummary\" : false,\"mapping\" : [{\"identity\" : \"rim\",\"map\" : \"N/A\"}]},{\"id\" : \"Extension.value[x]\",\"path\" : \"Extension.value[x]\",\"short\" : \"Value of extension\",\"definition\" : \"Value of extension - must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list).\",\"min\" : 1,\"max\" : \"1\",\"base\" : {\"path\" : \"Extension.value[x]\",\"min\" : 0,\"max\" : \"1\"},\"type\" : [{\"code\" : \"boolean\"}],\"constraint\" : [{\"key\" : \"ele-1\",\"severity\" : \"error\",\"human\" : \"All FHIR elements must have a @value or children\",\"expression\" : \"hasValue() or (children().count() > id.count())\",\"xpath\" : \"@value|f:*|h:div\",\"source\" : \"http://hl7.org/fhir/StructureDefinition/Element\"}],\"isModifier\" : false,\"isSummary\" : false,\"mapping\" : [{\"identity\" : \"rim\",\"map\" : \"N/A\"}]}]},\"differential\" : {\"element\" : [{\"id\" : \"Extension\",\"path\" : \"Extension\",\"short\" : \"The specified type/profile/target must be supported by implementations\",\"definition\" : \"If true indicates that the specified type, profile or targetProfile must be supported by implementations.\",\"comment\" : \"An element may be labelled as must support. This extension clarifies which types/profiles/targetProfiles are must-support. It has no meaning if the element itself is not must-support. If the element is labelled must-support, and none of the options are labelled as must support, then an application must support at least one of the possible options, but is not required to support all of them.\",\"min\" : 0,\"max\" : \"1\"},{\"id\" : \"Extension.extension\",\"path\" : \"Extension.extension\",\"max\" : \"0\"},{\"id\" : \"Extension.url\",\"path\" : \"Extension.url\",\"fixedUri\" : \"http://hl7.org/fhir/StructureDefinition/elementdefinition-type-must-support\"},{\"id\" : \"Extension.value[x]\",\"path\" : \"Extension.value[x]\",\"min\" : 1,\"type\" : [{\"code\" : \"boolean\"}]}]}}"; private static final String INSTANCE_NAME_SOURCE = "{\"resourceType\" : \"StructureDefinition\",\"id\" : \"instance-name\",\"extension\" : [{\"url\" : \"http://hl7.org/fhir/StructureDefinition/structuredefinition-wg\",\"valueCode\" : \"fhir\"},{\"url\" : \"http://hl7.org/fhir/StructureDefinition/structuredefinition-fmm\",\"valueInteger\" : 1}],\"url\" : \"http://hl7.org/fhir/StructureDefinition/instance-name\",\"version\" : \"4.5.0\",\"name\" : \"instance-name\",\"status\" : \"draft\",\"date\" : \"2015-02-28\",\"publisher\" : \"Health Level Seven, Inc. - FHIR Core WG\",\"contact\" : [{\"telecom\" : [{\"system\" : \"url\",\"value\" : \"http://hl7.org/special/committees/FHIR\"}]}],\"description\" : \"If true indicates that the specified type, profile or targetProfile must be supported by implementations.\",\"fhirVersion\" : \"4.5.0\",\"mapping\" : [{\"identity\" : \"rim\",\"uri\" : \"http://hl7.org/v3\",\"name\" : \"RIM Mapping\"}],\"kind\" : \"complex-type\",\"abstract\" : false,\"context\" : [{\"type\" : \"element\",\"expression\" : \"Resource.meta\"}],\"type\" : \"Extension\",\"baseDefinition\" : \"http://hl7.org/fhir/StructureDefinition/Extension\",\"derivation\" : \"constraint\",\"snapshot\" : {\"element\" : [{\"id\" : \"Extension\",\"path\" : \"Extension\",\"short\" : \"The specified type/profile/target must be supported by implementations\",\"definition\" : \"If true indicates that the specified type, profile or targetProfile must be supported by implementations.\",\"comment\" : \"todo.\",\"min\" : 0,\"max\" : \"1\",\"base\" : {\"path\" : \"Extension\",\"min\" : 0,\"max\" : \"*\"},\"constraint\" : [{\"key\" : \"ele-1\",\"severity\" : \"error\",\"human\" : \"All FHIR elements must have a @value or children\",\"expression\" : \"hasValue() or (children().count() > id.count())\",\"xpath\" : \"@value|f:*|h:div\",\"source\" : \"http://hl7.org/fhir/StructureDefinition/Element\"},{\"key\" : \"ext-1\",\"severity\" : \"error\",\"human\" : \"Must have either extensions or value[x], not both\",\"expression\" : \"extension.exists() != value.exists()\",\"xpath\" : \"exists(f:extension)!=exists(f:*[starts-with(local-name(.), 'value')])\",\"source\" : \"http://hl7.org/fhir/StructureDefinition/Extension\"}],\"isModifier\" : false},{\"id\" : \"Extension.id\",\"path\" : \"Extension.id\",\"representation\" : [\"xmlAttr\"],\"short\" : \"Unique id for inter-element referencing\",\"definition\" : \"Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.\",\"min\" : 0,\"max\" : \"1\",\"base\" : {\"path\" : \"Element.id\",\"min\" : 0,\"max\" : \"1\"},\"type\" : [{\"extension\" : [{\"url\" : \"http://hl7.org/fhir/StructureDefinition/structuredefinition-fhir-type\",\"valueUri\" : \"string\"}],\"code\" : \"http://hl7.org/fhirpath/System.String\"}],\"isModifier\" : false,\"isSummary\" : false,\"mapping\" : [{\"identity\" : \"rim\",\"map\" : \"n/a\"}]},{\"id\" : \"Extension.extension\",\"path\" : \"Extension.extension\",\"slicing\" : {\"discriminator\" : [{\"type\" : \"value\",\"path\" : \"url\"}],\"description\" : \"Extensions are always sliced by (at least) url\",\"rules\" : \"open\"},\"short\" : \"Extension\",\"definition\" : \"An Extension\",\"min\" : 0,\"max\" : \"0\",\"base\" : {\"path\" : \"Element.extension\",\"min\" : 0,\"max\" : \"*\"},\"type\" : [{\"code\" : \"Extension\"}],\"constraint\" : [{\"key\" : \"ele-1\",\"severity\" : \"error\",\"human\" : \"All FHIR elements must have a @value or children\",\"expression\" : \"hasValue() or (children().count() > id.count())\",\"xpath\" : \"@value|f:*|h:div\",\"source\" : \"http://hl7.org/fhir/StructureDefinition/Element\"},{\"key\" : \"ext-1\",\"severity\" : \"error\",\"human\" : \"Must have either extensions or value[x], not both\",\"expression\" : \"extension.exists() != value.exists()\",\"xpath\" : \"exists(f:extension)!=exists(f:*[starts-with(local-name(.), \\\"value\\\")])\",\"source\" : \"http://hl7.org/fhir/StructureDefinition/Extension\"}],\"isModifier\" : false,\"isSummary\" : false},{\"id\" : \"Extension.url\",\"path\" : \"Extension.url\",\"representation\" : [\"xmlAttr\"],\"short\" : \"identifies the meaning of the extension\",\"definition\" : \"Source of the definition for the extension code - a logical name or a URL.\",\"comment\" : \"The definition may point directly to a computable or human-readable definition of the extensibility codes, or it may be a logical URI as declared in some other specification. The definition SHALL be a URI for the Structure Definition defining the extension.\",\"min\" : 1,\"max\" : \"1\",\"base\" : {\"path\" : \"Extension.url\",\"min\" : 1,\"max\" : \"1\"},\"type\" : [{\"extension\" : [{\"url\" : \"http://hl7.org/fhir/StructureDefinition/structuredefinition-fhir-type\",\"valueUri\" : \"uri\"}],\"code\" : \"http://hl7.org/fhirpath/System.String\"}],\"fixedUri\" : \"http://hl7.org/fhir/StructureDefinition/instance-name\",\"isModifier\" : false,\"isSummary\" : false,\"mapping\" : [{\"identity\" : \"rim\",\"map\" : \"N/A\"}]},{\"id\" : \"Extension.value[x]\",\"path\" : \"Extension.value[x]\",\"short\" : \"Value of extension\",\"definition\" : \"Value of extension - must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list).\",\"min\" : 1,\"max\" : \"1\",\"base\" : {\"path\" : \"Extension.value[x]\",\"min\" : 0,\"max\" : \"1\"},\"type\" : [{\"code\" : \"string\"}],\"constraint\" : [{\"key\" : \"ele-1\",\"severity\" : \"error\",\"human\" : \"All FHIR elements must have a @value or children\",\"expression\" : \"hasValue() or (children().count() > id.count())\",\"xpath\" : \"@value|f:*|h:div\",\"source\" : \"http://hl7.org/fhir/StructureDefinition/Element\"}],\"isModifier\" : false,\"isSummary\" : false,\"mapping\" : [{\"identity\" : \"rim\",\"map\" : \"N/A\"}]}]},\"differential\" : {\"element\" : [{\"id\" : \"Extension\",\"path\" : \"Extension\",\"short\" : \"The specified type/profile/target must be supported by implementations\",\"definition\" : \"If true indicates that the specified type, profile or targetProfile must be supported by implementations.\",\"comment\" : \"todo.\",\"min\" : 0,\"max\" : \"1\"},{\"id\" : \"Extension.extension\",\"path\" : \"Extension.extension\",\"max\" : \"0\"},{\"id\" : \"Extension.url\",\"path\" : \"Extension.url\",\"fixedUri\" : \"http://hl7.org/fhir/StructureDefinition/instance-name\"},{\"id\" : \"Extension.value[x]\",\"path\" : \"Extension.value[x]\",\"min\" : 1,\"type\" : [{\"code\" : \"string\"}]}]}}"; private static final String INSTANCE_DESC_SOURCE = "{\"resourceType\" : \"StructureDefinition\",\"id\" : \"instance-description\",\"extension\" : [{\"url\" : \"http://hl7.org/fhir/StructureDefinition/structuredefinition-wg\",\"valueCode\" : \"fhir\"},{\"url\" : \"http://hl7.org/fhir/StructureDefinition/structuredefinition-fmm\",\"valueInteger\" : 1}],\"url\" : \"http://hl7.org/fhir/StructureDefinition/instance-description\",\"version\" : \"4.5.0\",\"name\" : \"instance-description\",\"status\" : \"draft\",\"date\" : \"2015-02-28\",\"publisher\" : \"Health Level Seven, Inc. - FHIR Core WG\",\"contact\" : [{\"telecom\" : [{\"system\" : \"url\",\"value\" : \"http://hl7.org/special/committees/FHIR\"}]}],\"description\" : \"If true indicates that the specified type, profile or targetProfile must be supported by implementations.\",\"fhirVersion\" : \"4.5.0\",\"mapping\" : [{\"identity\" : \"rim\",\"uri\" : \"http://hl7.org/v3\",\"name\" : \"RIM Mapping\"}],\"kind\" : \"complex-type\",\"abstract\" : false,\"context\" : [{\"type\" : \"element\",\"expression\" : \"Resource.meta\"}],\"type\" : \"Extension\",\"baseDefinition\" : \"http://hl7.org/fhir/StructureDefinition/Extension\",\"derivation\" : \"constraint\",\"snapshot\" : {\"element\" : [{\"id\" : \"Extension\",\"path\" : \"Extension\",\"short\" : \"The specified type/profile/target must be supported by implementations\",\"definition\" : \"If true indicates that the specified type, profile or targetProfile must be supported by implementations.\",\"comment\" : \"todo.\",\"min\" : 0,\"max\" : \"1\",\"base\" : {\"path\" : \"Extension\",\"min\" : 0,\"max\" : \"*\"},\"constraint\" : [{\"key\" : \"ele-1\",\"severity\" : \"error\",\"human\" : \"All FHIR elements must have a @value or children\",\"expression\" : \"hasValue() or (children().count() > id.count())\",\"xpath\" : \"@value|f:*|h:div\",\"source\" : \"http://hl7.org/fhir/StructureDefinition/Element\"},{\"key\" : \"ext-1\",\"severity\" : \"error\",\"human\" : \"Must have either extensions or value[x], not both\",\"expression\" : \"extension.exists() != value.exists()\",\"xpath\" : \"exists(f:extension)!=exists(f:*[starts-with(local-name(.), 'value')])\",\"source\" : \"http://hl7.org/fhir/StructureDefinition/Extension\"}],\"isModifier\" : false},{\"id\" : \"Extension.id\",\"path\" : \"Extension.id\",\"representation\" : [\"xmlAttr\"],\"short\" : \"Unique id for inter-element referencing\",\"definition\" : \"Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.\",\"min\" : 0,\"max\" : \"1\",\"base\" : {\"path\" : \"Element.id\",\"min\" : 0,\"max\" : \"1\"},\"type\" : [{\"extension\" : [{\"url\" : \"http://hl7.org/fhir/StructureDefinition/structuredefinition-fhir-type\",\"valueUri\" : \"markdown\"}],\"code\" : \"http://hl7.org/fhirpath/System.String\"}],\"isModifier\" : false,\"isSummary\" : false,\"mapping\" : [{\"identity\" : \"rim\",\"map\" : \"n/a\"}]},{\"id\" : \"Extension.extension\",\"path\" : \"Extension.extension\",\"slicing\" : {\"discriminator\" : [{\"type\" : \"value\",\"path\" : \"url\"}],\"description\" : \"Extensions are always sliced by (at least) url\",\"rules\" : \"open\"},\"short\" : \"Extension\",\"definition\" : \"An Extension\",\"min\" : 0,\"max\" : \"0\",\"base\" : {\"path\" : \"Element.extension\",\"min\" : 0,\"max\" : \"*\"},\"type\" : [{\"code\" : \"Extension\"}],\"constraint\" : [{\"key\" : \"ele-1\",\"severity\" : \"error\",\"human\" : \"All FHIR elements must have a @value or children\",\"expression\" : \"hasValue() or (children().count() > id.count())\",\"xpath\" : \"@value|f:*|h:div\",\"source\" : \"http://hl7.org/fhir/StructureDefinition/Element\"},{\"key\" : \"ext-1\",\"severity\" : \"error\",\"human\" : \"Must have either extensions or value[x], not both\",\"expression\" : \"extension.exists() != value.exists()\",\"xpath\" : \"exists(f:extension)!=exists(f:*[starts-with(local-name(.), \\\"value\\\")])\",\"source\" : \"http://hl7.org/fhir/StructureDefinition/Extension\"}],\"isModifier\" : false,\"isSummary\" : false},{\"id\" : \"Extension.url\",\"path\" : \"Extension.url\",\"representation\" : [\"xmlAttr\"],\"short\" : \"identifies the meaning of the extension\",\"definition\" : \"Source of the definition for the extension code - a logical name or a URL.\",\"comment\" : \"The definition may point directly to a computable or human-readable definition of the extensibility codes, or it may be a logical URI as declared in some other specification. The definition SHALL be a URI for the Structure Definition defining the extension.\",\"min\" : 1,\"max\" : \"1\",\"base\" : {\"path\" : \"Extension.url\",\"min\" : 1,\"max\" : \"1\"},\"type\" : [{\"extension\" : [{\"url\" : \"http://hl7.org/fhir/StructureDefinition/structuredefinition-fhir-type\",\"valueUri\" : \"uri\"}],\"code\" : \"http://hl7.org/fhirpath/System.String\"}],\"fixedUri\" : \"http://hl7.org/fhir/StructureDefinition/instance-description\",\"isModifier\" : false,\"isSummary\" : false,\"mapping\" : [{\"identity\" : \"rim\",\"map\" : \"N/A\"}]},{\"id\" : \"Extension.value[x]\",\"path\" : \"Extension.value[x]\",\"short\" : \"Value of extension\",\"definition\" : \"Value of extension - must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list).\",\"min\" : 1,\"max\" : \"1\",\"base\" : {\"path\" : \"Extension.value[x]\",\"min\" : 0,\"max\" : \"1\"},\"type\" : [{\"code\" : \"markdown\"}],\"constraint\" : [{\"key\" : \"ele-1\",\"severity\" : \"error\",\"human\" : \"All FHIR elements must have a @value or children\",\"expression\" : \"hasValue() or (children().count() > id.count())\",\"xpath\" : \"@value|f:*|h:div\",\"source\" : \"http://hl7.org/fhir/StructureDefinition/Element\"}],\"isModifier\" : false,\"isSummary\" : false,\"mapping\" : [{\"identity\" : \"rim\",\"map\" : \"N/A\"}]}]},\"differential\" : {\"element\" : [{\"id\" : \"Extension\",\"path\" : \"Extension\",\"short\" : \"The specified type/profile/target must be supported by implementations\",\"definition\" : \"If true indicates that the specified type, profile or targetProfile must be supported by implementations.\",\"comment\" : \"todo.\",\"min\" : 0,\"max\" : \"1\"},{\"id\" : \"Extension.extension\",\"path\" : \"Extension.extension\",\"max\" : \"0\"},{\"id\" : \"Extension.url\",\"path\" : \"Extension.url\",\"fixedUri\" : \"http://hl7.org/fhir/StructureDefinition/instance-description\"},{\"id\" : \"Extension.value[x]\",\"path\" : \"Extension.value[x]\",\"min\" : 1,\"type\" : [{\"code\" : \"markdown\"}]}]}}"; + private static final String CODE_SYSTEM_PROPS_EXT = "{\"resourceType\" : \"StructureDefinition\",\"id\" : \"codesystem-properties-mode\",\"extension\" : [{\"url\" : \"http://hl7.org/fhir/StructureDefinition/structuredefinition-wg\",\"valueCode\" : \"vocab\"},{\"url\" : \"http://hl7.org/fhir/StructureDefinition/structuredefinition-fmm\",\"valueInteger\" : 1}],\"url\" : \"http://hl7.org/fhir/StructureDefinition/codesystem-properties-mode\",\"version\" : \"4.6.0\",\"name\" : \"properties-mode\",\"status\" : \"draft\",\"date\" : \"2021-01-02T08:58:31+11:00\",\"publisher\" : \"HL7\",\"description\" : \"The extent to which the properties of the code system (including the filters) are represented in this resource instance.\",\"fhirVersion\" : \"4.6.0\",\"mapping\" : [{\"identity\" : \"rim\",\"uri\" : \"http://hl7.org/v3\",\"name\" : \"RIM Mapping\"}],\"kind\" : \"complex-type\",\"abstract\" : false,\"context\" : [{\"type\" : \"element\",\"expression\" : \"CodeSystem\"}],\"type\" : \"Extension\",\"baseDefinition\" : \"http://hl7.org/fhir/StructureDefinition/Extension\",\"derivation\" : \"constraint\",\"snapshot\" : {\"element\" : [{\"id\" : \"Extension\",\"path\" : \"Extension\",\"short\" : \"not-present | partial | complete\",\"definition\" : \"The extent to which the properties of the code system (including the filters) are represented in this resource instance.\",\"min\" : 0,\"max\" : \"1\",\"base\" : {\"path\" : \"Extension\",\"min\" : 0,\"max\" : \"*\"},\"constraint\" : [{\"key\" : \"ele-1\",\"severity\" : \"error\",\"human\" : \"All FHIR elements must have a @value or children\",\"expression\" : \"hasValue() or (children().count() > id.count())\",\"xpath\" : \"@value|f:*|h:div\",\"source\" : \"http://hl7.org/fhir/StructureDefinition/Element\"},{\"key\" : \"ext-1\",\"severity\" : \"error\",\"human\" : \"Must have either extensions or value[x], not both\",\"expression\" : \"extension.exists() != value.exists()\",\"xpath\" : \"exists(f:extension)!=exists(f:*[starts-with(local-name(.), 'value')])\",\"source\" : \"http://hl7.org/fhir/StructureDefinition/Extension\"}],\"isModifier\" : false},{\"id\" : \"Extension.id\",\"path\" : \"Extension.id\",\"representation\" : [\"xmlAttr\"],\"short\" : \"Unique id for inter-element referencing\",\"definition\" : \"Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.\",\"min\" : 0,\"max\" : \"1\",\"base\" : {\"path\" : \"Element.id\",\"min\" : 0,\"max\" : \"1\"},\"type\" : [{\"extension\" : [{\"url\" : \"http://hl7.org/fhir/StructureDefinition/structuredefinition-fhir-type\",\"valueUri\" : \"string\"}],\"code\" : \"http://hl7.org/fhirpath/System.String\"}],\"isModifier\" : false,\"isSummary\" : false,\"mapping\" : [{\"identity\" : \"rim\",\"map\" : \"n/a\"}]},{\"id\" : \"Extension.extension\",\"path\" : \"Extension.extension\",\"slicing\" : {\"discriminator\" : [{\"type\" : \"value\",\"path\" : \"url\"}],\"description\" : \"Extensions are always sliced by (at least) url\",\"rules\" : \"open\"},\"short\" : \"Extension\",\"definition\" : \"An Extension\",\"min\" : 0,\"max\" : \"0\",\"base\" : {\"path\" : \"Element.extension\",\"min\" : 0,\"max\" : \"*\"},\"type\" : [{\"code\" : \"Extension\"}],\"constraint\" : [{\"key\" : \"ele-1\",\"severity\" : \"error\",\"human\" : \"All FHIR elements must have a @value or children\",\"expression\" : \"hasValue() or (children().count() > id.count())\",\"xpath\" : \"@value|f:*|h:div\",\"source\" : \"http://hl7.org/fhir/StructureDefinition/Element\"},{\"key\" : \"ext-1\",\"severity\" : \"error\",\"human\" : \"Must have either extensions or value[x], not both\",\"expression\" : \"extension.exists() != value.exists()\",\"xpath\" : \"exists(f:extension)!=exists(f:*[starts-with(local-name(.), \\\"value\\\")])\",\"source\" : \"http://hl7.org/fhir/StructureDefinition/Extension\"}],\"isModifier\" : false,\"isSummary\" : false},{\"id\" : \"Extension.url\",\"path\" : \"Extension.url\",\"representation\" : [\"xmlAttr\"],\"short\" : \"identifies the meaning of the extension\",\"definition\" : \"Source of the definition for the extension code - a logical name or a URL.\",\"comment\" : \"The definition may point directly to a computable or human-readable definition of the extensibility codes, or it may be a logical URI as declared in some other specification. The definition SHALL be a URI for the Structure Definition defining the extension.\",\"min\" : 1,\"max\" : \"1\",\"base\" : {\"path\" : \"Extension.url\",\"min\" : 1,\"max\" : \"1\"},\"type\" : [{\"extension\" : [{\"url\" : \"http://hl7.org/fhir/StructureDefinition/structuredefinition-fhir-type\",\"valueUri\" : \"uri\"}],\"code\" : \"http://hl7.org/fhirpath/System.String\"}],\"fixedUri\" : \"http://hl7.org/fhir/StructureDefinition/codesystem-properties-mode\",\"isModifier\" : false,\"isSummary\" : false,\"mapping\" : [{\"identity\" : \"rim\",\"map\" : \"N/A\"}]},{\"id\" : \"Extension.value[x]\",\"path\" : \"Extension.value[x]\",\"short\" : \"Value of extension\",\"definition\" : \"Value of extension - must be one of a constrained set of the data types (see [Extensibility](extensibility.html) for a list).\",\"min\" : 1,\"max\" : \"1\",\"base\" : {\"path\" : \"Extension.value[x]\",\"min\" : 0,\"max\" : \"1\"},\"type\" : [{\"code\" : \"code\"}],\"constraint\" : [{\"key\" : \"ele-1\",\"severity\" : \"error\",\"human\" : \"All FHIR elements must have a @value or children\",\"expression\" : \"hasValue() or (children().count() > id.count())\",\"xpath\" : \"@value|f:*|h:div\",\"source\" : \"http://hl7.org/fhir/StructureDefinition/Element\"}],\"isModifier\" : false,\"isSummary\" : false,\"binding\" : {\"extension\" : [{\"url\" : \"http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName\",\"valueString\" : \"CodeSystemPropertiesMode\"}],\"strength\" : \"required\",\"description\" : \"The extent to which the properties of the code system (including the filters) are represented in a code system resource.\",\"valueSet\" : \"http://hl7.org/fhir/ValueSet/codesystem-properties-mode\"},\"mapping\" : [{\"identity\" : \"rim\",\"map\" : \"N/A\"}]}]},\"differential\" : {\"element\" : [{\"id\" : \"Extension\",\"path\" : \"Extension\",\"short\" : \"not-present | partial | complete\",\"definition\" : \"The extent to which the properties of the code system (including the filters) are represented in this resource instance.\",\"min\" : 0,\"max\" : \"1\",\"isModifier\" : false},{\"id\" : \"Extension.extension\",\"path\" : \"Extension.extension\",\"max\" : \"0\"},{\"id\" : \"Extension.url\",\"path\" : \"Extension.url\",\"fixedUri\" : \"http://hl7.org/fhir/StructureDefinition/codesystem-properties-mode\"},{\"id\" : \"Extension.value[x]\",\"path\" : \"Extension.value[x]\",\"min\" : 1,\"type\" : [{\"code\" : \"code\"}],\"binding\" : {\"extension\" : [{\"url\" : \"http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName\",\"valueString\" : \"CodeSystemPropertiesMode\"}],\"strength\" : \"required\",\"description\" : \"The extent to which the properties of the code system (including the filters) are represented in a code system resource.\",\"valueSet\" : \"http://hl7.org/fhir/ValueSet/codesystem-properties-mode\"}}]}}"; public static boolean isKnownExtension(String url) { return Utilities.existsInList(url, "http://hl7.org/fhir/StructureDefinition/elementdefinition-type-must-support", "http://hl7.org/fhir/StructureDefinition/instance-name", "http://hl7.org/fhir/StructureDefinition/instance-description", + "http://hl7.org/fhir/StructureDefinition/codesystem-properties-mode", "http://hl7.org/fhir/StructureDefinition/structuredefinition-rdf-type" ); } @@ -29,6 +31,7 @@ public class SpecialExtensions { case "http://hl7.org/fhir/StructureDefinition/elementdefinition-type-must-support" : return makeExt(MUST_SUPPORT_SOURCE); case "http://hl7.org/fhir/StructureDefinition/instance-name" : return makeExt(INSTANCE_NAME_SOURCE); case "http://hl7.org/fhir/StructureDefinition/instance-description" : return makeExt(INSTANCE_DESC_SOURCE); + case "codesystem-properties-mode" : return makeExt(CODE_SYSTEM_PROPS_EXT); default: return null; } } catch (Exception e) { diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/type/QuestionnaireValidator.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/type/QuestionnaireValidator.java index 1f4a42917..77e5e7e65 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/type/QuestionnaireValidator.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/type/QuestionnaireValidator.java @@ -192,9 +192,13 @@ public class QuestionnaireValidator extends BaseValidator { hint(errors, IssueType.REQUIRED, element.line(), element.col(), stack.getLiteralPath(), questionnaire != null, I18nConstants.QUESTIONNAIRE_QR_Q_NONE); if (ok) { Questionnaire qsrc = questionnaire.startsWith("#") ? loadQuestionnaire(element, questionnaire.substring(1)) : context.fetchResource(Questionnaire.class, questionnaire); - ok = questionnaireMode == QuestionnaireMode.REQUIRED ? - rule(errors, IssueType.REQUIRED, q.line(), q.col(), stack.getLiteralPath(), qsrc != null, I18nConstants.QUESTIONNAIRE_QR_Q_NOTFOUND, questionnaire) : - warning(errors, IssueType.REQUIRED, q.line(), q.col(), stack.getLiteralPath(), qsrc != null, I18nConstants.QUESTIONNAIRE_QR_Q_NOTFOUND, questionnaire); + if (questionnaireMode == QuestionnaireMode.REQUIRED) { + ok = rule(errors, IssueType.REQUIRED, q.line(), q.col(), stack.getLiteralPath(), qsrc != null, I18nConstants.QUESTIONNAIRE_QR_Q_NOTFOUND, questionnaire); + } else if (questionnaire.startsWith("http://example.org")) { + ok = hint(errors, IssueType.REQUIRED, q.line(), q.col(), stack.getLiteralPath(), qsrc != null, I18nConstants.QUESTIONNAIRE_QR_Q_NOTFOUND, questionnaire); + } else { + ok = warning(errors, IssueType.REQUIRED, q.line(), q.col(), stack.getLiteralPath(), qsrc != null, I18nConstants.QUESTIONNAIRE_QR_Q_NOTFOUND, questionnaire); + } if (ok) { boolean inProgress = "in-progress".equals(element.getNamedChildValue("status")); validateQuestionannaireResponseItems(hostContext, qsrc, qsrc.getItem(), errors, element, stack, inProgress, element, new QStack(qsrc, element)); diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/type/StructureDefinitionValidator.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/type/StructureDefinitionValidator.java index bdf481276..3164ba886 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/type/StructureDefinitionValidator.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/type/StructureDefinitionValidator.java @@ -15,10 +15,12 @@ import org.hl7.fhir.convertors.factory.*; import org.hl7.fhir.exceptions.FHIRException; import org.hl7.fhir.r5.conformance.ProfileUtilities; import org.hl7.fhir.r5.context.IWorkerContext; +import org.hl7.fhir.r5.context.IWorkerContext.ValidationResult; import org.hl7.fhir.r5.elementmodel.Element; import org.hl7.fhir.r5.elementmodel.Manager; import org.hl7.fhir.r5.elementmodel.Manager.FhirFormat; import org.hl7.fhir.r5.formats.IParser.OutputStyle; +import org.hl7.fhir.r5.model.Coding; import org.hl7.fhir.r5.model.ElementDefinition; import org.hl7.fhir.r5.model.ExpressionNode; import org.hl7.fhir.r5.model.Resource; @@ -35,6 +37,7 @@ import org.hl7.fhir.utilities.i18n.I18nConstants; import org.hl7.fhir.utilities.validation.ValidationMessage; import org.hl7.fhir.utilities.validation.ValidationMessage.IssueType; import org.hl7.fhir.utilities.validation.ValidationMessage.Source; +import org.hl7.fhir.utilities.validation.ValidationOptions; import org.hl7.fhir.validation.BaseValidator; import org.hl7.fhir.validation.TimeTracker; import org.hl7.fhir.validation.instance.utils.NodeStack; @@ -209,13 +212,23 @@ public class StructureDefinitionValidator extends BaseValidator { String ref = valueSet.hasPrimitiveValue() ? valueSet.primitiveValue() : valueSet.getNamedChildValue("reference"); if (warning(errors, IssueType.BUSINESSRULE, stack.getLiteralPath(), !snapshot || ref != null, I18nConstants.SD_ED_SHOULD_BIND_WITH_VS, path)) { Resource vs = context.fetchResource(Resource.class, ref); - if (warning(errors, IssueType.BUSINESSRULE, stack.getLiteralPath(), vs != null, I18nConstants.SD_ED_BIND_UNKNOWN_VS, path, ref)) { - rule(errors, IssueType.BUSINESSRULE, stack.getLiteralPath(), vs instanceof ValueSet, I18nConstants.SD_ED_BIND_NOT_VS, path, ref, vs.fhirType()); + + // just because we can't resolve it directly doesn't mean that terminology server can't. Check with it + + if (warning(errors, IssueType.BUSINESSRULE, stack.getLiteralPath(), vs != null || serverSupportsValueSet(ref), I18nConstants.SD_ED_BIND_UNKNOWN_VS, path, ref)) { + if (vs != null) { + rule(errors, IssueType.BUSINESSRULE, stack.getLiteralPath(), vs instanceof ValueSet, I18nConstants.SD_ED_BIND_NOT_VS, path, ref, vs.fhirType()); + } } } } } + private boolean serverSupportsValueSet(String ref) { + ValidationResult vr = context.validateCode(new ValidationOptions().checkValueSetOnly().setVsAsUrl().noClient(), new Coding("http://loinc.org", "5792-7", null), new ValueSet().setUrl(ref)); + return vr.getErrorClass() == null; + } + private void validateElementType(List errors, Element type, NodeStack stack, StructureDefinition sd, String path) { String code = type.getNamedChildValue("code"); if (code == null && path != null) { diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/utils/ValidatorHostContext.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/utils/ValidatorHostContext.java index 507951d7c..af29a2188 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/utils/ValidatorHostContext.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/utils/ValidatorHostContext.java @@ -26,11 +26,20 @@ public class ValidatorHostContext { } public ValidatorHostContext(Object appContext, Element element) { - this.appContext = appContext; - this.resource = element; - this.rootResource = element; - // no container - } + this.appContext = appContext; + this.resource = element; + this.rootResource = element; + // no container + dump("creating"); + } + + public ValidatorHostContext(Object appContext, Element element, Element root) { + this.appContext = appContext; + this.resource = element; + this.rootResource = root; + // no container + dump("creating"); + } public Object getAppContext() { return appContext; @@ -52,6 +61,7 @@ public class ValidatorHostContext { public ValidatorHostContext setRootResource(Element rootResource) { this.rootResource = rootResource; + dump("setting root resource"); return this; } @@ -96,6 +106,7 @@ public class ValidatorHostContext { res.rootResource = resource; res.resource = element; res.profile = profile; + res.dump("forContained"); return res; } @@ -104,6 +115,7 @@ public class ValidatorHostContext { res.rootResource = element; res.resource = element; res.profile = profile; + res.dump("forEntry"); return res; } @@ -113,6 +125,7 @@ public class ValidatorHostContext { res.rootResource = rootResource; res.profile = profile; res.sliceRecords = sliceRecords != null ? sliceRecords : new HashMap>(); + res.dump("forProfile "+profile.getUrl()); return res; } @@ -122,15 +135,24 @@ public class ValidatorHostContext { res.rootResource = resource; res.profile = profile; res.checkSpecials = false; + res.dump("forLocalReference "+profile.getUrl()); return res; } + private void dump(String ctxt) { +// System.out.println("** app = "+(appContext == null ? "(null)" : appContext.toString())+", res = "+resource.toString()+", root = "+rootResource.toString()+" ("+ctxt+")"); +// if (rootResource.getName().equals("contained")) { +// System.out.println("** something is wrong!"); +// } + } + public ValidatorHostContext forRemoteReference(StructureDefinition profile, Element resource) { ValidatorHostContext res = new ValidatorHostContext(appContext); res.resource = resource; res.rootResource = resource; res.profile = profile; res.checkSpecials = false; + res.dump("forRemoteReference "+profile.getUrl()); return res; } @@ -141,6 +163,7 @@ public class ValidatorHostContext { res.profile = profile; res.checkSpecials = false; res.sliceRecords = new HashMap>(); + res.dump("forSlicing"); return res; }