From a327f0312e2bc1b5135c6952aa40798b2d30d4f3 Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Sat, 28 Oct 2023 06:35:20 +1100 Subject: [PATCH 01/22] code clean up --- .../hl7/fhir/r4/utils/client/network/FhirRequestBuilder.java | 3 --- .../src/main/java/org/hl7/fhir/r5/elementmodel/ParserBase.java | 1 - .../main/java/org/hl7/fhir/utilities/npm/PackageClient.java | 1 - .../src/main/java/org/hl7/fhir/validation/BaseValidator.java | 1 - 4 files changed, 6 deletions(-) diff --git a/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/utils/client/network/FhirRequestBuilder.java b/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/utils/client/network/FhirRequestBuilder.java index acfc07f83..da7dca904 100644 --- a/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/utils/client/network/FhirRequestBuilder.java +++ b/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/utils/client/network/FhirRequestBuilder.java @@ -276,9 +276,6 @@ public class FhirRequestBuilder { if (error != null) { String s = ResourceUtilities.getErrorDescription(error); System.out.println(s); - if (s.startsWith("Unable to find value set")) { - System.out.println("!"); - } throw new EFhirClientException("Error from "+source+": " + ResourceUtilities.getErrorDescription(error), error); } diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/ParserBase.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/ParserBase.java index 14e5e8061..139bd5f2e 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/ParserBase.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/ParserBase.java @@ -130,7 +130,6 @@ public abstract class ParserBase { public abstract void compose(Element e, OutputStream destination, OutputStyle style, String base) throws FHIRException, IOException; - //FIXME: i18n should be done here public void logError(List errors, String ruleDate, int line, int col, String path, IssueType type, String message, IssueSeverity level) throws FHIRFormatError { if (errors != null) { if (policy == ValidationPolicy.EVERYTHING) { diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/npm/PackageClient.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/npm/PackageClient.java index 8592d5ab6..8ba2c59fa 100644 --- a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/npm/PackageClient.java +++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/npm/PackageClient.java @@ -119,7 +119,6 @@ public class PackageClient { try { return obj.hasString("date") ? obj.asDate("date") : null; } catch (DateTimeParseException e) { - //FIXME Some IGs use an older date format: try { return new SimpleDateFormat("yyyyMMddhhmmss").parse(obj.getJsonString("date").asString()).toInstant(); } catch (ParseException ex) { 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 2dea489eb..55dc10fdd 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 @@ -351,7 +351,6 @@ public class BaseValidator implements IValidationContextResourceLoader { * Set this parameter to false if the validation does not pass * @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, String ruleDate, IssueType type, int line, int col, String path, boolean thePass, boolean isCritical, String msg, String html, String[] text) { if (!thePass && doingHints()) { addValidationMessage(errors, ruleDate, type, line, col, path, msg, IssueSeverity.INFORMATION, null).setSlicingHint(true).setSliceHtml(html, text).setCriticalSignpost(isCritical); From 83f0009f2dd6e64f38ade14ebe54a735485e7d04 Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Sat, 28 Oct 2023 06:35:52 +1100 Subject: [PATCH 02/22] remove "profile" from tx operations --- .../org/hl7/fhir/r5/context/BaseWorkerContext.java | 7 ++++--- .../main/java/org/hl7/fhir/r5/model/Parameters.java | 12 ++++++++++++ 2 files changed, 16 insertions(+), 3 deletions(-) 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 7908ebe1b..e5b80fd8d 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 @@ -1375,7 +1375,8 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte if (valueSet != null) { pIn.addParameter().setName("valueSet").setResource(valueSet); } - pIn.addParameter().setName("profile").setResource(expParameters); + + pIn.addParameters(expParameters); return pIn; } @@ -1388,7 +1389,7 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte if (vsUrl != null) { pIn.addParameter().setName("url").setValue(new CanonicalType(vsUrl)); } - pIn.addParameter().setName("profile").setResource(expParameters); + pIn.addParameters(expParameters); return pIn; } @@ -1548,7 +1549,7 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte if (expParameters == null) { throw new Error(formatMessage(I18nConstants.NO_EXPANSIONPROFILE_PROVIDED)); } - pin.addParameter().setName("profile").setResource(expParameters); + pin.addParameters(expParameters); if (options.isDisplayWarningMode()) { pin.addParameter("mode","lenient-display-validation"); diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/model/Parameters.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/model/Parameters.java index c5b362491..d9ae0ad06 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/model/Parameters.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/model/Parameters.java @@ -1856,6 +1856,18 @@ public String toString() { getParameter().removeIf(p -> name.equals(p.getName())); } + public void addParameters(Parameters expParameters) { + addParameters(expParameters.getParameter()); + } + + private void addParameters(List parameters) { + for (ParametersParameterComponent p : parameters) { + if (!hasParameter(p.getName())) { + addParameter(p); + } + } + } + // end addition } From 892b1242594da468419ab296497ce1585db7dcbd Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Sat, 28 Oct 2023 06:36:16 +1100 Subject: [PATCH 03/22] Fix problem resolving context in CDA invariants --- .../main/java/org/hl7/fhir/r5/utils/FHIRPathEngine.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/FHIRPathEngine.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/FHIRPathEngine.java index 3c89a1901..9b4932450 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/FHIRPathEngine.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/FHIRPathEngine.java @@ -511,6 +511,7 @@ public class FHIRPathEngine { } types.addType(sd.getUrl()); } else { + boolean checkTypeName = false; String ctxt = null; if (t.contains("#")) { ctxt = t.substring(0, t.indexOf('#')); @@ -518,6 +519,7 @@ public class FHIRPathEngine { } else if (Utilities.isAbsoluteUrl(t)) { ctxt = t; t = ctxt.substring(ctxt.lastIndexOf("/")+1); + checkTypeName = true; } else { ctxt = t.substring(0, t.indexOf('.')); } @@ -525,7 +527,9 @@ public class FHIRPathEngine { if (sd == null) { throw makeException(expr, I18nConstants.FHIRPATH_UNKNOWN_CONTEXT, t); } - ElementDefinitionMatch ed = getElementDefinition(sd, t, true, expr); + String tn = checkTypeName ? sd.getSnapshot().getElementFirstRep().getPath() : t; + + ElementDefinitionMatch ed = getElementDefinition(sd, tn, true, expr); if (ed == null) { throw makeException(expr, I18nConstants.FHIRPATH_UNKNOWN_CONTEXT_ELEMENT, t); } @@ -3646,7 +3650,7 @@ public class FHIRPathEngine { private void checkContextString(TypeDetails focus, String name, ExpressionNode expr, boolean sing) throws PathEngineException { - if (!focus.hasNoTypes() && !focus.hasType(worker, "string") && !focus.hasType(worker, "code") && !focus.hasType(worker, "uri") && !focus.hasType(worker, "canonical") && !focus.hasType(worker, "id")) { + if (!focus.hasNoTypes() && !focus.hasType(worker, "string") && !focus.hasType(worker, "code") && !focus.hasType(worker, "uri") && !focus.hasType(worker, "url") && !focus.hasType(worker, "canonical") && !focus.hasType(worker, "id")) { throw makeException(expr, sing ? I18nConstants.FHIRPATH_STRING_SING_ONLY : I18nConstants.FHIRPATH_STRING_ORD_ONLY, name, focus.describe()); } } @@ -6087,6 +6091,7 @@ public class FHIRPathEngine { public ElementDefinitionMatch getElementDefinition(StructureDefinition sd, String path, boolean allowTypedName, ExpressionNode expr) throws PathEngineException { + for (ElementDefinition ed : sd.getSnapshot().getElement()) { if (ed.getPath().equals(path)) { if (ed.hasContentReference()) { From 681bc1ab365c1a7f2c713903870b0105e04bf098 Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Sat, 28 Oct 2023 06:36:34 +1100 Subject: [PATCH 04/22] Fix semver validation --- .../java/org/hl7/fhir/utilities/VersionUtilities.java | 8 ++------ .../java/org/hl7/fhir/utilities/VersionUtilitiesTest.java | 1 + 2 files changed, 3 insertions(+), 6 deletions(-) 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 7220a6173..ef77fda91 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 @@ -251,14 +251,10 @@ public class VersionUtilities { } public static boolean isSemVer(String version) { - if (Utilities.charCount(version, '.') != 2) { + if (Utilities.noString(version)) { return false; } - String[] p = version.split("\\."); - if (p[2].contains("-")) { - p[2] = p[2].substring(0, p[2].indexOf("-")); - } - return Utilities.isInteger(p[0]) && Utilities.isInteger(p[1]) && Utilities.isInteger(p[2]); + return version.matches("^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-\\+]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-\\+][0-9a-zA-Z-\\+]*))*))?$"); } /** diff --git a/org.hl7.fhir.utilities/src/test/java/org/hl7/fhir/utilities/VersionUtilitiesTest.java b/org.hl7.fhir.utilities/src/test/java/org/hl7/fhir/utilities/VersionUtilitiesTest.java index b41f866f2..ff2898b04 100644 --- a/org.hl7.fhir.utilities/src/test/java/org/hl7/fhir/utilities/VersionUtilitiesTest.java +++ b/org.hl7.fhir.utilities/src/test/java/org/hl7/fhir/utilities/VersionUtilitiesTest.java @@ -11,6 +11,7 @@ public class VersionUtilitiesTest { public void isValidSemVer() { assertTrue(VersionUtilities.isSemVer("0.1.1")); assertTrue(VersionUtilities.isSemVer("0.1.1-ballot1")); + assertTrue(VersionUtilities.isSemVer("0.0.0-alpha.0.131")); assertFalse(VersionUtilities.isSemVer("0.1.a")); } From 903d4c9d66620fa46d2c3ae411e2bded921d62a5 Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Sat, 28 Oct 2023 06:37:06 +1100 Subject: [PATCH 05/22] Support using names in [[[markdown]]] when rendering --- .../org/hl7/fhir/r5/renderers/utils/RenderingContext.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/utils/RenderingContext.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/utils/RenderingContext.java index 69c15468c..dc859e7ad 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/utils/RenderingContext.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/utils/RenderingContext.java @@ -190,6 +190,7 @@ public class RenderingContext { private String changeVersion; private Map links = new HashMap<>(); + private Map namedLinks = new HashMap<>(); /** * * @param context - access to all related resources that might be needed @@ -720,5 +721,8 @@ public class RenderingContext { return this; } - + public Map getNamedLinks() { + return namedLinks; + } + } \ No newline at end of file From 322f0d4756c02976a2bdbdee69ea76280e4c8fc7 Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Sat, 28 Oct 2023 06:37:42 +1100 Subject: [PATCH 06/22] allow URL as a type of string in FHIRPath type checking --- org.hl7.fhir.utilities/src/main/resources/Messages.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/org.hl7.fhir.utilities/src/main/resources/Messages.properties b/org.hl7.fhir.utilities/src/main/resources/Messages.properties index d5b5e9018..cffdc8877 100644 --- a/org.hl7.fhir.utilities/src/main/resources/Messages.properties +++ b/org.hl7.fhir.utilities/src/main/resources/Messages.properties @@ -610,7 +610,7 @@ FHIRPATH_PRIMITIVE_ONLY = Error evaluating FHIRPath expression: The function {0} FHIRPATH_REFERENCE_ONLY = Error evaluating FHIRPath expression: The function {0} can only be used on ordered string, uri, canonical or Reference but found {1} FHIRPATH_CODED_ONLY = Error evaluating FHIRPath expression: The function {0} can only be used on ordered string, code, uri, Coding, CodeableConcept but found {1} FHIRPATH_STRING_ORD_ONLY = Error evaluating FHIRPath expression: The function {0} can only be used on ordered collection of string, uri, code, id but found {1} -FHIRPATH_STRING_SING_ONLY = Error evaluating FHIRPath expression: The function {0} can only be used on string, uri, code, id but found {1} +FHIRPATH_STRING_SING_ONLY = Error evaluating FHIRPath expression: The function {0} can only be used on string, uri, url, code, id but found {1} FHIRPATH_NO_COLLECTION = Error evaluating FHIRPath expression: The function {0} can only be used on a singleton value but found {1} FHIRPATH_NOT_IMPLEMENTED = Error evaluating FHIRPath expression: The function {0} is not implemented FHIRPATH_PARAM_WRONG = Error evaluating FHIRPath expression: The expression type {0} is not supported for parameter {1} on function {2} From 034b1057e6519d1168702cab009637744f2e4c6f Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Sat, 28 Oct 2023 06:38:16 +1100 Subject: [PATCH 07/22] CDA templates with no extension value use urn:oid: not urn:hl7ii: --- .../org/hl7/fhir/validation/instance/InstanceValidator.java | 4 ++-- pom.xml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) 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 35c4d63e0..f33e19bff 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 @@ -5871,10 +5871,10 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat if (!definition.getPath().contains(".") && profile.hasExtension(ToolingExtensions.EXT_PROFILE_STYLE) && "cda".equals(ToolingExtensions.readStringExtension(profile, ToolingExtensions.EXT_PROFILE_STYLE))) { List templates = element.getChildren("templateId"); for (Element t : templates) { - String tid = "urn:hl7ii:"+t.getChildValue("root")+(t.hasChild("extension") ? ":"+t.getChildValue("extension") : ""); + String tid = t.hasChild("extension") ? "urn:hl7ii:"+t.getChildValue("root")+ ":"+t.getChildValue("extension") : "urn:oid:"+t.getChildValue("root"); StructureDefinition sd = cu.fetchProfileByIdentifier(tid); if (sd == null) { - ok = rule(errors, "2023-10-20", IssueType.INVALID, element.line(), element.col(), stack.getLiteralPath(), false, t.hasChild("extension") ? I18nConstants.CDA_UNKNOWN_TEMPLATE_EXT : I18nConstants.CDA_UNKNOWN_TEMPLATE, t.getChildValue("root"), t.getChildValue("extension")) && ok; + hint(errors, "2023-10-20", IssueType.INVALID, element.line(), element.col(), stack.getLiteralPath(), false, t.hasChild("extension") ? I18nConstants.CDA_UNKNOWN_TEMPLATE_EXT : I18nConstants.CDA_UNKNOWN_TEMPLATE, t.getChildValue("root"), t.getChildValue("extension")); } else { ElementDefinition ed = sd.getSnapshot().getElementFirstRep(); if (!element.hasValidated(sd, ed)) { diff --git a/pom.xml b/pom.xml index 13c349333..92fd2100c 100644 --- a/pom.xml +++ b/pom.xml @@ -20,7 +20,7 @@ 32.0.1-jre 6.4.1 - 1.4.13 + 1.4.14-SNAPSHOT 2.15.2 5.9.2 1.8.2 From e4a1a556a2d3bc266acc032cda1dd04d2fff8548 Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Mon, 30 Oct 2023 23:59:35 +1100 Subject: [PATCH 08/22] get sql viewDefinition implementation passing all tests --- .../org/hl7/fhir/r5/model/ExpressionNode.java | 4 + .../java/org/hl7/fhir/r5/utils/sql/Cell.java | 6 + .../org/hl7/fhir/r5/utils/sql/Column.java | 37 ++++ .../org/hl7/fhir/r5/utils/sql/ColumnKind.java | 2 +- .../org/hl7/fhir/r5/utils/sql/Provider.java | 2 +- .../org/hl7/fhir/r5/utils/sql/Runner.java | 94 +++++--- .../hl7/fhir/r5/utils/sql/StorageJson.java | 4 +- .../hl7/fhir/r5/utils/sql/StorageSqlite3.java | 10 +- .../org/hl7/fhir/r5/utils/sql/Validator.java | 204 +++++++++++------- .../org/hl7/fhir/r5/sql/SQLOnFhirTests.java | 5 +- 10 files changed, 248 insertions(+), 120 deletions(-) diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/model/ExpressionNode.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/model/ExpressionNode.java index 0742ef2e9..d4e3b697e 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/model/ExpressionNode.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/model/ExpressionNode.java @@ -729,5 +729,9 @@ public class ExpressionNode { } return names; } + + public boolean isNullSet() { + return kind == Kind.Constant && constant == null; + } } \ No newline at end of file diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/sql/Cell.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/sql/Cell.java index 0e8e37f9a..8e2e07c5e 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/sql/Cell.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/sql/Cell.java @@ -13,6 +13,12 @@ public class Cell { this.column = column; } + public Cell(Column column, Value value) { + super(); + this.column = column; + this.values.add(value); + } + public Column getColumn() { return column; } diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/sql/Column.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/sql/Column.java index abddd4664..745e5c99d 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/sql/Column.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/sql/Column.java @@ -7,6 +7,7 @@ public class Column { private String type; private ColumnKind kind; private boolean isColl; + private boolean duplicateReported; protected Column() { super(); @@ -57,6 +58,42 @@ public class Column { public void setColl(boolean isColl) { this.isColl = isColl; } + + public String diff(Column other) { + if (!name.equals(other.name)) { + return "Names differ: '"+name+"' vs '"+other.name+"'"; + } + if (kind != ColumnKind.Null && other.kind != ColumnKind.Null) { + if (length != other.length) { + return "Lengths differ: '"+length+"' vs '"+other.length+"'"; + } + if (kind != other.kind) { + return "Kinds differ: '"+kind+"' vs '"+other.kind+"'"; + } + if (isColl != other.isColl) { + return "Collection status differs: '"+isColl+"' vs '"+other.isColl+"'"; + } + } else if (kind == ColumnKind.Null) { + kind = other.kind; + length = other.length; + isColl = other.isColl; + } + return null; + } + + public boolean isDuplicateReported() { + return duplicateReported; + } + + public void setDuplicateReported(boolean duplicateReported) { + this.duplicateReported = duplicateReported; + } + + @Override + public String toString() { + return "Column [name=" + name + ", length=" + length + ", type=" + type + ", kind=" + kind + ", isColl=" + isColl + + "]"; + } } diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/sql/ColumnKind.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/sql/ColumnKind.java index a1733f1d6..536d2addb 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/sql/ColumnKind.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/sql/ColumnKind.java @@ -1,5 +1,5 @@ package org.hl7.fhir.r5.utils.sql; public enum ColumnKind { - String, DateTime, Integer, Decimal, Binary, Time, Boolean, Complex + String, DateTime, Integer, Decimal, Binary, Time, Boolean, Complex, Null } diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/sql/Provider.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/sql/Provider.java index d1aeeaabb..9e464a330 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/sql/Provider.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/sql/Provider.java @@ -7,5 +7,5 @@ import org.hl7.fhir.r5.model.Base; public interface Provider { List fetch(String resourceType); - Base resolveReference(String ref, String resourceType); + Base resolveReference(Base rootResource, String ref, String specifiedResourceType); } diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/sql/Runner.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/sql/Runner.java index 5087a497d..ea4ac1a10 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/sql/Runner.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/sql/Runner.java @@ -24,6 +24,7 @@ import org.hl7.fhir.r5.utils.FHIRPathEngine; import org.hl7.fhir.r5.utils.FHIRPathEngine.IEvaluationContext; import org.hl7.fhir.r5.utils.FHIRPathUtilityClasses.FunctionDetails; import org.hl7.fhir.utilities.json.model.JsonObject; +import org.hl7.fhir.utilities.validation.ValidationMessage; public class Runner implements IEvaluationContext { @@ -33,9 +34,8 @@ public class Runner implements IEvaluationContext { private List prohibitedNames = new ArrayList(); private FHIRPathEngine fpe; - private List columns = new ArrayList<>(); - private String resourceName; + private List issues; public IWorkerContext getContext() { @@ -86,15 +86,15 @@ public class Runner implements IEvaluationContext { } Validator validator = new Validator(context, fpe, prohibitedNames, storage.supportsArrays(), storage.supportsComplexTypes(), storage.needsName()); validator.checkViewDefinition(path, viewDefinition); + issues = validator.getIssues(); validator.dump(); validator.check(); resourceName = validator.getResourceName(); - columns = validator.getColumns(); evaluate(viewDefinition); } private void evaluate(JsonObject vd) { - Store store = storage.createStore(vd.asString("name"), columns); + Store store = storage.createStore(vd.asString("name"), (List) vd.getUserData("columns")); List data = provider.fetch(resourceName); @@ -130,7 +130,20 @@ public class Runner implements IEvaluationContext { if (select.has("forEach")) { focus.addAll(executeForEach(select, b)); } else if (select.has("forEachOrNull")) { + focus.addAll(executeForEachOrNull(select, b)); + if (focus.isEmpty()) { + List columns = (List) select.getUserData("columns"); + for (List row : rows) { + for (Column c : columns) { + Cell cell = cell(row, c.getName()); + if (cell == null) { + row.add(new Cell(c, null)); + } + } + } + return; + } } else { focus.add(b); } @@ -149,19 +162,30 @@ public class Runner implements IEvaluationContext { executeColumn(column, f, rowsToAdd); } - for (JsonObject sub : select.getJsonObjects("unionAll")) { - executeSelect(sub, f, rowsToAdd); - } - for (JsonObject sub : select.getJsonObjects("select")) { executeSelect(sub, f, rowsToAdd); } + + executeUnionAll(select.getJsonObjects("unionAll"), f, rowsToAdd); + rows.addAll(rowsToAdd); } } - private List executeUnion(JsonObject focus, Base b, List> rows) { - throw new FHIRException("union is not supported"); + private void executeUnionAll(List unionList, Base b, List> rows) { + if (unionList.isEmpty()) { + return; + } + List> sourceRows = new ArrayList<>(); + sourceRows.addAll(rows); + rows.clear(); + + for (JsonObject union : unionList) { + List> tempRows = new ArrayList<>(); + tempRows.addAll(sourceRows); + executeSelect(union, b, tempRows); + rows.addAll(tempRows); + } } private List> cloneRows(List> rows) { @@ -191,9 +215,6 @@ public class Runner implements IEvaluationContext { ExpressionNode n = (ExpressionNode) focus.getUserData("forEachOrNull"); List result = new ArrayList<>(); result.addAll(fpe.evaluate(b, n)); - if (result.size() == 0) { - result.add(null); - } return result; } @@ -203,23 +224,27 @@ public class Runner implements IEvaluationContext { if (b != null) { bl2.addAll(fpe.evaluate(b, n)); } - String name = column.getUserString("name"); - for (List row : rows) { - Cell c = cell(row, name); - if (c == null) { - c = new Cell(column(name)); - row.add(c); - } - if (!bl2.isEmpty()) { - if (bl2.size() + c.getValues().size() > 1) { - // this is a problem if collection != true or if the storage can't deal with it - // though this should've been picked up before now - but there are circumstances where it wouldn't be - if (!c.getColumn().isColl()) { - throw new FHIRException("The column "+c.getColumn().getName()+" is not allowed multiple values, but at least one row has multiple values"); + Column col = (Column) column.getUserData("column"); + if (col == null) { + System.out.println("Error"); + } else { + for (List row : rows) { + Cell c = cell(row, col.getName()); + if (c == null) { + c = new Cell(col); + row.add(c); + } + if (!bl2.isEmpty()) { + if (bl2.size() + c.getValues().size() > 1) { + // this is a problem if collection != true or if the storage can't deal with it + // though this should've been picked up before now - but there are circumstances where it wouldn't be + if (!c.getColumn().isColl()) { + throw new FHIRException("The column "+c.getColumn().getName()+" is not allowed multiple values, but at least one row has multiple values"); + } + } + for (Base b2 : bl2) { + c.getValues().add(genValue(c.getColumn(), b2)); } - } - for (Base b2 : bl2) { - c.getValues().add(genValue(c.getColumn(), b2)); } } } @@ -299,7 +324,7 @@ public class Runner implements IEvaluationContext { } } - private Column column(String columnName) { + private Column column(String columnName, List columns) { for (Column t : columns) { if (t.getName().equalsIgnoreCase(columnName)) { return t; @@ -353,7 +378,7 @@ public class Runner implements IEvaluationContext { public List executeFunction(FHIRPathEngine engine, Object appContext, List focus, String functionName, List> parameters) { switch (functionName) { case "getResourceKey" : return executeResourceKey(focus); - case "getReferenceKey" : return executeReferenceKey(focus, parameters); + case "getReferenceKey" : return executeReferenceKey(null, focus, parameters); default: throw new Error("Not known: "+functionName); } } @@ -375,7 +400,7 @@ public class Runner implements IEvaluationContext { return base; } - private List executeReferenceKey(List focus, List> parameters) { + private List executeReferenceKey(Base rootResource, List focus, List> parameters) { String rt = null; if (parameters.size() > 0) { rt = parameters.get(0).get(0).primitiveValue(); @@ -395,7 +420,7 @@ public class Runner implements IEvaluationContext { throw new FHIRException("Unable to generate a reference key based on a "+res.fhirType()); } if (ref != null) { - Base target = provider.resolveReference(ref, rt); + Base target = provider.resolveReference(rootResource, ref, rt); if (target != null) { if (!res.hasUserData("Storage.key")) { String key = storage.getKeyForTargetResource(target); @@ -437,6 +462,9 @@ public class Runner implements IEvaluationContext { public boolean paramIsType(String name, int index) { return "getReferenceKey".equals(name); } + public List getIssues() { + return issues; + } } diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/sql/StorageJson.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/sql/StorageJson.java index 9aca2cb22..d0e3aaeed 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/sql/StorageJson.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/sql/StorageJson.java @@ -48,7 +48,9 @@ public class StorageJson implements Storage { } private JsonElement makeJsonNode(Value value) { - if (value.getValueInt() != null) { + if (value == null) { + return new JsonNull(); + } else if (value.getValueInt() != null) { return new JsonNumber(value.getValueInt().intValue()); } if (value.getValueBoolean() != null) { diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/sql/StorageSqlite3.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/sql/StorageSqlite3.java index 0332e17fd..1a32d9c46 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/sql/StorageSqlite3.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/sql/StorageSqlite3.java @@ -2,6 +2,7 @@ package org.hl7.fhir.r5.utils.sql; import java.sql.Connection; import java.sql.PreparedStatement; +import java.sql.SQLType; import java.util.List; import org.hl7.fhir.exceptions.FHIRException; @@ -27,7 +28,7 @@ public class StorageSqlite3 implements Storage { private Connection conn; private int nextKey = 0; - protected StorageSqlite3(Connection conn) { + public StorageSqlite3(Connection conn) { super(); this.conn = conn; } @@ -38,7 +39,7 @@ public class StorageSqlite3 implements Storage { CommaSeparatedStringBuilder fields = new CommaSeparatedStringBuilder(", "); CommaSeparatedStringBuilder values = new CommaSeparatedStringBuilder(", "); StringBuilder b = new StringBuilder(); - b.append("Create Table "+name+" { "); + b.append("Create Table "+name+" ( "); b.append("ViewRowKey integer NOT NULL"); for (Column column : columns) { b.append(", "+column.getName()+" "+sqliteType(column.getKind())+" NULL"); // index columns are always nullable @@ -48,7 +49,7 @@ public class StorageSqlite3 implements Storage { b.append(", PRIMARY KEY (ViewRowKey))\r\n"); conn.createStatement().execute(b.toString()); - String isql = "Insert into "+name+" ("+fields.toString()+") values ("+values.toString()+")"; + String isql = "Insert into "+name+" (ViewRowKey, "+fields.toString()+") values (?, "+values.toString()+")"; PreparedStatement psql = conn.prepareStatement(isql); return new SQLiteStore(name, psql); } catch (Exception e) { @@ -79,6 +80,8 @@ public class StorageSqlite3 implements Storage { for (int i = 0; i < cells.size(); i++) { Cell c = cells.get(i); switch (c.getColumn().getKind()) { + case Null: + p.setNull(i+2, java.sql.Types.NVARCHAR); case Binary: p.setBytes(i+2, c.getValues().size() == 0 ? null : c.getValues().get(0).getValueBinary()); break; @@ -103,6 +106,7 @@ public class StorageSqlite3 implements Storage { case Complex: throw new FHIRException("SQLite runner does not handle complexes"); } } + p.execute(); } catch (Exception e) { throw new FHIRException(e); } diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/sql/Validator.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/sql/Validator.java index 7aa5cc8f9..c2dbd1b54 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/sql/Validator.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/sql/Validator.java @@ -18,6 +18,7 @@ import org.hl7.fhir.utilities.json.model.JsonBoolean; import org.hl7.fhir.utilities.json.model.JsonElement; import org.hl7.fhir.utilities.json.model.JsonNumber; import org.hl7.fhir.utilities.json.model.JsonObject; +import org.hl7.fhir.utilities.json.model.JsonProperty; import org.hl7.fhir.utilities.json.model.JsonString; import org.hl7.fhir.utilities.validation.ValidationMessage; import org.hl7.fhir.utilities.validation.ValidationMessage.IssueSeverity; @@ -35,7 +36,6 @@ public class Validator { private Boolean needsName; private String resourceName; - private List columns = new ArrayList(); private String name; public Validator(IWorkerContext context, FHIRPathEngine fpe, List prohibitedNames, Boolean arrays, Boolean complexTypes, Boolean needsName) { @@ -52,11 +52,10 @@ public class Validator { return resourceName; } - public List getColumns() { - return columns; - } - public void checkViewDefinition(String path, JsonObject viewDefinition) { + public void checkViewDefinition(String path, JsonObject viewDefinition) { + checkProperties(viewDefinition, path, "url", "identifier", "name", "version", "title", "status", "experimental", "date", "publisher", "contact", "description", "useContext", "copyright", "resource", "constant", "select", "where"); + JsonElement nameJ = viewDefinition.get("name"); if (nameJ == null) { if (needsName == null) { @@ -76,9 +75,12 @@ public class Validator { } } + List columns = new ArrayList<>(); + viewDefinition.setUserData("columns", columns); + JsonElement resourceNameJ = viewDefinition.get("resource"); if (resourceNameJ == null) { - error(path, viewDefinition, "No resource provided", IssueType.REQUIRED); + error(path, viewDefinition, "No resource specified", IssueType.REQUIRED); } else if (!(resourceNameJ instanceof JsonString)) { error(path, viewDefinition, "resource must be a string", IssueType.INVALID); } else { @@ -102,29 +104,24 @@ public class Validator { } TypeDetails t = new TypeDetails(CollectionStatus.SINGLETON, resourceName); - if (viewDefinition.has("forEach")) { - checkForEach(path, viewDefinition, viewDefinition.get("forEach"), t); - } else if (viewDefinition.has("forEachOrNull")) { - checkForEachOrNull(path, viewDefinition, viewDefinition.get("forEachOrNull"), t); - } else if (viewDefinition.has("unionAll")) { - checkUnion(path, viewDefinition, viewDefinition.get("unionAll"), t); - } else { - i = 0; - if (checkAllObjects(path, viewDefinition, "select")) { - for (JsonObject select : viewDefinition.getJsonObjects("select")) { - checkSelect(path+".select["+i+"]", select, t); - i++; - } - if (i == 0) { - error(path, viewDefinition, "No select statements found", IssueType.REQUIRED); - } + i = 0; + if (checkAllObjects(path, viewDefinition, "select")) { + for (JsonObject select : viewDefinition.getJsonObjects("select")) { + columns.addAll(checkSelect(path+".select["+i+"]", select, t)); + i++; + } + if (i == 0) { + error(path, viewDefinition, "No select statements found", IssueType.REQUIRED); } } } } } - private void checkSelect(String path, JsonObject select, TypeDetails t) { + private List checkSelect(String path, JsonObject select, TypeDetails t) { + List columns = new ArrayList<>(); + select.setUserData("columns", columns); + checkProperties(select, path, "column", "select", "forEach", "forEachOrNull", "unionAll"); if (select.has("forEach")) { t = checkForEach(path, select, select.get("forEach"), t); @@ -133,24 +130,18 @@ public class Validator { } if (t != null) { - boolean content = false; - - if (select.has("unionAll")) { - content = checkUnion(path, select, select.get("unionAll"), t); - } if (select.has("column")) { JsonElement a = select.get("column"); if (!(a instanceof JsonArray)) { error(path+".column", a, "column is not an array", IssueType.INVALID); } else { - content = true; int i = 0; for (JsonElement e : ((JsonArray) a)) { if (!(e instanceof JsonObject)) { error(path+".column["+i+"]", a, "column["+i+"] is a "+e.type().toName()+" not an object", IssueType.INVALID); } else { - checkColumn(path+".column["+i+"]", (JsonObject) e, t); + columns.add(checkColumn(path+".column["+i+"]", (JsonObject) e, t)); } } } @@ -161,47 +152,98 @@ public class Validator { if (!(a instanceof JsonArray)) { error(path+".select", a, "select is not an array", IssueType.INVALID); } else { - content = true; int i = 0; for (JsonElement e : ((JsonArray) a)) { if (!(e instanceof JsonObject)) { error(path+".select["+i+"]", e, "select["+i+"] is not an object", IssueType.INVALID); } else { - checkSelect(path+".select["+i+"]", (JsonObject) e, t); + columns.addAll(checkSelect(path+".select["+i+"]", (JsonObject) e, t)); } } } } - if (!content) { + if (select.has("unionAll")) { + columns.addAll(checkUnion(path, select, select.get("unionAll"), t)); + } + if (columns.isEmpty()) { error(path, select, "The select has no columns or selects", IssueType.REQUIRED); + } else { + checkColumnNamesUnique(select, path, columns); } } + return columns; } - private boolean checkUnion(String path, JsonObject focus, JsonElement expression, TypeDetails t) { + private void checkColumnNamesUnique(JsonObject select, String path, List columns) { + Set names = new HashSet<>(); + for (Column col : columns) { + if (col != null) { + if (!names.contains(col.getName())) { + names.add(col.getName()); + } else if (!col.isDuplicateReported()) { + col.setDuplicateReported(true); + error(path, select, "Duplicate Column Name '"+col.getName()+"'", IssueType.BUSINESSRULE); + } + } + } + } + + private List checkUnion(String path, JsonObject focus, JsonElement expression, TypeDetails t) { JsonElement a = focus.get("unionAll"); if (!(a instanceof JsonArray)) { - error(path+".union", a, "union is not an array", IssueType.INVALID); - return false; - } else { + error(path+".unionAll", a, "union is not an array", IssueType.INVALID); + return null; + } else { + List> unionColumns = new ArrayList<>(); int i = 0; for (JsonElement e : ((JsonArray) a)) { if (!(e instanceof JsonObject)) { - error(path+".union["+i+"]", e, "union["+i+"] is not an object", IssueType.INVALID); + error(path+".unionAll["+i+"]", e, "unionAll["+i+"] is not an object", IssueType.INVALID); } else { - checkSelect(path+".union["+i+"]", (JsonObject) e, t); + unionColumns.add(checkSelect(path+".unionAll["+i+"]", (JsonObject) e, t)); } + i++; } if (i < 2) { - warning(path+".union", a, "union should have more than one item"); + warning(path+".unionAll", a, "unionAll should have more than one item"); + } + if (unionColumns.size() > 1) { + List columns = unionColumns.get(0); + for (int ic = 1; ic < unionColumns.size(); ic++) { + String diff = columnDiffs(columns, unionColumns.get(ic)); + if (diff != null) { + error(path+".unionAll["+i+"]", ((JsonArray) a).get(ic), "unionAll["+i+"] column definitions do not match: "+diff, IssueType.INVALID); + } + } + a.setUserData("colunms", columns); + return columns; } - return true; } + return null; } - private void checkColumn(String path, JsonObject column, TypeDetails t) { + private String columnDiffs(List list1, List list2) { + if (list1.size() == list2.size()) { + for (int i = 0; i < list1.size(); i++) { + if (list1.get(i) == null || list2.get(i) == null) { + return null; // just suppress any addition errors + } + String diff = list1.get(i).diff(list2.get(i)); + if (diff != null) { + return diff+" at #"+i; + } + } + return null; + } else { + return "Column counts differ: "+list1.size()+" vs "+list2.size(); + } + } + + private Column checkColumn(String path, JsonObject column, TypeDetails t) { + checkProperties(column, path, "path", "name", "description", "collection", "type", "tag"); + if (!column.has("path")) { error(path, column, "no path found", IssueType.INVALID); } else { @@ -253,7 +295,7 @@ public class Validator { // ok, name is sorted! if (columnName != null) { column.setUserData("name", columnName); - boolean isColl = (td.getCollectionStatus() != CollectionStatus.SINGLETON) || column(columnName) != null; + boolean isColl = (td.getCollectionStatus() != CollectionStatus.SINGLETON); if (column.has("collection")) { JsonElement collectionJ = column.get("collection"); if (!(collectionJ instanceof JsonBoolean)) { @@ -273,24 +315,28 @@ public class Validator { warning(path, expression, "column appears to be a collection, but this is not allowed in this context"); } } - // ok collection is sorted Set types = new HashSet<>(); - for (String type : td.getTypes()) { - types.add(simpleType(type)); - } + if (node.isNullSet()) { + types.add("null"); + } else { + // ok collection is sorted + for (String type : td.getTypes()) { + types.add(simpleType(type)); + } - JsonElement typeJ = column.get("type"); - if (typeJ != null) { - if (typeJ instanceof JsonString) { - String type = typeJ.asString(); - if (!td.hasType(type)) { - error(path+".type", typeJ, "The path expression does not return a value of the type '"+type, IssueType.VALUE); + JsonElement typeJ = column.get("type"); + if (typeJ != null) { + if (typeJ instanceof JsonString) { + String type = typeJ.asString(); + if (!td.hasType(type)) { + error(path+".type", typeJ, "The path expression does not return a value of the type '"+type, IssueType.VALUE); + } else { + types.clear(); + types.add(simpleType(type)); + } } else { - types.clear(); - types.add(simpleType(type)); + error(path+".type", typeJ, "type must be a string", IssueType.INVALID); } - } else { - error(path+".type", typeJ, "type must be a string", IssueType.INVALID); } } if (types.size() != 1) { @@ -298,7 +344,7 @@ public class Validator { } else { String type = types.iterator().next(); boolean ok = false; - if (!isSimpleType(type)) { + if (!isSimpleType(type) && !"null".equals(type)) { if (complexTypes) { warning(path, expression, "Column is a complex type. This is not supported in some Runners"); } else if (!complexTypes) { @@ -310,28 +356,21 @@ public class Validator { ok = true; } if (ok) { - Column col = column(columnName); - if (col != null) { - if (!col.getType().equals(type)) { - error(path, expression, "Duplicate definition for "+columnName+" has different types ("+col.getType()+" vs "+type+")", IssueType.BUSINESSRULE); - } - if (col.isColl() != isColl) { - error(path, expression, "Duplicate definition for "+columnName+" has different status for collection ("+col.isColl()+" vs "+isColl+")", IssueType.BUSINESSRULE); - } - } else { - columns.add(new Column(columnName, isColl, type, kindForType(type))); - - } + Column col = new Column(columnName, isColl, type, kindForType(type)); + column.setUserData("column", col); + return col; } } } } } } + return null; } private ColumnKind kindForType(String type) { switch (type) { + case "null": return ColumnKind.Null; case "dateTime": return ColumnKind.DateTime; case "boolean": return ColumnKind.Boolean; case "integer": return ColumnKind.Integer; @@ -343,15 +382,6 @@ public class Validator { } } - private Column column(String columnName) { - for (Column t : columns) { - if (t.getName().equalsIgnoreCase(columnName)) { - return t; - } - } - return null; - } - private boolean isSimpleType(String type) { return Utilities.existsInList(type, "dateTime", "boolean", "integer", "decimal", "string", "base64Binary"); } @@ -433,6 +463,7 @@ public class Validator { } private void checkConstant(String path, JsonObject constant) { + checkProperties(constant, path, "name", "valueBase64Binary", "valueBoolean", "valueCanonical", "valueCode", "valueDate", "valueDateTime", "valueDecimal", "valueId", "valueInstant", "valueInteger", "valueInteger64", "valueOid", "valueString", "valuePositiveInt", "valueTime", "valueUnsignedInt", "valueUri", "valueUrl", "valueUuid"); JsonElement nameJ = constant.get("name"); if (nameJ == null) { error(path, constant, "No name provided", IssueType.REQUIRED); @@ -508,6 +539,8 @@ public class Validator { } } private void checkWhere(String path, JsonObject where) { + checkProperties(where, path, "path", "description"); + String expr = where.asString("path"); if (expr == null) { error(path, where, "No path provided", IssueType.REQUIRED); @@ -534,6 +567,19 @@ public class Validator { } } + private void checkProperties(JsonObject obj, String path, String... names) { + for (JsonProperty p : obj.getProperties()) { + boolean nameOk = "extension".equals(p.getName()); + for (String name : names) { + nameOk = nameOk || name.equals(p.getName()); + } + if (!nameOk) { + error(path+"."+p.getName(), p.getValue(), "Unknown JSON "+p.getValue().type().name(), IssueType.UNKNOWN); + } + } + + } + private boolean isValidName(String name) { boolean first = true; for (char c : name.toCharArray()) { diff --git a/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/sql/SQLOnFhirTests.java b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/sql/SQLOnFhirTests.java index 74daafaec..e0bf364e9 100644 --- a/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/sql/SQLOnFhirTests.java +++ b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/sql/SQLOnFhirTests.java @@ -54,7 +54,7 @@ public class SQLOnFhirTests { } @Override - public Base resolveReference(String ref, String rt) { + public Base resolveReference(Base rootResource, String ref, String rt) { if (ref == null) { return null; } @@ -109,7 +109,7 @@ public class SQLOnFhirTests { @SuppressWarnings("deprecation") @ParameterizedTest(name = "{index}: file {0}") @MethodSource("data") - @Disabled + //@Disabled public void test(String name, TestDetails test) throws FileNotFoundException, IOException, FHIRException, org.hl7.fhir.exceptions.FHIRException, UcumException { this.details = test; Runner runner = new Runner(); @@ -126,6 +126,7 @@ public class SQLOnFhirTests { runner.execute(test.path+".view", test.testCase.getJsonObject("view")); results = store.getRows(); } catch (Exception e) { + e.printStackTrace(); Assertions.assertTrue(test.testCase.has("expectError"), e.getMessage()); } if (results != null) { From 809b2f68ea627b6adb1d21ec48c080004163653c Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Tue, 31 Oct 2023 16:57:25 +1100 Subject: [PATCH 09/22] Fix broken links in code system rendering of parents --- .../org/hl7/fhir/r4/context/BaseWorkerContext.java | 10 ++++++---- .../org/hl7/fhir/r4b/context/BaseWorkerContext.java | 12 +++++++----- .../org/hl7/fhir/r5/context/BaseWorkerContext.java | 12 +++++++----- .../hl7/fhir/r5/renderers/CodeSystemRenderer.java | 2 +- 4 files changed, 21 insertions(+), 15 deletions(-) diff --git a/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/context/BaseWorkerContext.java b/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/context/BaseWorkerContext.java index 31ffcf5aa..46c29efac 100644 --- a/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/context/BaseWorkerContext.java +++ b/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/context/BaseWorkerContext.java @@ -469,10 +469,12 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte tlog("$expand on " + txCache.summary(vs)); try { ValueSet result = txClient.expandValueset(vs, p, params); - if (!result.hasUrl()) - result.setUrl(vs.getUrl()); - if (!result.hasUrl()) - throw new Error("no url in expand value set 2"); + if (result != null) { + if (!result.hasUrl()) + result.setUrl(vs.getUrl()); + if (!result.hasUrl()) + throw new Error("no url in expand value set 2"); + } res = new ValueSetExpansionOutcome(result).setTxLink(txLog.getLastId()); } catch (Exception e) { res = new ValueSetExpansionOutcome(e.getMessage() == null ? e.getClass().getName() : e.getMessage(), diff --git a/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/context/BaseWorkerContext.java b/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/context/BaseWorkerContext.java index 1b1e7c27b..a3e4a6fd8 100644 --- a/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/context/BaseWorkerContext.java +++ b/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/context/BaseWorkerContext.java @@ -805,11 +805,13 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte tlog("$expand on " + txCache.summary(vs)); try { ValueSet result = txClient.expandValueset(vs, p, params); - if (!result.hasUrl()) { - result.setUrl(vs.getUrl()); - } - if (!result.hasUrl()) { - throw new Error(formatMessage(I18nConstants.NO_URL_IN_EXPAND_VALUE_SET_2)); + if (result != null) { + if (!result.hasUrl()) { + result.setUrl(vs.getUrl()); + } + if (!result.hasUrl()) { + throw new Error(formatMessage(I18nConstants.NO_URL_IN_EXPAND_VALUE_SET_2)); + } } res = new ValueSetExpansionOutcome(result).setTxLink(txLog.getLastId()); } catch (Exception e) { 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 e5b80fd8d..4ac5070f1 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 @@ -952,11 +952,13 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte txLog("$expand on "+txCache.summary(vs)); try { ValueSet result = tcc.getClient().expandValueset(vs, p, params); - if (!result.hasUrl()) { - result.setUrl(vs.getUrl()); - } - if (!result.hasUrl()) { - throw new Error(formatMessage(I18nConstants.NO_URL_IN_EXPAND_VALUE_SET_2)); + if (result != null) { + if (!result.hasUrl()) { + result.setUrl(vs.getUrl()); + } + if (!result.hasUrl()) { + throw new Error(formatMessage(I18nConstants.NO_URL_IN_EXPAND_VALUE_SET_2)); + } } res = new ValueSetExpansionOutcome(result).setTxLink(txLog.getLastId()); } catch (Exception e) { 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 d4d0994d0..e84e767ac 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 @@ -542,7 +542,7 @@ public class CodeSystemRenderer extends TerminologyRenderer { } else if (pcv.hasValueStringType() && Utilities.isAbsoluteUrlLinkable(pcv.getValue().primitiveValue())) { td.ah(pcv.getValue().primitiveValue()).tx(pcv.getValue().primitiveValue()); } else if ("parent".equals(pcv.getCode())) { - td.ah("#"+cs.getId()+"-"+pcv.getValue().primitiveValue()).addText(pcv.getValue().primitiveValue()); + td.ah("#"+cs.getId()+"-"+Utilities.nmtokenize(pcv.getValue().primitiveValue())).addText(pcv.getValue().primitiveValue()); } else { td.addText(pcv.getValue().primitiveValue()); } From c3f469374a49dae44bf9605504b7853d23f3636e Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Tue, 31 Oct 2023 16:57:42 +1100 Subject: [PATCH 10/22] fix broken links in extension references done by [[[]]] --- .../java/org/hl7/fhir/r5/renderers/DataRenderer.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/DataRenderer.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/DataRenderer.java index 88adf4f63..2627640dd 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/DataRenderer.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/DataRenderer.java @@ -161,9 +161,17 @@ public class DataRenderer extends Renderer implements CodeResolver { if (p == null) p = getContext().getWorker().fetchResource(StructureDefinition.class, link); if (p != null) { + if ("Extension".equals(p.getType())) { + path = null; + } else if (p.hasSnapshot()) { + path = p.getSnapshot().getElementFirstRep().getPath(); + } else if (Utilities.isAbsoluteUrl(path)) { + path = null; + } url = p.getWebPath(); - if (url == null) + if (url == null) { url = p.getUserString("filename"); + } } else throw new DefinitionException("Unable to resolve markdown link "+link); From 5898691293e817edc4b1b46e8b357f69ff220b31 Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Tue, 31 Oct 2023 16:58:12 +1100 Subject: [PATCH 11/22] Fixes to Search Parameter rendering per FHIR-I decision --- .../r5/renderers/SearchParameterRenderer.java | 23 ++++++++++++------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/SearchParameterRenderer.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/SearchParameterRenderer.java index e50332d38..d7c9b260e 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/SearchParameterRenderer.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/SearchParameterRenderer.java @@ -98,17 +98,24 @@ public class SearchParameterRenderer extends TerminologyRenderer { } } } - tr = tbl.tr(); + tr = tbl.tr(); tr.td().tx("Multiples"); - if (spd.getMultipleAnd() && spd.getMultipleOr()) { - tr.td().tx("The parameter can repeat (and) and can have repeating values (or)"); - } else if (spd.getMultipleOr()) { - tr.td().tx("The parameter can repeat (and) but each repeat can only have one value"); + XhtmlNode ul = tr.td().ul(); + if (!spd.hasMultipleAnd()) { + ul.li().tx("multipleAnd: It's up to the server whether the parameter may repeat in order to specify multiple values that must all be true"); } else if (spd.getMultipleAnd()) { - tr.td().tx("The parameter cannot repeat (and) but the single parameter can have multiple values (or)"); - } else { - tr.td().tx("The parameter cannot repeat or have multiple values"); + ul.li().tx("multipleAnd: The parameter may repeat in order to specify multiple values that must all be true"); + } else { + ul.li().tx("multipleAnd: The parameter may only appear once"); } + if (!spd.hasMultipleOr()) { + ul.li().tx("multipleOr: It's up to the server whether the parameter can have multiple values (separated by comma) where at least one must be true"); + } else if (spd.getMultipleOr()) { + ul.li().tx("multipleOr: The parameter may have multiple values (separated by comma) where at least one must be true"); + } else { + ul.li().tx("multipleOr: The parameter may only have one value (no comma separators)"); + } + if (spd.hasComparator()) { tr = tbl.tr(); tr.td().tx("Comparators"); From d419d5a5e68930c3f57eb4b80ff829ed5658f7e3 Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Tue, 31 Oct 2023 16:59:49 +1100 Subject: [PATCH 12/22] Handle unknown constants properly, and fix handling of type ancestors at the root --- .../org/hl7/fhir/r5/utils/FHIRPathEngine.java | 54 +++++++++++++++---- 1 file changed, 43 insertions(+), 11 deletions(-) diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/FHIRPathEngine.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/FHIRPathEngine.java index 9b4932450..c93c93fa0 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/FHIRPathEngine.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/FHIRPathEngine.java @@ -78,6 +78,7 @@ import org.hl7.fhir.utilities.validation.ValidationOptions; import org.hl7.fhir.utilities.xhtml.NodeType; import org.hl7.fhir.utilities.xhtml.XhtmlNode; +import ca.uhn.fhir.fhirpath.FhirPathExecutionException; import ca.uhn.fhir.model.api.TemporalPrecisionEnum; import ca.uhn.fhir.util.ElementUtil; @@ -3091,7 +3092,12 @@ public class FHIRPathEngine { } else if (hostServices == null) { throw makeException(expr, I18nConstants.FHIRPATH_UNKNOWN_CONSTANT, s); } else { - return hostServices.resolveConstantType(this, context.appInfo, s, explicitConstant); + TypeDetails v = hostServices.resolveConstantType(this, context.appInfo, s, explicitConstant); + if (v == null) { + throw makeException(expr, I18nConstants.FHIRPATH_UNKNOWN_CONSTANT, s); + } else { + return v; + } } } @@ -3145,7 +3151,7 @@ public class FHIRPathEngine { } private TypeDetails executeType(String type, ExpressionNode exp, boolean atEntry, TypeDetails focus, Set elementDependencies) throws PathEngineException, DefinitionException { - if (atEntry && Character.isUpperCase(exp.getName().charAt(0)) && hashTail(type).equals(exp.getName())) { // special case for start up + if (atEntry && Character.isUpperCase(exp.getName().charAt(0)) && (hashTail(type).equals(exp.getName()) || isAncestor(type, exp.getName()) )) { // special case for start up return new TypeDetails(CollectionStatus.SINGLETON, type); } TypeDetails result = new TypeDetails(focus.getCollectionStatus()); @@ -3154,6 +3160,21 @@ public class FHIRPathEngine { } + private boolean isAncestor(String wanted, String stated) { + try { + StructureDefinition sd = worker.fetchTypeDefinition(wanted); + while (sd != null) { + if (stated.equals(sd.getTypeName())) { + return true; + } + sd = worker.fetchResource(StructureDefinition.class, sd.getBaseDefinition()); + } + return false; + } catch (Exception e) { + return false; + } + } + private String hashTail(String type) { return type.contains("#") ? "" : type.substring(type.lastIndexOf("/")+1); } @@ -4318,7 +4339,11 @@ public class FHIRPathEngine { if (x == null) { return makeBoolean(false); } - return makeBoolean(checkHtmlNames(x)); + boolean ok = checkHtmlNames(x, true); + if (ok && VersionUtilities.isR6Plus(this.worker.getVersion())) { + ok = checkForContent(x); + } + return makeBoolean(ok); } private List funcHtmlChecks2(ExecutionContext context, List focus, ExpressionNode exp) throws FHIRException { @@ -4387,18 +4412,25 @@ public class FHIRPathEngine { return null; } - private boolean checkHtmlNames(XhtmlNode node) { + private boolean checkHtmlNames(XhtmlNode node, boolean block) { if (node.getNodeType() == NodeType.Comment) { if (node.getContent().startsWith("DOCTYPE")) return false; } if (node.getNodeType() == NodeType.Element) { - if (!Utilities.existsInList(node.getName(), - "p", "br", "div", "h1", "h2", "h3", "h4", "h5", "h6", "a", "span", "b", "em", "i", "strong", - "small", "big", "tt", "small", "dfn", "q", "var", "abbr", "acronym", "cite", "blockquote", "hr", "address", "bdo", "kbd", "q", "sub", "sup", - "ul", "ol", "li", "dl", "dt", "dd", "pre", "table", "caption", "colgroup", "col", "thead", "tr", "tfoot", "tbody", "th", "td", - "code", "samp", "img", "map", "area")) { - return false; + if (block) { + if (!Utilities.existsInList(node.getName(), + "p", "br", "div", "h1", "h2", "h3", "h4", "h5", "h6", "a", "span", "b", "em", "i", "strong", + "small", "big", "tt", "small", "dfn", "q", "var", "abbr", "acronym", "cite", "blockquote", "hr", "address", "bdo", "kbd", "q", "sub", "sup", + "ul", "ol", "li", "dl", "dt", "dd", "pre", "table", "caption", "colgroup", "col", "thead", "tr", "tfoot", "tbody", "th", "td", + "code", "samp", "img", "map", "area")) { + return false; + } + } else { + if (!Utilities.existsInList(node.getName(), + "a", "span", "b", "em", "i", "strong", "small", "big", "small", "q", "var", "abbr", "acronym", "cite", "kbd", "q", "sub", "sup", "code", "samp", "img", "map", "area")) { + return false; + } } for (String an : node.getAttributes().keySet()) { boolean ok = an.startsWith("xmlns") || Utilities.existsInList(an, @@ -4417,7 +4449,7 @@ public class FHIRPathEngine { } } for (XhtmlNode c : node.getChildNodes()) { - if (!checkHtmlNames(c)) { + if (!checkHtmlNames(c, block && !"p".equals(c))) { return false; } } From 1557e52f779a1b947056c865c94e8fad63bd7c6a Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Tue, 31 Oct 2023 17:00:20 +1100 Subject: [PATCH 13/22] disable sql on fhir tests until package is packaged properly by next release of IG publisher --- .../src/test/java/org/hl7/fhir/r5/sql/SQLOnFhirTests.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/sql/SQLOnFhirTests.java b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/sql/SQLOnFhirTests.java index e0bf364e9..861bcd154 100644 --- a/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/sql/SQLOnFhirTests.java +++ b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/sql/SQLOnFhirTests.java @@ -109,7 +109,7 @@ public class SQLOnFhirTests { @SuppressWarnings("deprecation") @ParameterizedTest(name = "{index}: file {0}") @MethodSource("data") - //@Disabled + @Disabled public void test(String name, TestDetails test) throws FileNotFoundException, IOException, FHIRException, org.hl7.fhir.exceptions.FHIRException, UcumException { this.details = test; Runner runner = new Runner(); From e061c221cf3237deae6ae79ce21a3800d94c5181 Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Tue, 31 Oct 2023 17:00:33 +1100 Subject: [PATCH 14/22] fix typo in WG name --- .../src/main/java/org/hl7/fhir/utilities/HL7WorkGroups.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/HL7WorkGroups.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/HL7WorkGroups.java index eea327241..24994497e 100644 --- a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/HL7WorkGroups.java +++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/HL7WorkGroups.java @@ -125,7 +125,7 @@ public class HL7WorkGroups { case "sd": return "Structured Documents"; case "sec": return "Security"; case "soa": return "Services Oriented Architecture"; - case "ti": return "Terminology Infrastructure Work Group"; + case "ti": return "Terminology Infrastructure"; case "tsmg": return "Terminology Services Management Group (TSMG)"; case "us": return "US Realm Steering Committee"; case "v2": return "V2 Management Group"; From 6c878dd9c0b3806f94636cc034ee169bc58e0a3f Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Tue, 31 Oct 2023 17:00:52 +1100 Subject: [PATCH 15/22] Validate contextInvariant in extension definitions --- .../main/java/org/hl7/fhir/utilities/i18n/I18nConstants.java | 2 ++ org.hl7.fhir.utilities/src/main/resources/Messages.properties | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/i18n/I18nConstants.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/i18n/I18nConstants.java index bc66ea886..973834dec 100644 --- a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/i18n/I18nConstants.java +++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/i18n/I18nConstants.java @@ -1012,6 +1012,8 @@ public class I18nConstants { public static final String TERMINOLOGY_TX_OID_MULTIPLE_MATCHES = "TERMINOLOGY_TX_OID_MULTIPLE_MATCHES"; public static final String CDA_UNKNOWN_TEMPLATE = "CDA_UNKNOWN_TEMPLATE"; public static final String CDA_UNKNOWN_TEMPLATE_EXT = "CDA_UNKNOWN_TEMPLATE_EXT"; + public static final String UNABLE_TO_DETERMINE_TYPE_CONTEXT_INV = "UNABLE_TO_DETERMINE_TYPE_CONTEXT_INV"; + public static final String ED_CONTEXT_INVARIANT_EXPRESSION_ERROR = "ED_CONTEXT_INVARIANT_EXPRESSION_ERROR"; } diff --git a/org.hl7.fhir.utilities/src/main/resources/Messages.properties b/org.hl7.fhir.utilities/src/main/resources/Messages.properties index cffdc8877..333f28dc6 100644 --- a/org.hl7.fhir.utilities/src/main/resources/Messages.properties +++ b/org.hl7.fhir.utilities/src/main/resources/Messages.properties @@ -928,7 +928,7 @@ NO_VALID_DISPLAY_FOUND_one = No valid Display Names found for {1}#{2} in the lan NO_VALID_DISPLAY_FOUND_other = No valid Display Names found for {1}#{2} in the languages {4} SD_NO_CONTEXT_WHEN_NOT_EXTENSION = The type is {0} so an extension context should not be specified SD_NO_CONTEXT_INV_WHEN_NOT_EXTENSION = The type is {0} so an extension context invariants should not be specified -SD_CONTEXT_SHOULD_NOT_BE_ELEMENT = Review the extension type: extensions should not have a context of {0} unless it''s really intended that they can be used anywhere +SD_CONTEXT_SHOULD_NOT_BE_ELEMENT = Review the extension type for {1}: extensions should not have a context of {0} unless it''s really intended that they can be used anywhere ED_PATH_WRONG_TYPE_MATCH = The path must be ''{0}'' not ''{1}'' when the type list is not constrained ATTEMPT_TO_CHANGE_SLICING = The element at {0} defines the slicing {1} but then an element in the slicing {2} tries to redefine the slicing to {3} REPEAT_SLICING_IGNORED = The element at {0} defines the slicing but then an element in the slicing {2} repeats it, which is ignored @@ -1069,3 +1069,5 @@ XSI_TYPE_UNNECESSARY = xsi:type is unnecessary at this point TERMINOLOGY_TX_OID_MULTIPLE_MATCHES = The OID ''{0}'' matches multiple code systems ({1}) CDA_UNKNOWN_TEMPLATE = The CDA Template {0} is not known CDA_UNKNOWN_TEMPLATE_EXT = The CDA Template {0} / {1} is not known +UNABLE_TO_DETERMINE_TYPE_CONTEXT_INV = The types could not be determined from the extension context, so the invariant can't be validated (types = {0}) +ED_CONTEXT_INVARIANT_EXPRESSION_ERROR = Error in constraint ''{0}'': {1} \ No newline at end of file From 89fc407479a1401cd6e14b25c98c4c870467ee51 Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Tue, 31 Oct 2023 17:00:59 +1100 Subject: [PATCH 16/22] fix --- .../type/StructureDefinitionValidator.java | 72 ++++++++++++++++++- 1 file changed, 69 insertions(+), 3 deletions(-) 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 18defe561..1d9497c1c 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 @@ -38,6 +38,7 @@ import org.hl7.fhir.r5.model.ValueSet; import org.hl7.fhir.r5.terminologies.utilities.TerminologyServiceErrorClass; import org.hl7.fhir.r5.utils.FHIRPathEngine; import org.hl7.fhir.r5.utils.ToolingExtensions; +import org.hl7.fhir.utilities.CommaSeparatedStringBuilder; import org.hl7.fhir.utilities.Utilities; import org.hl7.fhir.utilities.VersionUtilities; import org.hl7.fhir.utilities.i18n.I18nConstants; @@ -46,6 +47,7 @@ import org.hl7.fhir.utilities.validation.ValidationMessage.IssueType; import org.hl7.fhir.utilities.validation.ValidationOptions; import org.hl7.fhir.validation.BaseValidator; import org.hl7.fhir.validation.instance.utils.NodeStack; +import org.hl7.fhir.validation.instance.utils.ValidationContext; public class StructureDefinitionValidator extends BaseValidator { @@ -152,6 +154,7 @@ public class StructureDefinitionValidator extends BaseValidator { } } } + List extensions = src.getChildren("extension"); int c = 0; for (Element extension : extensions) { @@ -160,6 +163,13 @@ public class StructureDefinitionValidator extends BaseValidator { } c++; } + + List contextInvariants = src.getChildren("contextInvariant"); + c = 0; + for (Element contextInvariant : contextInvariants) { + ok = validateContextInvariant(errors, contextInvariant, src, stack.push(contextInvariant, c, null, null)) && ok; + c++; + } // if this is defining an extension, make sure that the extension fixed value matches the URL String type = src.getNamedChildValue("type"); @@ -344,7 +354,7 @@ public class StructureDefinitionValidator extends BaseValidator { cv = ec.primitiveValue(); } if ("element".equals(ct) && "Element".equals(cv)) { - warning(errors, "2023-04-23", IssueType.BUSINESSRULE, n.getLiteralPath(), false, I18nConstants.SD_CONTEXT_SHOULD_NOT_BE_ELEMENT, cv); + warning(errors, "2023-04-23", IssueType.BUSINESSRULE, n.getLiteralPath(), false, I18nConstants.SD_CONTEXT_SHOULD_NOT_BE_ELEMENT, cv, src.getNamedChildValue("id")); } } else { ok = rule(errors, "2023-04-23", IssueType.INVALID, n.getLiteralPath(), false, I18nConstants.SD_NO_CONTEXT_WHEN_NOT_EXTENSION, type) && ok; @@ -545,10 +555,11 @@ public class StructureDefinitionValidator extends BaseValidator { types.add(elements.get(0).getNamedChildValue("path")); } List warnings = new ArrayList<>(); + ValidationContext vc = new ValidationContext(invariant); if (Utilities.existsInList(rootPath, context.getResourceNames())) { - fpe.checkOnTypes(invariant, rootPath, types, fpe.parse(exp), warnings); + fpe.checkOnTypes(vc, rootPath, types, fpe.parse(exp), warnings); } else { - fpe.checkOnTypes(invariant, "DomainResource", types, fpe.parse(exp), warnings); + fpe.checkOnTypes(vc, "DomainResource", types, fpe.parse(exp), warnings); } for (String s : warnings) { warning(errors, "2023-07-27", IssueType.BUSINESSRULE, stack, false, key+": "+s); @@ -571,6 +582,61 @@ public class StructureDefinitionValidator extends BaseValidator { return ok; } + private boolean validateContextInvariant(List errors, Element invariant, Element sd, NodeStack stack) { + boolean ok = true; + String expression = invariant.getValue(); + if (!Utilities.noString(expression)) { + // we have to figure out the context, and we might be in type slicing. + String exp = expression; + List types = listTypeContexts(sd); + if (types.size() == 0) { + hint(errors, "2023-10-31", IssueType.INFORMATIONAL, stack, false, I18nConstants.UNABLE_TO_DETERMINE_TYPE_CONTEXT_INV, listContexts(sd)); + } else + try { + List warnings = new ArrayList<>(); + ValidationContext vc = new ValidationContext(invariant); + fpe.checkOnTypes(vc, "DomainResource", types, fpe.parse(exp), warnings); + for (String s : warnings) { + warning(errors, "2023-07-27", IssueType.BUSINESSRULE, stack, false, s); + } + } catch (Exception e) { + if (debug) { + e.printStackTrace(); + } + ok = rule(errors, "2023-06-19", IssueType.INVALID, stack, false, I18nConstants.ED_CONTEXT_INVARIANT_EXPRESSION_ERROR, expression, e.getMessage()) && ok; + } + } + return ok; + } + + private Object listContexts(Element sd) { + CommaSeparatedStringBuilder b = new CommaSeparatedStringBuilder(); + for (Element e : sd.getChildren("context")) { + b.append(e.getNamedChildValue("type")+"="+e.getNamedChildValue("expression")); + } + return b.toString(); + } + + private List listTypeContexts(Element sd) { + List types = new ArrayList<>(); + for (Element e : sd.getChildren("context")) { + switch (e.getNamedChildValue("type")) { + case "fhirpath" : + break; + case "element" : + types.add(e.getNamedChildValue("expression")); + break; + case "extension" : + // this isn't defined? + types.add(e.getNamedChildValue("Extension")); + types.add(e.getNamedChildValue("Extension.value")); + break; + default: + } + } + return types; + } + private boolean haseHasInvariant(StructureDefinition base, String key) { for (ElementDefinition ed : base.getSnapshot().getElement()) { for (ElementDefinitionConstraintComponent inv : ed.getConstraint()) { From 1e066b7d145cdffa72607751f511fe182fe27a23 Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Tue, 31 Oct 2023 21:05:46 +1100 Subject: [PATCH 17/22] release notes --- RELEASE_NOTES.md | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 7b06c6ab5..e46e4ddb8 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,7 +1,22 @@ ## Validator Changes -* no changes +* Validate contextInvariant in extension definitions +* fix Typo in TI WG name +* Handle unknown constants properly in FHIRPath +* Fix handling of type ancestors at the root of FHIRPath expressions +* CDA templates with no extension value use urn:oid: not urn:hl7ii: +* Allow URL as a type of string in FHIRPath type checking +* Fix semver validation +* Fix problem resolving context in CDA invariants ## Other code changes -* no changes \ No newline at end of file +* Finish SQL in FHIR Implementation, but disable sql on fhir tests until package is packaged properly by next release of IG publisher +* Fixes to Search Parameter rendering per FHIR-I decision +* Fix broken links in extension references done by [[[]]] +* Fix broken links in code system rendering of parents +* Support using names in [[[markdown]]] when rendering +* Remove "profile" from tx operations +* Include checkIPSCodes and bundleValidationRules in json + + From 7386b2b8f8783b74e7b2c493a2d5a2784ebecada Mon Sep 17 00:00:00 2001 From: dotasek Date: Tue, 31 Oct 2023 09:49:37 -0400 Subject: [PATCH 18/22] Include checkIPSCodes and bundleValidationRules in json (#1473) + gentle renaming --- .../validation/BundleValidationRule.java | 25 ++++++++++++++----- .../fhir/validation/cli/model/CliContext.java | 18 ++++++++++--- .../hl7/fhir/validation/cli/utils/Params.java | 14 +++++------ .../validation/tests/ValidationTests.java | 2 +- 4 files changed, 41 insertions(+), 18 deletions(-) diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/validation/BundleValidationRule.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/validation/BundleValidationRule.java index 370f67c4c..5c44c48f1 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/validation/BundleValidationRule.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/validation/BundleValidationRule.java @@ -1,24 +1,37 @@ package org.hl7.fhir.r5.utils.validation; +import com.fasterxml.jackson.annotation.JsonProperty; + public class BundleValidationRule { + @JsonProperty("rule") private String rule; + + @JsonProperty("profile") private String profile; private boolean checked; - public BundleValidationRule(String rule, String profile) { - super(); - this.rule = rule; - this.profile = profile; - } - + @JsonProperty("rule") public String getRule() { return rule; } + @JsonProperty("rule") + public BundleValidationRule setRule(String rule) { + this.rule = rule; + return this; + } + + @JsonProperty("profile") public String getProfile() { return profile; } + @JsonProperty("profile") + public BundleValidationRule setProfile(String profile) { + this.profile = profile; + return this; + } + public boolean isChecked() { return checked; } diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/model/CliContext.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/model/CliContext.java index 037bf6d38..445e8a59b 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/model/CliContext.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/model/CliContext.java @@ -131,8 +131,8 @@ public class CliContext { @JsonProperty("outputStyle") private String outputStyle = null; - - // TODO: Mark what goes here? + + @JsonProperty("bundleValidationRules") private List bundleValidationRules = new ArrayList<>(); @JsonProperty("jurisdiction") @@ -191,11 +191,17 @@ public class CliContext { return this; } - // TODO: Mark what goes here? + @JsonProperty("bundleValidationRules") public List getBundleValidationRules() { return bundleValidationRules; } + @JsonProperty("bundleValidationRules") + public CliContext setBundleValidationRules(List bundleValidationRules) { + this.bundleValidationRules = bundleValidationRules; + return this; + } + public CliContext addIg(String ig) { if (this.igs == null) { this.igs = new ArrayList<>(); @@ -322,14 +328,18 @@ public class CliContext { this.allowDoubleQuotesInFHIRPath = allowDoubleQuotesInFHIRPath; } + @JsonProperty("checkIPSCodes") public boolean isCheckIPSCodes() { return checkIPSCodes; } - public void setCheckIPSCodes(boolean checkIPSCodes) { + @JsonProperty("checkIPSCodes") + public CliContext setCheckIPSCodes(boolean checkIPSCodes) { this.checkIPSCodes = checkIPSCodes; + return this; } + @JsonProperty("locale") public String getLanguageCode() { return locale; diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/utils/Params.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/utils/Params.java index 1d92339bb..29983d61e 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/utils/Params.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/utils/Params.java @@ -181,25 +181,25 @@ public class Params { cliContext.addProfile(p); } } else if (args[i].equals(BUNDLE)) { - String p = null; - String r = null; + String profile = null; + String rule = null; if (i + 1 == args.length) { throw new Error("Specified -profile without indicating bundle rule "); } else { - r = args[++i]; + rule = args[++i]; } if (i + 1 == args.length) { throw new Error("Specified -profile without indicating profile source"); } else { - p = args[++i]; + profile = args[++i]; } - cliContext.getBundleValidationRules().add(new BundleValidationRule(r, p)); + cliContext.getBundleValidationRules().add(new BundleValidationRule().setRule(rule).setProfile(profile)); } else if (args[i].equals(QUESTIONNAIRE)) { if (i + 1 == args.length) throw new Error("Specified -questionnaire without indicating questionnaire mode"); else { - String q = args[++i]; - cliContext.setQuestionnaireMode(QuestionnaireMode.fromCode(q)); + String questionnaireMode = args[++i]; + cliContext.setQuestionnaireMode(QuestionnaireMode.fromCode(questionnaireMode)); } } else if (args[i].equals(LEVEL)) { if (i + 1 == args.length) diff --git a/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/validation/tests/ValidationTests.java b/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/validation/tests/ValidationTests.java index 55e5ec2fb..d4d2d83ad 100644 --- a/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/validation/tests/ValidationTests.java +++ b/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/validation/tests/ValidationTests.java @@ -287,7 +287,7 @@ public class ValidationTests implements IEvaluationContext, IValidatorResourceFe } val.getBundleValidationRules().clear(); if (content.has("bundle-param")) { - val.getBundleValidationRules().add(new BundleValidationRule(content.getAsJsonObject("bundle-param").get("rule").getAsString(), content.getAsJsonObject("bundle-param").get("profile").getAsString())); + val.getBundleValidationRules().add(new BundleValidationRule().setRule(content.getAsJsonObject("bundle-param").get("rule").getAsString()).setProfile( content.getAsJsonObject("bundle-param").get("profile").getAsString())); } if (content.has("profiles")) { for (JsonElement je : content.getAsJsonArray("profiles")) { From 6fb5b11619611b37a1ca26f63c69d7d003dc3da5 Mon Sep 17 00:00:00 2001 From: dotasek Date: Tue, 31 Oct 2023 10:55:39 -0400 Subject: [PATCH 19/22] Bump test cases to 1.4.14 ***NO_CI*** --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 92fd2100c..e5fee398b 100644 --- a/pom.xml +++ b/pom.xml @@ -20,7 +20,7 @@ 32.0.1-jre 6.4.1 - 1.4.14-SNAPSHOT + 1.4.14 2.15.2 5.9.2 1.8.2 From 3c198658e133d059a2574668442c1b9bd2191d44 Mon Sep 17 00:00:00 2001 From: markiantorno Date: Tue, 31 Oct 2023 15:51:40 +0000 Subject: [PATCH 20/22] Release: v6.2.1 ## Validator Changes * Validate contextInvariant in extension definitions * fix Typo in TI WG name * Handle unknown constants properly in FHIRPath * Fix handling of type ancestors at the root of FHIRPath expressions * CDA templates with no extension value use urn:oid: not urn:hl7ii: * Allow URL as a type of string in FHIRPath type checking * Fix semver validation * Fix problem resolving context in CDA invariants ## Other code changes * Finish SQL in FHIR Implementation, but disable sql on fhir tests until package is packaged properly by next release of IG publisher * Fixes to Search Parameter rendering per FHIR-I decision * Fix broken links in extension references done by [[[]]] * Fix broken links in code system rendering of parents * Support using names in [[[markdown]]] when rendering * Remove "profile" from tx operations * Include checkIPSCodes and bundleValidationRules in json ***NO_CI*** --- org.hl7.fhir.convertors/pom.xml | 2 +- org.hl7.fhir.dstu2/pom.xml | 2 +- org.hl7.fhir.dstu2016may/pom.xml | 2 +- org.hl7.fhir.dstu3/pom.xml | 2 +- org.hl7.fhir.r4/pom.xml | 2 +- org.hl7.fhir.r4b/pom.xml | 2 +- org.hl7.fhir.r5/pom.xml | 2 +- org.hl7.fhir.report/pom.xml | 2 +- org.hl7.fhir.utilities/pom.xml | 2 +- org.hl7.fhir.validation.cli/pom.xml | 2 +- org.hl7.fhir.validation/pom.xml | 2 +- pom.xml | 2 +- 12 files changed, 12 insertions(+), 12 deletions(-) diff --git a/org.hl7.fhir.convertors/pom.xml b/org.hl7.fhir.convertors/pom.xml index 40e30044d..3d9c4ba14 100644 --- a/org.hl7.fhir.convertors/pom.xml +++ b/org.hl7.fhir.convertors/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 6.2.1-SNAPSHOT + 6.2.1 ../pom.xml diff --git a/org.hl7.fhir.dstu2/pom.xml b/org.hl7.fhir.dstu2/pom.xml index 271855a0f..b351f1493 100644 --- a/org.hl7.fhir.dstu2/pom.xml +++ b/org.hl7.fhir.dstu2/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 6.2.1-SNAPSHOT + 6.2.1 ../pom.xml diff --git a/org.hl7.fhir.dstu2016may/pom.xml b/org.hl7.fhir.dstu2016may/pom.xml index df2f2b4a3..c9cf8b8b5 100644 --- a/org.hl7.fhir.dstu2016may/pom.xml +++ b/org.hl7.fhir.dstu2016may/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 6.2.1-SNAPSHOT + 6.2.1 ../pom.xml diff --git a/org.hl7.fhir.dstu3/pom.xml b/org.hl7.fhir.dstu3/pom.xml index 8d3097564..6b2866442 100644 --- a/org.hl7.fhir.dstu3/pom.xml +++ b/org.hl7.fhir.dstu3/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 6.2.1-SNAPSHOT + 6.2.1 ../pom.xml diff --git a/org.hl7.fhir.r4/pom.xml b/org.hl7.fhir.r4/pom.xml index 4117d416a..85e93e347 100644 --- a/org.hl7.fhir.r4/pom.xml +++ b/org.hl7.fhir.r4/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 6.2.1-SNAPSHOT + 6.2.1 ../pom.xml diff --git a/org.hl7.fhir.r4b/pom.xml b/org.hl7.fhir.r4b/pom.xml index 25ea7f3ae..0da73c65b 100644 --- a/org.hl7.fhir.r4b/pom.xml +++ b/org.hl7.fhir.r4b/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 6.2.1-SNAPSHOT + 6.2.1 ../pom.xml diff --git a/org.hl7.fhir.r5/pom.xml b/org.hl7.fhir.r5/pom.xml index 7279e9dad..b6e677809 100644 --- a/org.hl7.fhir.r5/pom.xml +++ b/org.hl7.fhir.r5/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 6.2.1-SNAPSHOT + 6.2.1 ../pom.xml diff --git a/org.hl7.fhir.report/pom.xml b/org.hl7.fhir.report/pom.xml index 713f9a2fe..c39b2bdae 100644 --- a/org.hl7.fhir.report/pom.xml +++ b/org.hl7.fhir.report/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 6.2.1-SNAPSHOT + 6.2.1 ../pom.xml diff --git a/org.hl7.fhir.utilities/pom.xml b/org.hl7.fhir.utilities/pom.xml index 78fe43557..87871f5ce 100644 --- a/org.hl7.fhir.utilities/pom.xml +++ b/org.hl7.fhir.utilities/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 6.2.1-SNAPSHOT + 6.2.1 ../pom.xml diff --git a/org.hl7.fhir.validation.cli/pom.xml b/org.hl7.fhir.validation.cli/pom.xml index 131164d70..db0604130 100644 --- a/org.hl7.fhir.validation.cli/pom.xml +++ b/org.hl7.fhir.validation.cli/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 6.2.1-SNAPSHOT + 6.2.1 ../pom.xml diff --git a/org.hl7.fhir.validation/pom.xml b/org.hl7.fhir.validation/pom.xml index ca9484eec..d5351a004 100644 --- a/org.hl7.fhir.validation/pom.xml +++ b/org.hl7.fhir.validation/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 6.2.1-SNAPSHOT + 6.2.1 ../pom.xml diff --git a/pom.xml b/pom.xml index e5fee398b..83f0c3bf3 100644 --- a/pom.xml +++ b/pom.xml @@ -14,7 +14,7 @@ HAPI FHIR --> org.hl7.fhir.core - 6.2.1-SNAPSHOT + 6.2.1 pom From a47dccc7f648bcefdd3d412adf5e471a75897f62 Mon Sep 17 00:00:00 2001 From: markiantorno Date: Tue, 31 Oct 2023 16:23:32 +0000 Subject: [PATCH 21/22] Updating version to: 6.2.2-SNAPSHOT and incrementing test cases dependency. --- RELEASE_NOTES.md | 19 ++----------------- org.hl7.fhir.convertors/pom.xml | 2 +- org.hl7.fhir.dstu2/pom.xml | 2 +- org.hl7.fhir.dstu2016may/pom.xml | 2 +- org.hl7.fhir.dstu3/pom.xml | 2 +- org.hl7.fhir.r4/pom.xml | 2 +- org.hl7.fhir.r4b/pom.xml | 2 +- org.hl7.fhir.r5/pom.xml | 2 +- org.hl7.fhir.report/pom.xml | 2 +- org.hl7.fhir.utilities/pom.xml | 2 +- org.hl7.fhir.validation.cli/pom.xml | 2 +- org.hl7.fhir.validation/pom.xml | 2 +- pom.xml | 2 +- 13 files changed, 14 insertions(+), 29 deletions(-) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index e46e4ddb8..7b06c6ab5 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,22 +1,7 @@ ## Validator Changes -* Validate contextInvariant in extension definitions -* fix Typo in TI WG name -* Handle unknown constants properly in FHIRPath -* Fix handling of type ancestors at the root of FHIRPath expressions -* CDA templates with no extension value use urn:oid: not urn:hl7ii: -* Allow URL as a type of string in FHIRPath type checking -* Fix semver validation -* Fix problem resolving context in CDA invariants +* no changes ## Other code changes -* Finish SQL in FHIR Implementation, but disable sql on fhir tests until package is packaged properly by next release of IG publisher -* Fixes to Search Parameter rendering per FHIR-I decision -* Fix broken links in extension references done by [[[]]] -* Fix broken links in code system rendering of parents -* Support using names in [[[markdown]]] when rendering -* Remove "profile" from tx operations -* Include checkIPSCodes and bundleValidationRules in json - - +* no changes \ No newline at end of file diff --git a/org.hl7.fhir.convertors/pom.xml b/org.hl7.fhir.convertors/pom.xml index 3d9c4ba14..4603813da 100644 --- a/org.hl7.fhir.convertors/pom.xml +++ b/org.hl7.fhir.convertors/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 6.2.1 + 6.2.2-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.dstu2/pom.xml b/org.hl7.fhir.dstu2/pom.xml index b351f1493..dce98caac 100644 --- a/org.hl7.fhir.dstu2/pom.xml +++ b/org.hl7.fhir.dstu2/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 6.2.1 + 6.2.2-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.dstu2016may/pom.xml b/org.hl7.fhir.dstu2016may/pom.xml index c9cf8b8b5..e44ea9169 100644 --- a/org.hl7.fhir.dstu2016may/pom.xml +++ b/org.hl7.fhir.dstu2016may/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 6.2.1 + 6.2.2-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.dstu3/pom.xml b/org.hl7.fhir.dstu3/pom.xml index 6b2866442..62734b0cf 100644 --- a/org.hl7.fhir.dstu3/pom.xml +++ b/org.hl7.fhir.dstu3/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 6.2.1 + 6.2.2-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.r4/pom.xml b/org.hl7.fhir.r4/pom.xml index 85e93e347..a5007ea6d 100644 --- a/org.hl7.fhir.r4/pom.xml +++ b/org.hl7.fhir.r4/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 6.2.1 + 6.2.2-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.r4b/pom.xml b/org.hl7.fhir.r4b/pom.xml index 0da73c65b..da832d185 100644 --- a/org.hl7.fhir.r4b/pom.xml +++ b/org.hl7.fhir.r4b/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 6.2.1 + 6.2.2-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.r5/pom.xml b/org.hl7.fhir.r5/pom.xml index b6e677809..592395f81 100644 --- a/org.hl7.fhir.r5/pom.xml +++ b/org.hl7.fhir.r5/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 6.2.1 + 6.2.2-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.report/pom.xml b/org.hl7.fhir.report/pom.xml index c39b2bdae..165c6681f 100644 --- a/org.hl7.fhir.report/pom.xml +++ b/org.hl7.fhir.report/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 6.2.1 + 6.2.2-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.utilities/pom.xml b/org.hl7.fhir.utilities/pom.xml index 87871f5ce..1656e6669 100644 --- a/org.hl7.fhir.utilities/pom.xml +++ b/org.hl7.fhir.utilities/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 6.2.1 + 6.2.2-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.validation.cli/pom.xml b/org.hl7.fhir.validation.cli/pom.xml index db0604130..96824b4af 100644 --- a/org.hl7.fhir.validation.cli/pom.xml +++ b/org.hl7.fhir.validation.cli/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 6.2.1 + 6.2.2-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.validation/pom.xml b/org.hl7.fhir.validation/pom.xml index d5351a004..b40e9eef1 100644 --- a/org.hl7.fhir.validation/pom.xml +++ b/org.hl7.fhir.validation/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 6.2.1 + 6.2.2-SNAPSHOT ../pom.xml diff --git a/pom.xml b/pom.xml index 83f0c3bf3..fb5b99691 100644 --- a/pom.xml +++ b/pom.xml @@ -14,7 +14,7 @@ HAPI FHIR --> org.hl7.fhir.core - 6.2.1 + 6.2.2-SNAPSHOT pom From 35504dc460a3f76731ca0e3cd666e2a32bff9965 Mon Sep 17 00:00:00 2001 From: dotasek Date: Wed, 1 Nov 2023 09:37:41 -0400 Subject: [PATCH 22/22] Use https for primary packages server (#1476) * Use https for primary packages server * Fix okToUsePackageServer --- .../org/hl7/fhir/utilities/npm/BasePackageCacheManager.java | 2 +- .../src/main/java/org/hl7/fhir/utilities/npm/PackageServer.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/npm/BasePackageCacheManager.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/npm/BasePackageCacheManager.java index 5afafcf2d..659e478db 100644 --- a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/npm/BasePackageCacheManager.java +++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/npm/BasePackageCacheManager.java @@ -95,7 +95,7 @@ public abstract class BasePackageCacheManager implements IPackageCacheManager { // this is not a long term thing, but it's not clear how to release patches for // 1.4.0 private boolean okToUsePackageServer(String server, String id) { - if ("http://packages.fhir.org".equals(server) && "hl7.fhir.r2b.core".equals(id)) { + if (PackageServer.PRIMARY_SERVER.equals(server) && "hl7.fhir.r2b.core".equals(id)) { return false; } return true; diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/npm/PackageServer.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/npm/PackageServer.java index 6afd7df89..22b1143c4 100644 --- a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/npm/PackageServer.java +++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/npm/PackageServer.java @@ -46,7 +46,7 @@ public class PackageServer { return url; } - public static final String PRIMARY_SERVER = "http://packages.fhir.org"; + public static final String PRIMARY_SERVER = "https://packages.fhir.org"; public static final String SECONDARY_SERVER = "https://packages2.fhir.org/packages"; public static PackageServer primaryServer() {