From f7a495685ba2b7ca75696af4bfa647241d44f70e Mon Sep 17 00:00:00 2001 From: dotasek Date: Thu, 6 Jun 2024 16:21:14 -0400 Subject: [PATCH 01/50] Fix case typo in Consent.ProvisionComponent --- .../resources30_40/Consent30_40.java | 13 +- .../resources40_50/Consent40_50.java | 9 +- .../org/hl7/fhir/r4/formats/RdfParser.java | 2 +- .../org/hl7/fhir/r4/formats/XmlParser.java | 12 +- .../java/org/hl7/fhir/r4/model/Consent.java | 140 +++++++++--------- 5 files changed, 89 insertions(+), 87 deletions(-) diff --git a/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/conv30_40/resources30_40/Consent30_40.java b/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/conv30_40/resources30_40/Consent30_40.java index 1c783f74c..eaf5aba5a 100644 --- a/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/conv30_40/resources30_40/Consent30_40.java +++ b/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/conv30_40/resources30_40/Consent30_40.java @@ -13,6 +13,7 @@ import org.hl7.fhir.convertors.conv30_40.datatypes30_40.primitivetypes30_40.Date import org.hl7.fhir.convertors.conv30_40.datatypes30_40.primitivetypes30_40.Uri30_40; import org.hl7.fhir.exceptions.FHIRException; import org.hl7.fhir.r4.model.CodeableConcept; +import org.hl7.fhir.r4.model.Consent; import org.hl7.fhir.r4.model.Identifier; public class Consent30_40 { @@ -47,7 +48,7 @@ public class Consent30_40 { tgt.setPolicyRule(new CodeableConcept(c)); } if (src.hasSecurityLabel() || src.hasPeriod() || src.hasActor() || src.hasAction() || src.hasPurpose() || src.hasDataPeriod() || src.hasData() || src.hasExcept()) { - org.hl7.fhir.r4.model.Consent.provisionComponent pc = new org.hl7.fhir.r4.model.Consent.provisionComponent(); + Consent.ProvisionComponent pc = new Consent.ProvisionComponent(); if (src.hasPeriod()) pc.setPeriod(Period30_40.convertPeriod(src.getPeriod())); for (org.hl7.fhir.dstu3.model.Consent.ConsentActorComponent t : src.getActor()) @@ -104,7 +105,7 @@ public class Consent30_40 { } } if (src.hasProvision()) { - org.hl7.fhir.r4.model.Consent.provisionComponent p = src.getProvision(); + Consent.ProvisionComponent p = src.getProvision(); if (p.hasPeriod()) tgt.setPeriod(Period30_40.convertPeriod(p.getPeriod())); for (org.hl7.fhir.r4.model.Consent.provisionActorComponent t : p.getActor()) @@ -117,7 +118,7 @@ public class Consent30_40 { tgt.setDataPeriod(Period30_40.convertPeriod(p.getDataPeriod())); for (org.hl7.fhir.r4.model.Consent.provisionDataComponent t : p.getData()) tgt.addData(convertConsentDataComponent(t)); - for (org.hl7.fhir.r4.model.Consent.provisionComponent t : p.getProvision()) + for (Consent.ProvisionComponent t : p.getProvision()) tgt.addExcept(convertExceptComponent(t)); } return tgt; @@ -369,7 +370,7 @@ public class Consent30_40 { return tgt; } - static public org.hl7.fhir.dstu3.model.Consent.ExceptComponent convertExceptComponent(org.hl7.fhir.r4.model.Consent.provisionComponent src) throws FHIRException { + static public org.hl7.fhir.dstu3.model.Consent.ExceptComponent convertExceptComponent(Consent.ProvisionComponent src) throws FHIRException { if (src == null) return null; org.hl7.fhir.dstu3.model.Consent.ExceptComponent tgt = new org.hl7.fhir.dstu3.model.Consent.ExceptComponent(); @@ -393,10 +394,10 @@ public class Consent30_40 { return tgt; } - static public org.hl7.fhir.r4.model.Consent.provisionComponent convertExceptComponent(org.hl7.fhir.dstu3.model.Consent.ExceptComponent src) throws FHIRException { + static public Consent.ProvisionComponent convertExceptComponent(org.hl7.fhir.dstu3.model.Consent.ExceptComponent src) throws FHIRException { if (src == null) return null; - org.hl7.fhir.r4.model.Consent.provisionComponent tgt = new org.hl7.fhir.r4.model.Consent.provisionComponent(); + Consent.ProvisionComponent tgt = new Consent.ProvisionComponent(); ConversionContext30_40.INSTANCE.getVersionConvertor_30_40().copyBackboneElement(src,tgt); if (src.hasType()) tgt.setTypeElement(convertConsentExceptType(src.getTypeElement())); diff --git a/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/conv40_50/resources40_50/Consent40_50.java b/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/conv40_50/resources40_50/Consent40_50.java index 0fe389de5..d5fa94f0f 100644 --- a/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/conv40_50/resources40_50/Consent40_50.java +++ b/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/conv40_50/resources40_50/Consent40_50.java @@ -10,6 +10,7 @@ import org.hl7.fhir.convertors.conv40_50.datatypes40_50.primitive40_50.Boolean40 import org.hl7.fhir.convertors.conv40_50.datatypes40_50.primitive40_50.DateTime40_50; import org.hl7.fhir.convertors.conv40_50.datatypes40_50.special40_50.Reference40_50; import org.hl7.fhir.exceptions.FHIRException; +import org.hl7.fhir.r4.model.Consent; /* Copyright (c) 2011+, HL7, Inc. @@ -220,7 +221,7 @@ public class Consent40_50 { return tgt; } - public static org.hl7.fhir.r5.model.Consent.ProvisionComponent convertprovisionComponent(org.hl7.fhir.r4.model.Consent.provisionComponent src) throws FHIRException { + public static org.hl7.fhir.r5.model.Consent.ProvisionComponent convertprovisionComponent(Consent.ProvisionComponent src) throws FHIRException { if (src == null) return null; org.hl7.fhir.r5.model.Consent.ProvisionComponent tgt = new org.hl7.fhir.r5.model.Consent.ProvisionComponent(); @@ -242,15 +243,15 @@ public class Consent40_50 { tgt.setDataPeriod(Period40_50.convertPeriod(src.getDataPeriod())); for (org.hl7.fhir.r4.model.Consent.provisionDataComponent t : src.getData()) tgt.addData(convertprovisionDataComponent(t)); - for (org.hl7.fhir.r4.model.Consent.provisionComponent t : src.getProvision()) + for (Consent.ProvisionComponent t : src.getProvision()) tgt.addProvision(convertprovisionComponent(t)); return tgt; } - public static org.hl7.fhir.r4.model.Consent.provisionComponent convertprovisionComponent(org.hl7.fhir.r5.model.Consent.ProvisionComponent src) throws FHIRException { + public static Consent.ProvisionComponent convertprovisionComponent(org.hl7.fhir.r5.model.Consent.ProvisionComponent src) throws FHIRException { if (src == null) return null; - org.hl7.fhir.r4.model.Consent.provisionComponent tgt = new org.hl7.fhir.r4.model.Consent.provisionComponent(); + Consent.ProvisionComponent tgt = new Consent.ProvisionComponent(); ConversionContext40_50.INSTANCE.getVersionConvertor_40_50().copyBackboneElement(src, tgt); // if (src.hasType()) // tgt.setTypeElement(convertConsentProvisionType(src.getTypeElement())); diff --git a/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/formats/RdfParser.java b/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/formats/RdfParser.java index e09127adc..ee7a21d82 100644 --- a/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/formats/RdfParser.java +++ b/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/formats/RdfParser.java @@ -4917,7 +4917,7 @@ public class RdfParser extends RdfParserBase { } protected void composeConsentprovisionComponent(Complex parent, String parentType, String name, - Consent.provisionComponent element, int index) { + Consent.ProvisionComponent element, int index) { if (element == null) return; Complex t; diff --git a/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/formats/XmlParser.java b/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/formats/XmlParser.java index 7ccf6fdd6..6c46487ea 100644 --- a/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/formats/XmlParser.java +++ b/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/formats/XmlParser.java @@ -6924,9 +6924,9 @@ public class XmlParser extends XmlParserBase { return true; } - protected Consent.provisionComponent parseConsentprovisionComponent(XmlPullParser xpp, Consent owner) + protected Consent.ProvisionComponent parseConsentprovisionComponent(XmlPullParser xpp, Consent owner) throws XmlPullParserException, IOException, FHIRFormatError { - Consent.provisionComponent res = new Consent.provisionComponent(); + Consent.ProvisionComponent res = new Consent.ProvisionComponent(); parseBackboneAttributes(xpp, res); next(xpp); int eventType = nextNoWhitespace(xpp); @@ -6941,7 +6941,7 @@ public class XmlParser extends XmlParserBase { } protected boolean parseConsentprovisionComponentContent(int eventType, XmlPullParser xpp, Consent owner, - Consent.provisionComponent res) throws XmlPullParserException, IOException, FHIRFormatError { + Consent.ProvisionComponent res) throws XmlPullParserException, IOException, FHIRFormatError { if (eventType == XmlPullParser.START_TAG && xpp.getName().equals("type")) { res.setTypeElement( parseEnumeration(xpp, Consent.ConsentProvisionType.NULL, new Consent.ConsentProvisionTypeEnumFactory())); @@ -34008,7 +34008,7 @@ public class XmlParser extends XmlParserBase { } } - protected void composeConsentprovisionComponent(String name, Consent.provisionComponent element) throws IOException { + protected void composeConsentprovisionComponent(String name, Consent.ProvisionComponent element) throws IOException { if (element != null) { composeElementAttributes(element); xml.enter(FHIR_NS, name); @@ -34018,7 +34018,7 @@ public class XmlParser extends XmlParserBase { } } - protected void composeConsentprovisionComponentElements(Consent.provisionComponent element) throws IOException { + protected void composeConsentprovisionComponentElements(Consent.ProvisionComponent element) throws IOException { composeBackboneElementElements(element); if (element.hasTypeElement()) composeEnumeration("type", element.getTypeElement(), new Consent.ConsentProvisionTypeEnumFactory()); @@ -34057,7 +34057,7 @@ public class XmlParser extends XmlParserBase { composeConsentprovisionDataComponent("data", e); } if (element.hasProvision()) { - for (Consent.provisionComponent e : element.getProvision()) + for (Consent.ProvisionComponent e : element.getProvision()) composeConsentprovisionComponent("provision", e); } } diff --git a/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/model/Consent.java b/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/model/Consent.java index c2abe1adf..8ddec6144 100644 --- a/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/model/Consent.java +++ b/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/model/Consent.java @@ -750,9 +750,9 @@ public class Consent extends DomainResource { } else return super.setProperty(name, value); return value; - } - - @Override + } + + @Override public void removeChild(String name, Base value) throws FHIRException { if (name.equals("authority")) { this.authority = null; @@ -1111,9 +1111,9 @@ public class Consent extends DomainResource { } else return super.setProperty(name, value); return value; - } - - @Override + } + + @Override public void removeChild(String name, Base value) throws FHIRException { if (name.equals("verified")) { this.verified = null; @@ -1215,7 +1215,7 @@ public class Consent extends DomainResource { } @Block() - public static class provisionComponent extends BackboneElement implements IBaseBackboneElement { + public static class ProvisionComponent extends BackboneElement implements IBaseBackboneElement { /** * Action to take - permit or deny - when the rule conditions are met. Not * permitted in root rule, required in all nested rules. @@ -1308,16 +1308,16 @@ public class Consent extends DomainResource { * Rules which provide exceptions to the base rule or subrules. */ @Child(name = "provision", type = { - provisionComponent.class }, order = 11, min = 0, max = Child.MAX_UNLIMITED, modifier = false, summary = false) + ProvisionComponent.class }, order = 11, min = 0, max = Child.MAX_UNLIMITED, modifier = false, summary = false) @Description(shortDefinition = "Nested Exception Rules", formalDefinition = "Rules which provide exceptions to the base rule or subrules.") - protected List provision; + protected List provision; private static final long serialVersionUID = -1280172451L; /** * Constructor */ - public provisionComponent() { + public ProvisionComponent() { super(); } @@ -1351,7 +1351,7 @@ public class Consent extends DomainResource { * extensions. The accessor "getType" gives direct access to the * value */ - public provisionComponent setTypeElement(Enumeration value) { + public ProvisionComponent setTypeElement(Enumeration value) { this.type = value; return this; } @@ -1368,7 +1368,7 @@ public class Consent extends DomainResource { * @param value Action to take - permit or deny - when the rule conditions are * met. Not permitted in root rule, required in all nested rules. */ - public provisionComponent setType(ConsentProvisionType value) { + public ProvisionComponent setType(ConsentProvisionType value) { if (value == null) this.type = null; else { @@ -1398,7 +1398,7 @@ public class Consent extends DomainResource { /** * @param value {@link #period} (The timeframe in this rule is valid.) */ - public provisionComponent setPeriod(Period value) { + public ProvisionComponent setPeriod(Period value) { this.period = value; return this; } @@ -1417,7 +1417,7 @@ public class Consent extends DomainResource { /** * @return Returns a reference to this for easy method chaining */ - public provisionComponent setActor(List theActor) { + public ProvisionComponent setActor(List theActor) { this.actor = theActor; return this; } @@ -1439,7 +1439,7 @@ public class Consent extends DomainResource { return t; } - public provisionComponent addActor(provisionActorComponent t) { // 3 + public ProvisionComponent addActor(provisionActorComponent t) { // 3 if (t == null) return this; if (this.actor == null) @@ -1471,7 +1471,7 @@ public class Consent extends DomainResource { /** * @return Returns a reference to this for easy method chaining */ - public provisionComponent setAction(List theAction) { + public ProvisionComponent setAction(List theAction) { this.action = theAction; return this; } @@ -1493,7 +1493,7 @@ public class Consent extends DomainResource { return t; } - public provisionComponent addAction(CodeableConcept t) { // 3 + public ProvisionComponent addAction(CodeableConcept t) { // 3 if (t == null) return this; if (this.action == null) @@ -1527,7 +1527,7 @@ public class Consent extends DomainResource { /** * @return Returns a reference to this for easy method chaining */ - public provisionComponent setSecurityLabel(List theSecurityLabel) { + public ProvisionComponent setSecurityLabel(List theSecurityLabel) { this.securityLabel = theSecurityLabel; return this; } @@ -1549,7 +1549,7 @@ public class Consent extends DomainResource { return t; } - public provisionComponent addSecurityLabel(Coding t) { // 3 + public ProvisionComponent addSecurityLabel(Coding t) { // 3 if (t == null) return this; if (this.securityLabel == null) @@ -1583,7 +1583,7 @@ public class Consent extends DomainResource { /** * @return Returns a reference to this for easy method chaining */ - public provisionComponent setPurpose(List thePurpose) { + public ProvisionComponent setPurpose(List thePurpose) { this.purpose = thePurpose; return this; } @@ -1605,7 +1605,7 @@ public class Consent extends DomainResource { return t; } - public provisionComponent addPurpose(Coding t) { // 3 + public ProvisionComponent addPurpose(Coding t) { // 3 if (t == null) return this; if (this.purpose == null) @@ -1640,7 +1640,7 @@ public class Consent extends DomainResource { /** * @return Returns a reference to this for easy method chaining */ - public provisionComponent setClass_(List theClass_) { + public ProvisionComponent setClass_(List theClass_) { this.class_ = theClass_; return this; } @@ -1662,7 +1662,7 @@ public class Consent extends DomainResource { return t; } - public provisionComponent addClass_(Coding t) { // 3 + public ProvisionComponent addClass_(Coding t) { // 3 if (t == null) return this; if (this.class_ == null) @@ -1695,7 +1695,7 @@ public class Consent extends DomainResource { /** * @return Returns a reference to this for easy method chaining */ - public provisionComponent setCode(List theCode) { + public ProvisionComponent setCode(List theCode) { this.code = theCode; return this; } @@ -1717,7 +1717,7 @@ public class Consent extends DomainResource { return t; } - public provisionComponent addCode(CodeableConcept t) { // 3 + public ProvisionComponent addCode(CodeableConcept t) { // 3 if (t == null) return this; if (this.code == null) @@ -1758,7 +1758,7 @@ public class Consent extends DomainResource { * @param value {@link #dataPeriod} (Clinical or Operational Relevant period of * time that bounds the data controlled by this rule.) */ - public provisionComponent setDataPeriod(Period value) { + public ProvisionComponent setDataPeriod(Period value) { this.dataPeriod = value; return this; } @@ -1776,7 +1776,7 @@ public class Consent extends DomainResource { /** * @return Returns a reference to this for easy method chaining */ - public provisionComponent setData(List theData) { + public ProvisionComponent setData(List theData) { this.data = theData; return this; } @@ -1798,7 +1798,7 @@ public class Consent extends DomainResource { return t; } - public provisionComponent addData(provisionDataComponent t) { // 3 + public ProvisionComponent addData(provisionDataComponent t) { // 3 if (t == null) return this; if (this.data == null) @@ -1822,16 +1822,16 @@ public class Consent extends DomainResource { * @return {@link #provision} (Rules which provide exceptions to the base rule * or subrules.) */ - public List getProvision() { + public List getProvision() { if (this.provision == null) - this.provision = new ArrayList(); + this.provision = new ArrayList(); return this.provision; } /** * @return Returns a reference to this for easy method chaining */ - public provisionComponent setProvision(List theProvision) { + public ProvisionComponent setProvision(List theProvision) { this.provision = theProvision; return this; } @@ -1839,25 +1839,25 @@ public class Consent extends DomainResource { public boolean hasProvision() { if (this.provision == null) return false; - for (provisionComponent item : this.provision) + for (ProvisionComponent item : this.provision) if (!item.isEmpty()) return true; return false; } - public provisionComponent addProvision() { // 3 - provisionComponent t = new provisionComponent(); + public ProvisionComponent addProvision() { // 3 + ProvisionComponent t = new ProvisionComponent(); if (this.provision == null) - this.provision = new ArrayList(); + this.provision = new ArrayList(); this.provision.add(t); return t; } - public provisionComponent addProvision(provisionComponent t) { // 3 + public ProvisionComponent addProvision(ProvisionComponent t) { // 3 if (t == null) return this; if (this.provision == null) - this.provision = new ArrayList(); + this.provision = new ArrayList(); this.provision.add(t); return this; } @@ -1866,7 +1866,7 @@ public class Consent extends DomainResource { * @return The first repetition of repeating field {@link #provision}, creating * it if it does not already exist */ - public provisionComponent getProvisionFirstRep() { + public ProvisionComponent getProvisionFirstRep() { if (getProvision().isEmpty()) { addProvision(); } @@ -2021,7 +2021,7 @@ public class Consent extends DomainResource { this.getData().add((provisionDataComponent) value); // provisionDataComponent return value; case -547120939: // provision - this.getProvision().add((provisionComponent) value); // provisionComponent + this.getProvision().add((ProvisionComponent) value); // provisionComponent return value; default: return super.setProperty(hash, name, value); @@ -2053,13 +2053,13 @@ public class Consent extends DomainResource { } else if (name.equals("data")) { this.getData().add((provisionDataComponent) value); } else if (name.equals("provision")) { - this.getProvision().add((provisionComponent) value); + this.getProvision().add((ProvisionComponent) value); } else return super.setProperty(name, value); return value; - } - - @Override + } + + @Override public void removeChild(String name, Base value) throws FHIRException { if (name.equals("type")) { this.type = null; @@ -2082,7 +2082,7 @@ public class Consent extends DomainResource { } else if (name.equals("data")) { this.getData().remove((provisionDataComponent) value); } else if (name.equals("provision")) { - this.getProvision().remove((provisionComponent) value); + this.getProvision().remove((ProvisionComponent) value); } else super.removeChild(name, value); @@ -2180,13 +2180,13 @@ public class Consent extends DomainResource { return super.addChild(name); } - public provisionComponent copy() { - provisionComponent dst = new provisionComponent(); + public ProvisionComponent copy() { + ProvisionComponent dst = new ProvisionComponent(); copyValues(dst); return dst; } - public void copyValues(provisionComponent dst) { + public void copyValues(ProvisionComponent dst) { super.copyValues(dst); dst.type = type == null ? null : type.copy(); dst.period = period == null ? null : period.copy(); @@ -2234,8 +2234,8 @@ public class Consent extends DomainResource { } ; if (provision != null) { - dst.provision = new ArrayList(); - for (provisionComponent i : provision) + dst.provision = new ArrayList(); + for (ProvisionComponent i : provision) dst.provision.add(i.copy()); } ; @@ -2245,9 +2245,9 @@ public class Consent extends DomainResource { public boolean equalsDeep(Base other_) { if (!super.equalsDeep(other_)) return false; - if (!(other_ instanceof provisionComponent)) + if (!(other_ instanceof ProvisionComponent)) return false; - provisionComponent o = (provisionComponent) other_; + ProvisionComponent o = (ProvisionComponent) other_; return compareDeep(type, o.type, true) && compareDeep(period, o.period, true) && compareDeep(actor, o.actor, true) && compareDeep(action, o.action, true) && compareDeep(securityLabel, o.securityLabel, true) && compareDeep(purpose, o.purpose, true) && compareDeep(class_, o.class_, true) @@ -2259,9 +2259,9 @@ public class Consent extends DomainResource { public boolean equalsShallow(Base other_) { if (!super.equalsShallow(other_)) return false; - if (!(other_ instanceof provisionComponent)) + if (!(other_ instanceof ProvisionComponent)) return false; - provisionComponent o = (provisionComponent) other_; + ProvisionComponent o = (ProvisionComponent) other_; return compareValues(type, o.type, true); } @@ -2468,9 +2468,9 @@ public class Consent extends DomainResource { } else return super.setProperty(name, value); return value; - } - - @Override + } + + @Override public void removeChild(String name, Base value) throws FHIRException { if (name.equals("role")) { this.role = null; @@ -2771,9 +2771,9 @@ public class Consent extends DomainResource { } else return super.setProperty(name, value); return value; - } - - @Override + } + + @Override public void removeChild(String name, Base value) throws FHIRException { if (name.equals("meaning")) { this.meaning = null; @@ -2996,7 +2996,7 @@ public class Consent extends DomainResource { */ @Child(name = "provision", type = {}, order = 12, min = 0, max = 1, modifier = false, summary = true) @Description(shortDefinition = "Constraints to the base Consent.policyRule", formalDefinition = "An exception to the base policy of this consent. An exception can be an addition or removal of access permissions.") - protected provisionComponent provision; + protected ProvisionComponent provision; private static final long serialVersionUID = 206528051L; @@ -3663,12 +3663,12 @@ public class Consent extends DomainResource { * @return {@link #provision} (An exception to the base policy of this consent. * An exception can be an addition or removal of access permissions.) */ - public provisionComponent getProvision() { + public ProvisionComponent getProvision() { if (this.provision == null) if (Configuration.errorOnAutoCreate()) throw new Error("Attempt to auto-create Consent.provision"); else if (Configuration.doAutoCreate()) - this.provision = new provisionComponent(); // cc + this.provision = new ProvisionComponent(); // cc return this.provision; } @@ -3681,7 +3681,7 @@ public class Consent extends DomainResource { * consent. An exception can be an addition or removal of access * permissions.) */ - public Consent setProvision(provisionComponent value) { + public Consent setProvision(ProvisionComponent value) { this.provision = value; return this; } @@ -3877,7 +3877,7 @@ public class Consent extends DomainResource { this.getVerification().add((ConsentVerificationComponent) value); // ConsentVerificationComponent return value; case -547120939: // provision - this.provision = (provisionComponent) value; // provisionComponent + this.provision = (ProvisionComponent) value; // provisionComponent return value; default: return super.setProperty(hash, name, value); @@ -3913,13 +3913,13 @@ public class Consent extends DomainResource { } else if (name.equals("verification")) { this.getVerification().add((ConsentVerificationComponent) value); } else if (name.equals("provision")) { - this.provision = (provisionComponent) value; // provisionComponent + this.provision = (ProvisionComponent) value; // provisionComponent } else return super.setProperty(name, value); return value; - } - - @Override + } + + @Override public void removeChild(String name, Base value) throws FHIRException { if (name.equals("identifier")) { this.getIdentifier().remove(castToIdentifier(value)); @@ -3946,7 +3946,7 @@ public class Consent extends DomainResource { } else if (name.equals("verification")) { this.getVerification().remove((ConsentVerificationComponent) value); } else if (name.equals("provision")) { - this.provision = (provisionComponent) value; // provisionComponent + this.provision = (ProvisionComponent) value; // provisionComponent } else super.removeChild(name, value); @@ -4058,7 +4058,7 @@ public class Consent extends DomainResource { } else if (name.equals("verification")) { return addVerification(); } else if (name.equals("provision")) { - this.provision = new provisionComponent(); + this.provision = new ProvisionComponent(); return this.provision; } else return super.addChild(name); From 75fc9a8b57de774676fb6265cafdf0a5347206ea Mon Sep 17 00:00:00 2001 From: dotasek Date: Thu, 29 Aug 2024 11:39:47 -0400 Subject: [PATCH 02/50] Update azure maven tasks to version 4 (#1726) * Update azure maven tasks to version 4 * Increase compiler memory * Increment compiler version --- master-branch-pipeline.yml | 6 +++--- pom.xml | 4 ++-- pull-request-pipeline.yml | 2 +- release-branch-pipeline.yml | 4 ++-- setup-and-cache-job-template.yml | 2 +- test-cli-exec-job-template.yml | 2 +- test-unit-jobs-template.yml | 2 +- 7 files changed, 11 insertions(+), 11 deletions(-) diff --git a/master-branch-pipeline.yml b/master-branch-pipeline.yml index 6b94ef18d..bdafd4688 100644 --- a/master-branch-pipeline.yml +++ b/master-branch-pipeline.yml @@ -82,7 +82,7 @@ jobs: # Deploy the SNAPSHOT artifact to sonatype nexus. # This is done for the master branch merges only. - - task: Maven@3 + - task: Maven@4 displayName: 'Deploy to Sonatype staging' inputs: mavenPomFile: '$(System.DefaultWorkingDirectory)/pom.xml' @@ -115,7 +115,7 @@ jobs: # Deploy the SNAPSHOT artifact to GitHub packages. # This is done for the master branch merges only. - - task: Maven@3 + - task: Maven@4 displayName: 'Deploy to GitHub packages' inputs: mavenPomFile: '$(System.DefaultWorkingDirectory)/pom.xml' @@ -164,7 +164,7 @@ jobs: pip3 install pandas displayName: 'Set up python packages' - - task: Maven@3 + - task: Maven@4 inputs: mavenPomFile: '$(System.DefaultWorkingDirectory)/pom.xml' options: '-Dmaven.repo.local=$(MAVEN_CACHE_FOLDER) -pl org.hl7.fhir.utilities ' diff --git a/pom.xml b/pom.xml index 15f288cc3..23be8b3a6 100644 --- a/pom.xml +++ b/pom.xml @@ -418,7 +418,7 @@ org.apache.maven.plugins maven-compiler-plugin - 3.10.1 + 3.13.0 11 @@ -428,7 +428,7 @@ while if true it will use an executable. --> true 512m - 4000m + 5632m true diff --git a/pull-request-pipeline.yml b/pull-request-pipeline.yml index 2f1a97d58..2ecaa863f 100644 --- a/pull-request-pipeline.yml +++ b/pull-request-pipeline.yml @@ -154,7 +154,7 @@ jobs: sourceFolder: '$(System.DefaultWorkingDirectory)/org.hl7.fhir.${{ module }}_target/' contents: '**' targetFolder: '$(System.DefaultWorkingDirectory)/org.hl7.fhir.${{ module }}/target/' - - task: Maven@3 + - task: Maven@4 inputs: mavenPomFile: 'pom.xml' options: '-P JACOCO' diff --git a/release-branch-pipeline.yml b/release-branch-pipeline.yml index 3ff7caff5..3fcbcdf96 100644 --- a/release-branch-pipeline.yml +++ b/release-branch-pipeline.yml @@ -13,7 +13,7 @@ jobs: - job: check_all_dependencies_are_releases timeoutInMinutes: 5 steps: - - task: Maven@3 + - task: Maven@4 inputs: mavenPomFile: 'pom.xml' options: '-DcheckForSnapshotDependencies' @@ -136,7 +136,7 @@ jobs: version_from_pom: $[ dependencies.get_release_version.outputs['setOutput.version_from_pom'] ] steps: # Runs 'mvn clean package' - - task: Maven@3 + - task: Maven@4 inputs: mavenPomFile: 'pom.xml' mavenOptions: '-Xmx768m -Dmaven.resolver.transport=wagon' diff --git a/setup-and-cache-job-template.yml b/setup-and-cache-job-template.yml index 311b0ce8d..1844f946b 100644 --- a/setup-and-cache-job-template.yml +++ b/setup-and-cache-job-template.yml @@ -21,7 +21,7 @@ jobs: script: mkdir -p $(MAVEN_CACHE_FOLDER); pwd; ls -al $(MAVEN_CACHE_FOLDER) - ${{ if eq(parameters.signArtifacts, true) }}: - template: setup-signing-tasks-template.yml - - task: Maven@3 + - task: Maven@4 inputs: mavenPomFile: 'pom.xml' ${{ if eq(parameters.signArtifacts, true) }}: diff --git a/test-cli-exec-job-template.yml b/test-cli-exec-job-template.yml index 003a4fd4b..4e1516247 100644 --- a/test-cli-exec-job-template.yml +++ b/test-cli-exec-job-template.yml @@ -19,7 +19,7 @@ jobs: modules: - org.hl7.fhir.validation.cli # Runs 'mvn exec' - - task: Maven@3 + - task: Maven@4 inputs: mavenPomFile: 'pom.xml' mavenOptions: '-Xmx768m -Dmaven.resolver.transport=wagon' diff --git a/test-unit-jobs-template.yml b/test-unit-jobs-template.yml index 9a77bbe2b..1b7e47685 100644 --- a/test-unit-jobs-template.yml +++ b/test-unit-jobs-template.yml @@ -24,7 +24,7 @@ jobs: modules: - org.hl7.fhir.${{ value }} # Runs 'mvn install' - - task: Maven@3 + - task: Maven@4 inputs: mavenPomFile: 'pom.xml' options: '-Dmaven.repo.local=$(MAVEN_CACHE_FOLDER) -pl org.hl7.fhir.${{value}} -Djacoco.skip=${{unit.skipJaCoCo}} -P JACOCO' From c260bece21f9d6d935f5e90791d9ac87f98cc2b7 Mon Sep 17 00:00:00 2001 From: dotasek Date: Fri, 30 Aug 2024 09:44:33 -0400 Subject: [PATCH 03/50] Check for null fetcher (#1728) --- .../instance/type/ConceptMapValidator.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/type/ConceptMapValidator.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/type/ConceptMapValidator.java index 0d6892c17..b3aeb1c4c 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/type/ConceptMapValidator.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/type/ConceptMapValidator.java @@ -34,9 +34,9 @@ public class ConceptMapValidator extends BaseValidator { private static final int TOO_MANY_CODES_TO_VALIDATE = 500; public static class PropertyDefinition { - private String type; - private String system; - private CodeSystem cs; + private final String type; + private final String system; + private final CodeSystem cs; protected PropertyDefinition(String type, String system, CodeSystem cs) { super(); this.type = type; @@ -94,7 +94,7 @@ public class ConceptMapValidator extends BaseValidator { public class CMCodingValidationRequest extends CodingValidationRequest { - private NodeStack stack; + private final NodeStack stack; public CMCodingValidationRequest(NodeStack stack, Coding code, ValueSet vs) { super(code, vs); @@ -106,7 +106,7 @@ public class ConceptMapValidator extends BaseValidator { } } - private List batch = new ArrayList<>(); + private final List batch = new ArrayList<>(); public ConceptMapValidator(BaseValidator parent) { super(parent); @@ -237,7 +237,7 @@ public class ConceptMapValidator extends BaseValidator { } else { warning(errors, "2023-03-05", IssueType.NOTFOUND, grp.line(), grp.col(), stack.push(e, -1, null, null).getLiteralPath(), sourceScope != null, I18nConstants.CONCEPTMAP_GROUP_SOURCE_UNKNOWN, e.getValue()); } - if (ctxt.source.version == null && ctxt.source.cs != null && !CodeSystemUtilities.isExemptFromMultipleVersionChecking(ctxt.source.url)) { + if (ctxt.source.version == null && ctxt.source.cs != null && !CodeSystemUtilities.isExemptFromMultipleVersionChecking(ctxt.source.url) && fetcher != null) { Set possibleVersions = fetcher.fetchCanonicalResourceVersions(null, valContext.getAppContext(), ctxt.source.url); warning(errors, NO_RULE_DATE, IssueType.INVALID, grp.line(), grp.col(), stack.getLiteralPath(), possibleVersions.size() <= 1, I18nConstants.TYPE_SPECIFIC_CHECKS_DT_CANONICAL_MULTIPLE_POSSIBLE_VERSIONS, ctxt.source.url, ctxt.source.cs.getVersion(), CommaSeparatedStringBuilder.join(", ", Utilities.sorted(possibleVersions))); From 385b40cd4e88cdaa552a3add12862120a1198b9b Mon Sep 17 00:00:00 2001 From: dotasek Date: Fri, 30 Aug 2024 13:36:13 -0400 Subject: [PATCH 04/50] Update staging plugin (#1730) --- org.hl7.fhir.report/pom.xml | 2 +- org.hl7.fhir.validation.cli/pom.xml | 2 +- pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/org.hl7.fhir.report/pom.xml b/org.hl7.fhir.report/pom.xml index 14605cc43..7889e540c 100644 --- a/org.hl7.fhir.report/pom.xml +++ b/org.hl7.fhir.report/pom.xml @@ -89,7 +89,7 @@ org.sonatype.plugins nexus-staging-maven-plugin - true + true diff --git a/org.hl7.fhir.validation.cli/pom.xml b/org.hl7.fhir.validation.cli/pom.xml index e6da91b3d..f0907cd29 100644 --- a/org.hl7.fhir.validation.cli/pom.xml +++ b/org.hl7.fhir.validation.cli/pom.xml @@ -405,7 +405,7 @@ org.sonatype.plugins nexus-staging-maven-plugin - true + true diff --git a/pom.xml b/pom.xml index 23be8b3a6..645efd4c4 100644 --- a/pom.xml +++ b/pom.xml @@ -717,7 +717,7 @@ org.sonatype.plugins nexus-staging-maven-plugin - 1.6.13 + 1.7.0 true ossrh From 8e908da1aba78fa48c83c81aeb2c4de7179889ef Mon Sep 17 00:00:00 2001 From: Gjergj Sheldija Date: Tue, 3 Sep 2024 13:50:54 +0200 Subject: [PATCH 05/50] unit tests to check the concurrency bug --- .../r5/elementmodel/LanguageUtilsTest.java | 37 +++++++++++++++++++ .../languageUtils/CodeSystem-answer.json | 33 +++++++++++++++++ .../languageUtils/CodeSystem-answer.po | 37 +++++++++++++++++++ 3 files changed, 107 insertions(+) create mode 100644 org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/elementmodel/LanguageUtilsTest.java create mode 100644 org.hl7.fhir.r5/src/test/resources/languageUtils/CodeSystem-answer.json create mode 100644 org.hl7.fhir.r5/src/test/resources/languageUtils/CodeSystem-answer.po diff --git a/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/elementmodel/LanguageUtilsTest.java b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/elementmodel/LanguageUtilsTest.java new file mode 100644 index 000000000..58de58105 --- /dev/null +++ b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/elementmodel/LanguageUtilsTest.java @@ -0,0 +1,37 @@ +package org.hl7.fhir.r5.elementmodel; + +import org.hl7.fhir.r5.context.IWorkerContext; +import org.hl7.fhir.r5.test.utils.TestingUtilities; +import org.hl7.fhir.utilities.i18n.LanguageFileProducer; +import org.hl7.fhir.utilities.i18n.PoGetTextProducer; +import org.hl7.fhir.utilities.tests.ResourceLoaderTests; +import org.junit.jupiter.api.Test; + +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; + + +class LanguageUtilsTest implements ResourceLoaderTests { + + @Test + void importFromTranslations() throws Exception { + + IWorkerContext context = TestingUtilities.getSharedWorkerContext(); + + org.hl7.fhir.r5.elementmodel.JsonParser jp = new org.hl7.fhir.r5.elementmodel.JsonParser(context); + InputStream resource = getResourceAsInputStream("languageUtils", "CodeSystem-answer.json"); + Element element = jp.parseSingle(resource, null); + + PoGetTextProducer lp = new PoGetTextProducer(); + List res = new ArrayList<>(); + res.addAll(lp.loadSource(getResourceAsInputStream("languageUtils", "CodeSystem-answer.po"))); + + LanguageUtils languageUtils = new LanguageUtils(context); + int result = languageUtils.importFromTranslations(element, res, null); + + assert result == 3; + + } + +} \ No newline at end of file diff --git a/org.hl7.fhir.r5/src/test/resources/languageUtils/CodeSystem-answer.json b/org.hl7.fhir.r5/src/test/resources/languageUtils/CodeSystem-answer.json new file mode 100644 index 000000000..550bd355c --- /dev/null +++ b/org.hl7.fhir.r5/src/test/resources/languageUtils/CodeSystem-answer.json @@ -0,0 +1,33 @@ +{ + "resourceType": "CodeSystem", + "status": "active", + "content": "complete", + "name": "BasicAnswer", + "id": "basic-answer", + "title": "Administration-Method", + "description": "Basic answers for any kind of questions.", + "url": "https://example.com/CodeSystem/basic-answer", + "concept": [ + { + "code": "ok", + "display": "OK", + "definition": "KO" + }, + { + "code": "yes", + "display": "Yes", + "definition": "seY" + }, + { + "code": "no", + "display": "No", + "definition": "oN" + } + ], + "language": "en", + "version": "0.1.0", + "date": "2024-04-07", + "publisher": "Sample", + "caseSensitive": false, + "count": 3 +} diff --git a/org.hl7.fhir.r5/src/test/resources/languageUtils/CodeSystem-answer.po b/org.hl7.fhir.r5/src/test/resources/languageUtils/CodeSystem-answer.po new file mode 100644 index 000000000..becb6026b --- /dev/null +++ b/org.hl7.fhir.r5/src/test/resources/languageUtils/CodeSystem-answer.po @@ -0,0 +1,37 @@ +# en -> it + +#: CanonicalResource.name +#. A natural language name identifying the code system. This name should be usable as an identifier for the module by machine processing applications such as code generation. +msgid "BasicAnswer" +msgstr "" + +#: CanonicalResource.title +#. A short, descriptive, user-friendly title for the code system. +msgid "Administration-Method" +msgstr "" + +#: CanonicalResource.publisher +#. The name of the organization or individual that published the code system. +msgid "Example Publisher" +msgstr "" + +#: CanonicalResource.description +#. A free text natural language description of the code system from a consumer's perspective. +msgid "Basic answers for any kind of questions." +msgstr "" + +#: CodeSystem.concept.display +#. A human readable string that is the recommended default way to present this concept to a user. +msgid "OK" +msgstr "OK" + +#: CodeSystem.concept.display +#. A human readable string that is the recommended default way to present this concept to a user. +msgid "Yes" +msgstr "Si" + +#: CodeSystem.concept.display +#. A human readable string that is the recommended default way to present this concept to a user. +msgid "No" +msgstr "No" + From 00f4f0998f914e1d7f4cc22159023dfcd2e3fc8a Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Tue, 3 Sep 2024 21:26:17 +0800 Subject: [PATCH 06/50] Improve message for when elements are out of order --- .../hl7/fhir/r5/conformance/profile/ProfileUtilities.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/conformance/profile/ProfileUtilities.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/conformance/profile/ProfileUtilities.java index 468430552..79d668b36 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/conformance/profile/ProfileUtilities.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/conformance/profile/ProfileUtilities.java @@ -3463,6 +3463,11 @@ public class ProfileUtilities { public void sortDifferential(StructureDefinition base, StructureDefinition diff, String name, List errors, boolean errorIfChanges) throws FHIRException { + int index = 0; + for (ElementDefinition ed : diff.getDifferential().getElement()) { + ed.setUserData("ed.index", Integer.toString(index)); + index++; + } List original = new ArrayList<>(); original.addAll(diff.getDifferential().getElement()); final List diffList = diff.getDifferential().getElement(); @@ -3520,7 +3525,7 @@ public class ProfileUtilities { ElementDefinition e = diffList.get(i); ElementDefinition n = newDiff.get(i); if (!n.getPath().equals(e.getPath())) { - errors.add("The element "+e.getPath()+" is out of order (and maybe others after it)"); + errors.add("The element "+(e.hasId() ? e.getId() : e.getPath())+" @diff["+e.getUserString("ed.index")+"] is out of order (and maybe others after it)"); return; } } From 83daa93fbc68cd024eec3a98681dbb4779fd0fe3 Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Tue, 3 Sep 2024 21:26:35 +0800 Subject: [PATCH 07/50] fix concurrent modification error processing language translations --- .../org/hl7/fhir/r5/elementmodel/LanguageUtils.java | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/LanguageUtils.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/LanguageUtils.java index fa957c861..0e762dede 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/LanguageUtils.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/LanguageUtils.java @@ -166,7 +166,9 @@ public class LanguageUtils { } for (TranslationUnit t : translations) { if (!usedUnits.contains(t)) { - messages.add(new ValidationMessage(Source.Publisher, IssueType.INFORMATIONAL, t.getId(), "Unused '"+t.getLanguage()+"' translation '"+t.getSrcText()+"' -> '"+t.getTgtText()+"'", IssueSeverity.INFORMATION)); + if (messages != null) { + messages.add(new ValidationMessage(Source.Publisher, IssueType.INFORMATIONAL, t.getId(), "Unused '"+t.getLanguage()+"' translation '"+t.getSrcText()+"' -> '"+t.getTgtText()+"'", IssueSeverity.INFORMATION)); + } } } return r; @@ -182,7 +184,9 @@ public class LanguageUtils { } for (TranslationUnit t : translations) { if (!usedUnits.contains(t)) { - messages.add(new ValidationMessage(Source.Publisher, IssueType.INFORMATIONAL, t.getId(), "Unused '"+t.getLanguage()+"' translation '"+t.getSrcText()+"' -> '"+t.getTgtText()+"'", IssueSeverity.INFORMATION)); + if (messages != null) { + messages.add(new ValidationMessage(Source.Publisher, IssueType.INFORMATIONAL, t.getId(), "Unused '"+t.getLanguage()+"' translation '"+t.getSrcText()+"' -> '"+t.getTgtText()+"'", IssueSeverity.INFORMATION)); + } } } return r; @@ -296,7 +300,9 @@ public class LanguageUtils { } } } - for (Element c : element.getChildren()) { + List cl = new ArrayList(); + cl.addAll(element.getChildren()); + for (Element c : cl) { if (!c.getName().equals("designation")) { t = t + importFromTranslations(element, c, translations, usedUnits); } From 7e5014c6d7b45d21466ea27d9dd24363fc9862ed Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Tue, 3 Sep 2024 21:26:53 +0800 Subject: [PATCH 08/50] Fix problem generating value set spreadsheets --- .../spreadsheets/SpreadsheetGenerator.java | 3 ++- .../ValueSetSpreadsheetGenerator.java | 21 +++++++++++-------- 2 files changed, 14 insertions(+), 10 deletions(-) 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 18a7e22cf..ab82995d8 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 @@ -100,7 +100,8 @@ public class SpreadsheetGenerator { if (name.length() > MAX_SENSITIVE_SHEET_NAME_LEN - 2) { name = name.substring(0, MAX_SENSITIVE_SHEET_NAME_LEN - 2); } - String s = fixSheetNameChars(name); + name = fixSheetNameChars(name); + String s = name; if (sheetNames.containsKey(s)) { int i = 1; do { diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/spreadsheets/ValueSetSpreadsheetGenerator.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/spreadsheets/ValueSetSpreadsheetGenerator.java index 106a581e2..99bd4cb68 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/spreadsheets/ValueSetSpreadsheetGenerator.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/spreadsheets/ValueSetSpreadsheetGenerator.java @@ -19,6 +19,7 @@ import org.hl7.fhir.r5.model.ValueSet.ConceptSetFilterComponent; import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionContainsComponent; import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionParameterComponent; import org.hl7.fhir.r5.model.StructureDefinition.StructureDefinitionMappingComponent; +import org.hl7.fhir.utilities.DebugUtilities; import org.hl7.fhir.utilities.i18n.I18nConstants; public class ValueSetSpreadsheetGenerator extends CanonicalSpreadsheetGenerator { @@ -36,11 +37,12 @@ public class ValueSetSpreadsheetGenerator extends CanonicalSpreadsheetGenerator System.out.println("no valueset!"); } addValueSetMetadata(renderCanonicalResource(vs, false), vs); + int i = 0; for (ConceptSetComponent inc : vs.getCompose().getInclude()) { - genInclude(vs, inc, "Include"); + genInclude(vs, inc, "Include", i++); } for (ConceptSetComponent exc : vs.getCompose().getExclude()) { - genInclude(vs, exc, "Exclude"); + genInclude(vs, exc, "Exclude", i++); } if (vs.hasExpansion()) { if (vs.getExpansion().hasParameter()) { @@ -82,11 +84,11 @@ public class ValueSetSpreadsheetGenerator extends CanonicalSpreadsheetGenerator return value ? "" : "false"; } - private void genInclude(ValueSet vs, ConceptSetComponent inc, String mode) { + private void genInclude(ValueSet vs, ConceptSetComponent inc, String mode, int count) { if (inc.hasSystem()) { - genIncludeSystem(vs, inc, mode); + genIncludeSystem(vs, inc, mode, count); } else { - genIncludeValueSets(vs, inc, mode); + genIncludeValueSets(vs, inc, mode, count); } // String subname = inc.hasSystem() ? : "ValueSets"; // @@ -107,14 +109,15 @@ public class ValueSetSpreadsheetGenerator extends CanonicalSpreadsheetGenerator // configureSheet(sheet, sd); } - private void genIncludeValueSets(ValueSet vs, ConceptSetComponent inc, String mode) { - Sheet sheet = makeSheet(mode+" ValueSets"); + private void genIncludeValueSets(ValueSet vs, ConceptSetComponent inc, String mode, int count) { + Sheet sheet = makeSheet(mode+" ValueSet #"+count); addValueSets(sheet, inc.getValueSet()); configureSheet(sheet); } - private void genIncludeSystem(ValueSet vs, ConceptSetComponent inc, String mode) { - Sheet sheet = makeSheet(mode+" from "+dr.displaySystem(inc.getSystem())); + private void genIncludeSystem(ValueSet vs, ConceptSetComponent inc, String mode, int count) { + DebugUtilities.ln(inc.getSystem()); + Sheet sheet = makeSheet(mode+" #"+count); if (inc.hasValueSet()) { addValueSets(sheet, inc.getValueSet()); } From 63ab904401a7af0bc66e0732f80cdceea5c46752 Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Tue, 3 Sep 2024 21:27:28 +0800 Subject: [PATCH 09/50] fix problem where profile rendering had spurious 'slices for' nodes everywhere --- .../renderers/StructureDefinitionRenderer.java | 16 +++++++++++++--- .../fhir/r5/test/NarrativeGenerationTests.java | 8 ++++---- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/StructureDefinitionRenderer.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/StructureDefinitionRenderer.java index e2276d692..bcb245cc6 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/StructureDefinitionRenderer.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/StructureDefinitionRenderer.java @@ -897,7 +897,7 @@ public class StructureDefinitionRenderer extends ResourceRenderer { Row parent = null; if (child.hasSliceName()) { // ok, we're a slice - if (slicer == null || !slicer.getId().equals(child.getPath())) { + if (slicer == null || !noTail(slicer.getId()).equals(child.getPath())) { parent = gen.new Row(); String anchorE = child.getPath(); anchorE = makeAnchorUnique(anchorE); @@ -906,7 +906,7 @@ public class StructureDefinitionRenderer extends ResourceRenderer { parent.setColor(context.getProfileUtilities().getRowColor(child, isConstraintMode)); parent.setLineColor(1); parent.setIcon("icon_slice.png", context.formatPhrase(RenderingContext.TEXT_ICON_SLICE)); - parent.getCells().add(gen.new Cell(null, null, "Slices for "+ child.getName(), "", null)); + parent.getCells().add(gen.new Cell(null, null, context.formatPhrase(RenderingContext.STRUC_DEF_SLICE_FOR, child.getName()), "", null)); switch (context.getStructureMode()) { case BINDINGS: case OBLIGATIONS: @@ -947,6 +947,16 @@ public class StructureDefinitionRenderer extends ResourceRenderer { return slicingRow; } + private String noTail(String id) { + if (id.contains(".")) { + String t = id.substring(id.lastIndexOf(".")+1); + if (Utilities.isInteger(t)) { + return id.substring(0, id.lastIndexOf(".")); + } + } + return id; + } + private String makeAnchorUnique(String anchor) { if (anchors.containsKey(anchor)) { int c = anchors.get(anchor)+1; @@ -1063,7 +1073,7 @@ public class StructureDefinitionRenderer extends ResourceRenderer { hint = checkAdd(hint, !hasDef ? null : gt(element.getDefinitionElement())); } if (element.hasSlicing() && slicesExist(elements, element)) { // some elements set up slicing but don't actually slice, so we don't augment the name - sName = context.formatPhrase(RenderingContext.STRUC_DEF_SLICE_FOR, sName); + sName = context.formatPhrase(RenderingContext.STRUC_DEF_SLICE_FOR, sName); } Cell left = gen.new Cell(null, ref, sName, hint, null); row.getCells().add(left); diff --git a/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/NarrativeGenerationTests.java b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/NarrativeGenerationTests.java index 2372a130d..cab59327e 100644 --- a/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/NarrativeGenerationTests.java +++ b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/NarrativeGenerationTests.java @@ -84,12 +84,12 @@ public class NarrativeGenerationTests { @Override public String getLinkFor(String corePath, String typeSimple) { - throw new NotImplementedException(); + return "http://test/link"; } @Override public BindingResolution resolveBinding(StructureDefinition def, ElementDefinitionBindingComponent binding, String path) throws FHIRException { - throw new NotImplementedException(); + return new BindingResolution("test", "http://test"); } @Override @@ -102,7 +102,7 @@ public class NarrativeGenerationTests { return new BindingResolution(vs.present(), "valueset-"+vs.getIdBase()+".html"); } } - throw new NotImplementedException(); + return new BindingResolution("test", "http://test/ns"); } @Override @@ -120,7 +120,7 @@ public class NarrativeGenerationTests { @Override public String getLinkForUrl(String corePath, String s) { - throw new NotImplementedException(); + return "http://test/link/url"; } @Override From 96485e6175c951433a4308c7522997d75cc9769a Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Tue, 3 Sep 2024 21:27:41 +0800 Subject: [PATCH 10/50] updates --- .../hl7/fhir/utilities/npm/PackageHacker.java | 103 ++++++++++-------- .../xhtml/HierarchicalTableGenerator.java | 1 - 2 files changed, 55 insertions(+), 49 deletions(-) diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/npm/PackageHacker.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/npm/PackageHacker.java index 6aba70e60..62fed54cc 100644 --- a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/npm/PackageHacker.java +++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/npm/PackageHacker.java @@ -30,55 +30,55 @@ public class PackageHacker { private static boolean useSecureReferences = false; public static void main(String[] args) throws FileNotFoundException, IOException { - new PackageHacker().massEdit(new File("/Users/grahamegrieve/web/hl7.org/fhir")); - // new PackageHacker().edit("/Users/grahamegrieve/web/hl7.org/fhir/us/vitals/2020Sep/package.tgz"); +// new PackageHacker().massEdit(new File("/Users/grahamegrieve/web/hl7.org/fhir")); + new PackageHacker().edit(args[0]); } - private void massEdit(File dir) throws IOException { - System.out.println("process "+dir.getAbsolutePath()); - for (File f : dir.listFiles()) { - if (f.isDirectory()) { - massEdit(f); - } else if (f.getName().equals("package.tgz")) { - try { - FileInputStream fs = ManagedFileAccess.inStream(f); - NpmPackage pck = NpmPackage.fromPackage(fs); - if ("fhir.core".equals(pck.getNpm().str("type"))) { - System.out.println("!!change "+f.getAbsolutePath()); - pck.getNpm().remove("type"); - pck.getNpm().set("type", "Core"); - FileOutputStream fso = ManagedFileAccess.outStream(f); - try { - pck.save(fso); - } finally { - fso.close(); - } - } - } catch (Exception e) { - System.out.println("!!Error: "+e.getMessage()); - } - } else if (f.getName().startsWith("hl7.fhir.r") && f.getName().endsWith(".examples.tgz")) { - try { - FileInputStream fs = ManagedFileAccess.inStream(f); - NpmPackage pck = NpmPackage.fromPackage(fs); - if ("fhir.examples".equals(pck.getNpm().str("type"))) { - System.out.println("!!change "+f.getAbsolutePath()); - pck.getNpm().remove("type"); - pck.getNpm().set("type", "Examples"); - FileOutputStream fso = ManagedFileAccess.outStream(f); - try { - pck.save(fso); - } finally { - fso.close(); - } - } - } catch (Exception e) { - System.out.println("!!Error: "+e.getMessage()); - } - - } - } - } +// private void massEdit(File dir) throws IOException { +// System.out.println("process "+dir.getAbsolutePath()); +// for (File f : dir.listFiles()) { +// if (f.isDirectory()) { +// massEdit(f); +// } else if (f.getName().equals("package.tgz")) { +// try { +// FileInputStream fs = ManagedFileAccess.inStream(f); +// NpmPackage pck = NpmPackage.fromPackage(fs); +// if ("fhir.core".equals(pck.getNpm().str("type"))) { +// System.out.println("!!change "+f.getAbsolutePath()); +// pck.getNpm().remove("type"); +// pck.getNpm().set("type", "Core"); +// FileOutputStream fso = ManagedFileAccess.outStream(f); +// try { +// pck.save(fso); +// } finally { +// fso.close(); +// } +// } +// } catch (Exception e) { +// System.out.println("!!Error: "+e.getMessage()); +// } +// } else if (f.getName().startsWith("hl7.fhir.r") && f.getName().endsWith(".examples.tgz")) { +// try { +// FileInputStream fs = ManagedFileAccess.inStream(f); +// NpmPackage pck = NpmPackage.fromPackage(fs); +// if ("fhir.examples".equals(pck.getNpm().str("type"))) { +// System.out.println("!!change "+f.getAbsolutePath()); +// pck.getNpm().remove("type"); +// pck.getNpm().set("type", "Examples"); +// FileOutputStream fso = ManagedFileAccess.outStream(f); +// try { +// pck.save(fso); +// } finally { +// fso.close(); +// } +// } +// } catch (Exception e) { +// System.out.println("!!Error: "+e.getMessage()); +// } +// +// } +// } +// } private void edit(String name) throws FileNotFoundException, IOException { File f = ManagedFileAccess.file(name); @@ -132,7 +132,14 @@ public class PackageHacker { private void change(JsonObject npm) throws FileNotFoundException, IOException { // fixVersions(npm, ver); npm.remove("notForPublication"); - npm.set("name", "hl7.fhir.us.vitals"); + npm.set("name", "hl7.fhir.us.core.v700"); + npm.set("version", "7.0.0"); + npm.set("canonical", "http://hl7.org/fhir/us/core/v700"); + npm.set("url", "http://hl7.org/fhir/us/core/v700"); + npm.remove("dependencies"); + JsonObject dep = new JsonObject(); + npm.add("dependencies", dep); + dep.add("hl7.fhir.us.core", "7.0.0"); } private void fixVersionInContent(Map content) { diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/xhtml/HierarchicalTableGenerator.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/xhtml/HierarchicalTableGenerator.java index 9fc5f29ff..b4cb4bc5d 100644 --- a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/xhtml/HierarchicalTableGenerator.java +++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/xhtml/HierarchicalTableGenerator.java @@ -560,7 +560,6 @@ public class HierarchicalTableGenerator { } return b.toString(); } - } public class TableModel { From 973ab9e56f9a1d6cd7e81d116feb84b25ee0ffc5 Mon Sep 17 00:00:00 2001 From: Gjergj Sheldija Date: Tue, 3 Sep 2024 15:41:58 +0200 Subject: [PATCH 11/50] possible fix --- .../fhir/r5/elementmodel/LanguageUtils.java | 5 ++- .../r5/elementmodel/LanguageUtilsTest.java | 22 ++++++++++- .../CodeSystem-answer-translated.json | 38 +++++++++++++++++++ .../languageUtils/CodeSystem-answer.json | 9 ++--- 4 files changed, 65 insertions(+), 9 deletions(-) create mode 100644 org.hl7.fhir.r5/src/test/resources/languageUtils/CodeSystem-answer-translated.json diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/LanguageUtils.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/LanguageUtils.java index fa957c861..c5b26b2db 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/LanguageUtils.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/LanguageUtils.java @@ -296,7 +296,10 @@ public class LanguageUtils { } } } - for (Element c : element.getChildren()) { + + // Create a copy of the children collection before iterating + List childrenCopy = new ArrayList<>(element.getChildren()); + for (Element c : childrenCopy) { if (!c.getName().equals("designation")) { t = t + importFromTranslations(element, c, translations, usedUnits); } diff --git a/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/elementmodel/LanguageUtilsTest.java b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/elementmodel/LanguageUtilsTest.java index 58de58105..631731b27 100644 --- a/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/elementmodel/LanguageUtilsTest.java +++ b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/elementmodel/LanguageUtilsTest.java @@ -1,15 +1,20 @@ package org.hl7.fhir.r5.elementmodel; import org.hl7.fhir.r5.context.IWorkerContext; +import org.hl7.fhir.r5.formats.JsonCreatorDirect; +import org.hl7.fhir.r5.test.utils.CompareUtilities; import org.hl7.fhir.r5.test.utils.TestingUtilities; import org.hl7.fhir.utilities.i18n.LanguageFileProducer; import org.hl7.fhir.utilities.i18n.PoGetTextProducer; import org.hl7.fhir.utilities.tests.ResourceLoaderTests; +import org.hl7.fhir.utilities.validation.ValidationMessage; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; -import java.io.InputStream; +import java.io.*; import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; class LanguageUtilsTest implements ResourceLoaderTests { @@ -27,11 +32,24 @@ class LanguageUtilsTest implements ResourceLoaderTests { List res = new ArrayList<>(); res.addAll(lp.loadSource(getResourceAsInputStream("languageUtils", "CodeSystem-answer.po"))); + List lvm = new ArrayList<>(); + lvm.add(new ValidationMessage()); LanguageUtils languageUtils = new LanguageUtils(context); - int result = languageUtils.importFromTranslations(element, res, null); + int result = languageUtils.importFromTranslations(element, res, lvm); + + Writer generatedResource = new StringWriter(); + jp.compose(element, new JsonCreatorDirect(generatedResource, false, false)); assert result == 3; + InputStream translatedResource = getResourceAsInputStream("languageUtils", "CodeSystem-answer-translated.json"); + String text = new BufferedReader(new InputStreamReader(translatedResource)) + .lines() + .collect(Collectors.joining("\n")); + + String msg = CompareUtilities.checkJsonSrcIsSame("", generatedResource.toString(),text, null); + Assertions.assertNull(msg); + } } \ No newline at end of file diff --git a/org.hl7.fhir.r5/src/test/resources/languageUtils/CodeSystem-answer-translated.json b/org.hl7.fhir.r5/src/test/resources/languageUtils/CodeSystem-answer-translated.json new file mode 100644 index 000000000..06f059bde --- /dev/null +++ b/org.hl7.fhir.r5/src/test/resources/languageUtils/CodeSystem-answer-translated.json @@ -0,0 +1,38 @@ +{ + "resourceType" : "CodeSystem", + "id" : "basic-answer", + "language" : "en", + "url" : "https://example.com/CodeSystem/basic-answer", + "version" : "0.1.0", + "name" : "BasicAnswer", + "title" : "Administration-Method", + "status" : "active", + "date" : "2024-04-07", + "publisher" : "Sample", + "description" : "Basic answers for any kind of questions.", + "caseSensitive" : false, + "content" : "complete", + "count" : 3, + "concept" : [ { + "code" : "ok", + "display" : "OK", + "designation" : [ { + "language" : "it", + "value" : "OK" + } ] + }, { + "code" : "yes", + "display" : "Yes", + "designation" : [ { + "language" : "it", + "value" : "Si" + } ] + }, { + "code" : "no", + "display" : "No", + "designation" : [ { + "language" : "it", + "value" : "No" + } ] + } ] +} \ No newline at end of file diff --git a/org.hl7.fhir.r5/src/test/resources/languageUtils/CodeSystem-answer.json b/org.hl7.fhir.r5/src/test/resources/languageUtils/CodeSystem-answer.json index 550bd355c..fe6f0d690 100644 --- a/org.hl7.fhir.r5/src/test/resources/languageUtils/CodeSystem-answer.json +++ b/org.hl7.fhir.r5/src/test/resources/languageUtils/CodeSystem-answer.json @@ -10,18 +10,15 @@ "concept": [ { "code": "ok", - "display": "OK", - "definition": "KO" + "display": "OK" }, { "code": "yes", - "display": "Yes", - "definition": "seY" + "display": "Yes" }, { "code": "no", - "display": "No", - "definition": "oN" + "display": "No" } ], "language": "en", From 9c74e94e6885720b343fcd498c79465565d91999 Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Wed, 4 Sep 2024 08:59:11 +0800 Subject: [PATCH 12/50] test case dependency --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 645efd4c4..be5e3727d 100644 --- a/pom.xml +++ b/pom.xml @@ -21,7 +21,7 @@ 1.26.0 32.0.1-jre 6.4.1 - 1.5.20 + 1.5.21-SNAPSHOT 2.17.0 5.9.2 1.8.2 From 51ad87c7151425706b7c61f7b1ed44d7dcac9b4e Mon Sep 17 00:00:00 2001 From: Gjergj Sheldija Date: Wed, 4 Sep 2024 08:16:03 +0200 Subject: [PATCH 13/50] PR comment --- .../main/java/org/hl7/fhir/r5/elementmodel/LanguageUtils.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/LanguageUtils.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/LanguageUtils.java index c5b26b2db..383531be4 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/LanguageUtils.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/LanguageUtils.java @@ -298,7 +298,7 @@ public class LanguageUtils { } // Create a copy of the children collection before iterating - List childrenCopy = new ArrayList<>(element.getChildren()); + List childrenCopy = List.copyOf(element.getChildren()); for (Element c : childrenCopy) { if (!c.getName().equals("designation")) { t = t + importFromTranslations(element, c, translations, usedUnits); From 515bead90d0748c516e9e02efa3af5af04ccc3f5 Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Wed, 4 Sep 2024 21:59:01 +0800 Subject: [PATCH 14/50] compile fix --- .../ValueSetSpreadsheetGenerator.java | 8 ---- .../hl7/fhir/utilities/npm/PackageHacker.java | 41 +++++++++++-------- 2 files changed, 25 insertions(+), 24 deletions(-) diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/spreadsheets/ValueSetSpreadsheetGenerator.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/spreadsheets/ValueSetSpreadsheetGenerator.java index 99bd4cb68..86e749117 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/spreadsheets/ValueSetSpreadsheetGenerator.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/spreadsheets/ValueSetSpreadsheetGenerator.java @@ -1,26 +1,18 @@ package org.hl7.fhir.r5.renderers.spreadsheets; -import java.io.FileOutputStream; import java.io.IOException; -import java.io.OutputStream; import java.util.List; -import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; -import org.hl7.fhir.exceptions.DefinitionException; import org.hl7.fhir.r5.context.IWorkerContext; -import org.hl7.fhir.r5.context.SimpleWorkerContext; import org.hl7.fhir.r5.model.CanonicalType; -import org.hl7.fhir.r5.model.ElementDefinition; import org.hl7.fhir.r5.model.ValueSet; import org.hl7.fhir.r5.model.ValueSet.ConceptReferenceComponent; import org.hl7.fhir.r5.model.ValueSet.ConceptSetComponent; import org.hl7.fhir.r5.model.ValueSet.ConceptSetFilterComponent; import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionContainsComponent; import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionParameterComponent; -import org.hl7.fhir.r5.model.StructureDefinition.StructureDefinitionMappingComponent; import org.hl7.fhir.utilities.DebugUtilities; -import org.hl7.fhir.utilities.i18n.I18nConstants; public class ValueSetSpreadsheetGenerator extends CanonicalSpreadsheetGenerator { diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/npm/PackageHacker.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/npm/PackageHacker.java index 62fed54cc..2e9a45283 100644 --- a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/npm/PackageHacker.java +++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/npm/PackageHacker.java @@ -31,7 +31,18 @@ public class PackageHacker { public static void main(String[] args) throws FileNotFoundException, IOException { // new PackageHacker().massEdit(new File("/Users/grahamegrieve/web/hl7.org/fhir")); - new PackageHacker().edit(args[0]); + new PackageHacker().edit("/Users/grahamegrieve/web/hl7.org/fhir/6.0.0-ballot1/hl7.fhir.r6.core.tgz"); + new PackageHacker().edit("/Users/grahamegrieve/web/hl7.org/fhir/6.0.0-ballot1/hl7.fhir.r6.corexml.tgz"); + new PackageHacker().edit("/Users/grahamegrieve/web/hl7.org/fhir/6.0.0-ballot1/hl7.fhir.r6.examples.tgz"); + new PackageHacker().edit("/Users/grahamegrieve/web/hl7.org/fhir/6.0.0-ballot1/hl7.fhir.r6.expansions.tgz"); + new PackageHacker().edit("/Users/grahamegrieve/web/hl7.org/fhir/6.0.0-ballot1/hl7.fhir.r6.search.tgz"); + new PackageHacker().edit("/Users/grahamegrieve/web/hl7.org/fhir/6.0.0-ballot2/hl7.fhir.r6.core.tgz"); + new PackageHacker().edit("/Users/grahamegrieve/web/hl7.org/fhir/6.0.0-ballot2/hl7.fhir.r6.corexml.tgz"); + new PackageHacker().edit("/Users/grahamegrieve/web/hl7.org/fhir/6.0.0-ballot2/hl7.fhir.r6.examples.tgz"); + new PackageHacker().edit("/Users/grahamegrieve/web/hl7.org/fhir/6.0.0-ballot2/hl7.fhir.r6.expansions.tgz"); + new PackageHacker().edit("/Users/grahamegrieve/web/hl7.org/fhir/6.0.0-ballot2/hl7.fhir.r6.search.tgz"); + +// new PackageHacker().edit(args[0]); } // private void massEdit(File dir) throws IOException { @@ -85,6 +96,7 @@ public class PackageHacker { if (!f.exists()) throw new Error("Unable to find "+f.getAbsolutePath()); + System.out.println("Loading Package "+f.getAbsolutePath()); NpmPackage pck = null; FileInputStream fs = ManagedFileAccess.inStream(f); try { @@ -95,15 +107,15 @@ public class PackageHacker { System.out.println("Altering Package "+f.getAbsolutePath()); System.out.println(nice(pck.getNpm())); - change(pck.getNpm()); + if (change(pck.getNpm())) { System.out.println("Revised Package"); System.out.println("======================="); System.out.println(nice(pck.getNpm())); System.out.println("======================="); - System.out.print("save? y/n: "); - int r = System.in.read(); - if (r == 'y') { +// System.out.print("save? y/n: "); +// int r = System.in.read(); +// if (r == 'y') { f.renameTo(ManagedFileAccess.file(Utilities.changeFileExt(name, ".tgz.bak"))); FileOutputStream fso = ManagedFileAccess.outStream(f); try { @@ -111,7 +123,8 @@ public class PackageHacker { } finally { fso.close(); } - } +// } + } } private void fixExampleContent(Map content) { @@ -129,17 +142,13 @@ public class PackageHacker { return JsonParser.compose(json, true); } - private void change(JsonObject npm) throws FileNotFoundException, IOException { + private boolean change(JsonObject npm) throws FileNotFoundException, IOException { // fixVersions(npm, ver); - npm.remove("notForPublication"); - npm.set("name", "hl7.fhir.us.core.v700"); - npm.set("version", "7.0.0"); - npm.set("canonical", "http://hl7.org/fhir/us/core/v700"); - npm.set("url", "http://hl7.org/fhir/us/core/v700"); - npm.remove("dependencies"); - JsonObject dep = new JsonObject(); - npm.add("dependencies", dep); - dep.add("hl7.fhir.us.core", "7.0.0"); + if (npm.has("notForPublication")) { + npm.remove("notForPublication"); + return true; + } + return false; } private void fixVersionInContent(Map content) { From 4603b3ac3c18e58ce0c3109d61013afc2f13de1a Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Wed, 4 Sep 2024 23:25:28 +0800 Subject: [PATCH 15/50] compile fix --- .../r5/renderers/spreadsheets/ValueSetSpreadsheetGenerator.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/spreadsheets/ValueSetSpreadsheetGenerator.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/spreadsheets/ValueSetSpreadsheetGenerator.java index 86e749117..942c43eb6 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/spreadsheets/ValueSetSpreadsheetGenerator.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/spreadsheets/ValueSetSpreadsheetGenerator.java @@ -12,7 +12,6 @@ import org.hl7.fhir.r5.model.ValueSet.ConceptSetComponent; import org.hl7.fhir.r5.model.ValueSet.ConceptSetFilterComponent; import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionContainsComponent; import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionParameterComponent; -import org.hl7.fhir.utilities.DebugUtilities; public class ValueSetSpreadsheetGenerator extends CanonicalSpreadsheetGenerator { @@ -108,7 +107,6 @@ public class ValueSetSpreadsheetGenerator extends CanonicalSpreadsheetGenerator } private void genIncludeSystem(ValueSet vs, ConceptSetComponent inc, String mode, int count) { - DebugUtilities.ln(inc.getSystem()); Sheet sheet = makeSheet(mode+" #"+count); if (inc.hasValueSet()) { addValueSets(sheet, inc.getValueSet()); From 7fc34e509ab221f21de41046b1728018adf8ea53 Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Fri, 6 Sep 2024 22:18:01 +0800 Subject: [PATCH 16/50] alter processing of unknown code systems per discussion at ,https://chat.fhir.org/#narrow/stream/179252-IG-creation/topic/Don't.20error.20when.20you.20can't.20find.20code.20system and implement unknown-codesystems-cause-errors --- .../validation/ValueSetValidator.java | 4 +- .../org/hl7/fhir/utilities/Utilities.java | 14 +- .../hl7/fhir/utilities/npm/PackageHacker.java | 51 +++---- .../hl7/fhir/validation/ValidationEngine.java | 3 + .../fhir/validation/cli/model/CliContext.java | 22 ++- .../cli/services/ValidationService.java | 1 + .../hl7/fhir/validation/cli/utils/Params.java | 5 +- .../instance/InstanceValidator.java | 132 ++++++++++++------ .../tests/ValidationEngineTests.java | 8 +- 9 files changed, 163 insertions(+), 77 deletions(-) diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/terminologies/validation/ValueSetValidator.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/terminologies/validation/ValueSetValidator.java index 9315b55ab..dd8b9733a 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/terminologies/validation/ValueSetValidator.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/terminologies/validation/ValueSetValidator.java @@ -124,11 +124,9 @@ public class ValueSetValidator extends ValueSetProcessBase { } public String getMessage() { return message; - } - + } } - private ValueSet valueset; private Map inner = new HashMap<>(); private ValidationOptions options; 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 c56787430..5c117d455 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 @@ -1491,7 +1491,7 @@ public class Utilities { } public static boolean startsWithInList(String s, Collection list) { - if (s == null) { + if (s == null || list == null) { return false; } for (String l : list) { @@ -2304,4 +2304,16 @@ public class Utilities { } } + public static boolean listValueStartsWith(String s, Set list) { + if (s == null || list == null) { + return false; + } + for (String l : list) { + if (l.startsWith(s)) { + return true; + } + } + return false; + } + } diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/npm/PackageHacker.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/npm/PackageHacker.java index 2e9a45283..225bdd409 100644 --- a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/npm/PackageHacker.java +++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/npm/PackageHacker.java @@ -31,18 +31,19 @@ public class PackageHacker { public static void main(String[] args) throws FileNotFoundException, IOException { // new PackageHacker().massEdit(new File("/Users/grahamegrieve/web/hl7.org/fhir")); - new PackageHacker().edit("/Users/grahamegrieve/web/hl7.org/fhir/6.0.0-ballot1/hl7.fhir.r6.core.tgz"); - new PackageHacker().edit("/Users/grahamegrieve/web/hl7.org/fhir/6.0.0-ballot1/hl7.fhir.r6.corexml.tgz"); - new PackageHacker().edit("/Users/grahamegrieve/web/hl7.org/fhir/6.0.0-ballot1/hl7.fhir.r6.examples.tgz"); - new PackageHacker().edit("/Users/grahamegrieve/web/hl7.org/fhir/6.0.0-ballot1/hl7.fhir.r6.expansions.tgz"); - new PackageHacker().edit("/Users/grahamegrieve/web/hl7.org/fhir/6.0.0-ballot1/hl7.fhir.r6.search.tgz"); - new PackageHacker().edit("/Users/grahamegrieve/web/hl7.org/fhir/6.0.0-ballot2/hl7.fhir.r6.core.tgz"); - new PackageHacker().edit("/Users/grahamegrieve/web/hl7.org/fhir/6.0.0-ballot2/hl7.fhir.r6.corexml.tgz"); - new PackageHacker().edit("/Users/grahamegrieve/web/hl7.org/fhir/6.0.0-ballot2/hl7.fhir.r6.examples.tgz"); - new PackageHacker().edit("/Users/grahamegrieve/web/hl7.org/fhir/6.0.0-ballot2/hl7.fhir.r6.expansions.tgz"); - new PackageHacker().edit("/Users/grahamegrieve/web/hl7.org/fhir/6.0.0-ballot2/hl7.fhir.r6.search.tgz"); +// new PackageHacker().edit("/Users/grahamegrieve/web/hl7.org/fhir/6.0.0-ballot1/hl7.fhir.r6.core.tgz"); +// new PackageHacker().edit("/Users/grahamegrieve/web/hl7.org/fhir/6.0.0-ballot1/hl7.fhir.r6.corexml.tgz"); +// new PackageHacker().edit("/Users/grahamegrieve/web/hl7.org/fhir/6.0.0-ballot1/hl7.fhir.r6.examples.tgz"); +// new PackageHacker().edit("/Users/grahamegrieve/web/hl7.org/fhir/6.0.0-ballot1/hl7.fhir.r6.expansions.tgz"); +// new PackageHacker().edit("/Users/grahamegrieve/web/hl7.org/fhir/6.0.0-ballot1/hl7.fhir.r6.search.tgz"); +// new PackageHacker().edit("/Users/grahamegrieve/web/hl7.org/fhir/6.0.0-ballot2/hl7.fhir.r6.core.tgz"); +// new PackageHacker().edit("/Users/grahamegrieve/web/hl7.org/fhir/6.0.0-ballot2/hl7.fhir.r6.corexml.tgz"); +// new PackageHacker().edit("/Users/grahamegrieve/web/hl7.org/fhir/6.0.0-ballot2/hl7.fhir.r6.examples.tgz"); +// new PackageHacker().edit("/Users/grahamegrieve/web/hl7.org/fhir/6.0.0-ballot2/hl7.fhir.r6.expansions.tgz"); +// new PackageHacker().edit("/Users/grahamegrieve/web/hl7.org/fhir/6.0.0-ballot2/hl7.fhir.r6.search.tgz"); -// new PackageHacker().edit(args[0]); +// new PackageHacker().edit("/Users/grahamegrieve/web/hl7.org/fhir/us/core/v311/package.tgz", "http://hl7.org/fhir/us/core/STU3.1.1"); + new PackageHacker().edit("/Users/grahamegrieve/web/hl7.org/fhir/us/core/v700/package.tgz", "http://hl7.org/fhir/us/core/STU7"); } // private void massEdit(File dir) throws IOException { @@ -91,7 +92,7 @@ public class PackageHacker { // } // } - private void edit(String name) throws FileNotFoundException, IOException { + private void edit(String name, String path) throws FileNotFoundException, IOException { File f = ManagedFileAccess.file(name); if (!f.exists()) throw new Error("Unable to find "+f.getAbsolutePath()); @@ -107,15 +108,15 @@ public class PackageHacker { System.out.println("Altering Package "+f.getAbsolutePath()); System.out.println(nice(pck.getNpm())); - if (change(pck.getNpm())) { + if (change(pck.getNpm(), path)) { System.out.println("Revised Package"); System.out.println("======================="); System.out.println(nice(pck.getNpm())); System.out.println("======================="); -// System.out.print("save? y/n: "); -// int r = System.in.read(); -// if (r == 'y') { + System.out.print("save? y/n: "); + int r = System.in.read(); + if (r == 'y') { f.renameTo(ManagedFileAccess.file(Utilities.changeFileExt(name, ".tgz.bak"))); FileOutputStream fso = ManagedFileAccess.outStream(f); try { @@ -123,7 +124,7 @@ public class PackageHacker { } finally { fso.close(); } -// } + } } } @@ -142,13 +143,15 @@ public class PackageHacker { return JsonParser.compose(json, true); } - private boolean change(JsonObject npm) throws FileNotFoundException, IOException { - // fixVersions(npm, ver); - if (npm.has("notForPublication")) { - npm.remove("notForPublication"); - return true; - } - return false; + private boolean change(JsonObject npm, String path) throws FileNotFoundException, IOException { + npm.remove("url"); + npm.add("url", path); + return true; +// if (npm.has("notForPublication")) { +// npm.remove("notForPublication"); +// return true; +// } +// return false; } private void fixVersionInContent(Map content) { diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/ValidationEngine.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/ValidationEngine.java index a242ca2e9..9bf88787c 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/ValidationEngine.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/ValidationEngine.java @@ -226,6 +226,7 @@ public class ValidationEngine implements IValidatorResourceFetcher, IValidationP @Getter @Setter private boolean allowDoubleQuotesInFHIRPath; @Getter @Setter private boolean checkIPSCodes; @Getter @Setter private BestPracticeWarningLevel bestPracticeLevel; + @Getter @Setter private boolean unknownCodeSystemsCauseErrors; @Getter @Setter private Locale locale; @Getter @Setter private List igs = new ArrayList<>(); @Getter @Setter private List extensionDomains = new ArrayList<>(); @@ -289,6 +290,7 @@ public class ValidationEngine implements IValidatorResourceFetcher, IValidationP fhirPathEngine = other.fhirPathEngine; igLoader = other.igLoader; jurisdiction = other.jurisdiction; + unknownCodeSystemsCauseErrors = other.unknownCodeSystemsCauseErrors; } /** @@ -906,6 +908,7 @@ public class ValidationEngine implements IValidatorResourceFetcher, IValidationP if (policyAdvisor != null) { validator.setPolicyAdvisor(policyAdvisor); } + validator.setUnknownCodeSystemsCauseErrors(unknownCodeSystemsCauseErrors); return validator; } 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 f719f029b..79c604c6c 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 @@ -163,6 +163,9 @@ public class CliContext { @JsonProperty("bestPracticeLevel") private BestPracticeWarningLevel bestPracticeLevel = BestPracticeWarningLevel.Warning; + @JsonProperty("unknownCodeSystemsCauseErrors") + private boolean unknownCodeSystemsCauseErrors; + @JsonProperty("baseEngine") public String getBaseEngine() { return baseEngine; @@ -832,6 +835,7 @@ public class CliContext { Objects.equals(watchMode, that.watchMode) && Objects.equals(bestPracticeLevel, that.bestPracticeLevel) && Objects.equals(watchScanDelay, that.watchScanDelay) && + Objects.equals(unknownCodeSystemsCauseErrors, that.unknownCodeSystemsCauseErrors) && Objects.equals(watchSettleTime, that.watchSettleTime) ; } @@ -839,8 +843,8 @@ public class CliContext { public int hashCode() { return Objects.hash(baseEngine, doNative, extensions, hintAboutNonMustSupport, recursive, doDebug, assumeValidRestReferences, canDoNative, noInternalCaching, noExtensibleBindingMessages, noInvariants, displayWarnings, wantInvariantsInMessages, map, output, outputSuffix, htmlOutput, txServer, sv, txLog, txCache, mapLog, lang, srcLang, tgtLang, fhirpath, snomedCT, - targetVer, igs, questionnaireMode, level, profiles, sources, inputs, mode, locale, locations, crumbTrails, forPublication, showTimes, allowExampleUrls, outputStyle, jurisdiction, noUnicodeBiDiControlChars, watchMode, watchScanDelay, watchSettleTime, bestPracticeLevel, - htmlInMarkdownCheck, allowDoubleQuotesInFHIRPath, checkIPSCodes); + targetVer, igs, questionnaireMode, level, profiles, sources, inputs, mode, locale, locations, crumbTrails, forPublication, showTimes, allowExampleUrls, outputStyle, jurisdiction, noUnicodeBiDiControlChars, + watchMode, watchScanDelay, watchSettleTime, bestPracticeLevel, unknownCodeSystemsCauseErrors, htmlInMarkdownCheck, allowDoubleQuotesInFHIRPath, checkIPSCodes); } @Override @@ -899,6 +903,7 @@ public class CliContext { ", bestPracticeLevel=" + bestPracticeLevel + ", watchSettleTime=" + watchSettleTime + ", watchScanDelay=" + watchScanDelay + + ", unknownCodeSystemsCauseErrors=" + unknownCodeSystemsCauseErrors + '}'; } @@ -956,4 +961,17 @@ public class CliContext { return this; } + + @JsonProperty("unknownCodeSystemsCauseErrors") + public boolean isUnknownCodeSystemsCauseErrors() { + return unknownCodeSystemsCauseErrors; + } + + + @JsonProperty("unknownCodeSystemsCauseErrors") + public void setUnknownCodeSystemsCauseErrors(boolean unknownCodeSystemsCauseErrors) { + this.unknownCodeSystemsCauseErrors = unknownCodeSystemsCauseErrors; + } + + } \ No newline at end of file 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 fcdea6386..61d4b7d5f 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 @@ -581,6 +581,7 @@ public class ValidationService { } validationEngine.getBundleValidationRules().addAll(cliContext.getBundleValidationRules()); validationEngine.setJurisdiction(CodeSystemUtilities.readCoding(cliContext.getJurisdiction())); + validationEngine.setUnknownCodeSystemsCauseErrors(cliContext.isUnknownCodeSystemsCauseErrors()); TerminologyCache.setNoCaching(cliContext.isNoInternalCaching()); validationEngine.prepare(); // generate any missing snapshots System.out.println(" go (" + timeTracker.milestone() + ")"); 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 23136344d..0983d0072 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 @@ -94,8 +94,7 @@ public class Params { public static final String DISABLE_DEFAULT_RESOURCE_FETCHER = "-disable-default-resource-fetcher"; public static final String CHECK_IPS_CODES = "-check-ips-codes"; public static final String BEST_PRACTICE = "-best-practice"; - - + public static final String UNKNOWN_CODESYSTEMS_CAUSE_ERROR = "-unknown-codesystems-cause-errors"; public static final String RUN_TESTS = "-run-tests"; @@ -320,6 +319,8 @@ public class Params { cliContext.setCrumbTrails(true); } else if (args[i].equals(FOR_PUBLICATION)) { cliContext.setForPublication(true); + } else if (args[i].equals(UNKNOWN_CODESYSTEMS_CAUSE_ERROR)) { + cliContext.setUnknownCodeSystemsCauseErrors(true); } else if (args[i].equals(VERBOSE)) { cliContext.setCrumbTrails(true); } else if (args[i].equals(ALLOW_EXAMPLE_URLS)) { 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 071efc120..dbc8eb164 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 @@ -598,6 +598,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat private boolean example ; private IDigitalSignatureServices signatureServices; private ContextUtilities cu; + private boolean unknownCodeSystemsCauseErrors; public InstanceValidator(@Nonnull IWorkerContext theContext, @Nonnull IEvaluationContext hostServices, @Nonnull XVerExtensionManager xverManager) { super(theContext, xverManager, false); @@ -1125,7 +1126,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat timeTracker.tx(t, "vc "+system+"#"+code+" '"+display+"'"); if (s == null) return true; - ok = processTxIssues(errors, s, element, path, null, "no binding on code", false, null) & ok; + ok = processTxIssues(errors, s, element, path, false, null, null) & ok; if (s.isOk()) { if (s.getMessage() != null && !s.messageIsInIssues()) { @@ -1381,7 +1382,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat if (cc.hasCoding()) { long t = System.nanoTime(); ValidationResult vr = checkCodeOnServer(stack, null, cc); - bh.see(processTxIssues(errors, vr, element, path, org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity.INFORMATION, null, false, null)); + bh.see(processTxIssues(errors, vr, element, path, false, null, null)); timeTracker.tx(t, "vc " + cc.toString()); } } catch (CheckCodeOnServerException e) { @@ -1465,7 +1466,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat } else { checked.set(true); ValidationResult vr = checkCodeOnServer(stack, valueset, cc); - bh.see(processTxIssues(errors, vr, element, path, notFoundSeverityForBinding(strength), notFoundSeverityNoteForBinding(strength), false, vsRef)); + bh.see(processTxIssues(errors, vr, element, path, false, vsRef, strength)); if (!vr.isOk()) { bindingsOk = false; if (vr.getErrorClass() != null && vr.getErrorClass() == TerminologyServiceErrorClass.NOSERVICE) { @@ -1533,33 +1534,34 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat return checkDisp; } - private String notFoundSeverityNoteForBinding(BindingStrength strength) { - if (strength == BindingStrength.REQUIRED) { - return "error because this is a required binding"; - } else { - return null; - } - } +// private String notFoundSeverityNoteForBinding(BindingStrength strength, Set systems) { +// if (strength == BindingStrength.REQUIRED && +// (Utilities.listValueStartsWith("http://hl7.org/fhir", systems) || Utilities.listValueStartsWith("http://terminology.hl7.org", systems))) { +// return "error because this is a required binding to an HL7 code system"; +// } else { +// return null; +// } +// } +// +// /** +// * The terminology server will report an error for an unknown code system or version, or a dependent valueset +// * +// * but we only care for validation if the binding strength is strong enough. +// * @param binding +// * @return +// */ +// private org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity notFoundSeverityForBinding(BindingStrength strength, String systems) { +// if (strength == BindingStrength.REQUIRED && +// (Utilities.listValueStartsWith("http://hl7.org/fhir", systems) || Utilities.listValueStartsWith("http://terminology.hl7.org", systems))) { +// return org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity.ERROR; +// } else if (strength == BindingStrength.REQUIRED || strength == BindingStrength.EXTENSIBLE) { +// return org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity.WARNING; +// } else { +// return org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity.INFORMATION; +// } +// } - /** - * The terminology server will report an error for an unknown code system or version, or a dependent valueset - * - * but we only care for validation if the binding strength is strong enough. - * @param binding - * @return - */ - private org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity notFoundSeverityForBinding(BindingStrength strength) { - if (strength == BindingStrength.REQUIRED) { - return org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity.ERROR; - } else if (strength == BindingStrength.EXTENSIBLE) { - return org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity.WARNING; - } else { - return org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity.INFORMATION; - } - } - - private boolean processTxIssues(List errors, ValidationResult vr, Element element, String path, - org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity notFoundLevel, String notFoundNote, boolean ignoreCantInfer, String vsurl) { + private boolean processTxIssues(List errors, ValidationResult vr, Element element, String path, boolean ignoreCantInfer, String vsurl, BindingStrength bs) { boolean ok = true; if (vr != null) { for (OperationOutcomeIssueComponent iss : vr.getIssues()) { @@ -1567,12 +1569,35 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat && !iss.getDetails().hasCoding("http://hl7.org/fhir/tools/CodeSystem/tx-issue-type", "this-code-not-in-vs") && !(ignoreCantInfer || iss.getDetails().hasCoding("http://hl7.org/fhir/tools/CodeSystem/tx-issue-type", "cannot-infer"))) { OperationOutcomeIssueComponent i = iss.copy(); - if (i.getDetails().hasCoding("http://hl7.org/fhir/tools/CodeSystem/tx-issue-type", "not-found")) { - if (notFoundLevel != null && i.getSeverity().isHigherThan(notFoundLevel) || (vsurl != null && i.getDetails().getText().contains(vsurl))) { - i.setSeverity(notFoundLevel); + if (i.getDetails().hasCoding("http://hl7.org/fhir/tools/CodeSystem/tx-issue-type", "not-found")) { + String msg = iss.getDetails().getText(); + boolean isHL7 = msg == null ? false : msg.contains("http://hl7.org/fhir") || msg.contains("http://terminology.hl7.org"); + org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity notFoundLevel = null; + String notFoundNote = null; + if (bs == null) { + notFoundLevel = org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity.WARNING; + notFoundNote = null; // "binding=null"; + } else if (bs == BindingStrength.REQUIRED && isHL7) { + notFoundLevel = org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity.ERROR; + notFoundNote = "error because this is a required binding to an HL7 code system"; + } else if (bs == BindingStrength.REQUIRED && unknownCodeSystemsCauseErrors) { + notFoundLevel = org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity.ERROR; + notFoundNote = "error because this is a required binding"; + } else if (bs == BindingStrength.REQUIRED) { + notFoundLevel = org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity.WARNING; + notFoundNote = null; // "binding=required"; + } else if (bs == BindingStrength.EXTENSIBLE) { + notFoundLevel = org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity.WARNING; + notFoundNote = null; // "binding=extensible"; + } else { + notFoundLevel = org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity.WARNING; + notFoundNote = null; // "binding="+bs.toCode(); } - if (notFoundNote != null) { - i.getDetails().setText(i.getDetails().getText()+" ("+notFoundNote+")"); + if (notFoundLevel != null && i.getSeverity().isHigherThan(notFoundLevel)) { // && (vsurl != null && i.getDetails().getText().contains(vsurl))) { + i.setSeverity(notFoundLevel); + if (notFoundNote != null) { + i.getDetails().setText(i.getDetails().getText()+" ("+notFoundNote+")"); + } } } if (baseOptions.isDisplayWarningMode() && i.getSeverity() == org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity.ERROR && i.getDetails().hasCoding("http://hl7.org/fhir/tools/CodeSystem/tx-issue-type", "invalid-display")) { @@ -1592,7 +1617,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat boolean ok = true; if (isNotBlank(nextCoding.getCode()) && isNotBlank(nextCoding.getSystem()) && context.supportsSystem(nextCoding.getSystem(), baseOptions.getFhirVersion())) { ValidationResult vr = checkCodeOnServer(stack, valueset, nextCoding); - ok = processTxIssues(errors, vr, element, path, null, "ex-checkBindings", false, null) && ok; + ok = processTxIssues(errors, vr, element, path, false, null, null) && ok; if (vr.getSeverity() != null && !vr.messageIsInIssues()) { if (vr.getSeverity() == IssueSeverity.INFORMATION) { @@ -1721,7 +1746,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat if (strength == BindingStrength.REQUIRED) { removeTrackedMessagesForLocation(errors, element, path); } - ok = processTxIssues(errors, vr, element, path, notFoundSeverityForBinding(strength), notFoundSeverityNoteForBinding(strength), false, vsRef) && ok; + ok = processTxIssues(errors, vr, element, path, false, vsRef, strength) && ok; timeTracker.tx(t, "vc "+system+"#"+code+" '"+display+"'"); if (vr != null && !vr.isOk()) { if (vr.IsNoService()) @@ -1766,6 +1791,21 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat return ok; } + private Set getUnknownSystems(ValidationResult vr) { + if (vr == null) { + return null; + } + if (vr.getUnknownSystems() != null && !vr.getUnknownSystems().isEmpty()) { + return vr.getUnknownSystems(); + } + if (vr.getSystem() != null) { + Set set = new HashSet(); + set.add(vr.getSystem()); + return set; + } + return null; + } + private boolean convertCDACodeToCodeableConcept(List errors, String path, Element element, StructureDefinition logical, CodeableConcept cc) { boolean ok = true; cc.setText(element.getNamedChildValue("originalText", false)); @@ -1851,7 +1891,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat try { long t = System.nanoTime(); ValidationResult vr = checkCodeOnServer(stack, valueset, cc); - ok = processTxIssues(errors, vr, element, path, null, "ex-checkMaxValueSet", false, maxVSUrl) && ok; + ok = processTxIssues(errors, vr, element, path, false, maxVSUrl, null) && ok; timeTracker.tx(t, "vc "+cc.toString()); if (!vr.isOk()) { if (vr.getErrorClass() != null && vr.getErrorClass().isInfrastructure()) @@ -1890,7 +1930,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat try { long t = System.nanoTime(); ValidationResult vr = checkCodeOnServer(stack, valueset, c); - ok = processTxIssues(errors, vr, element, path, null, "ex-checkMaxValueSet-2", false, maxVSUrl) && ok; + ok = processTxIssues(errors, vr, element, path, false, maxVSUrl, null) && ok; timeTracker.tx(t, "vc "+c.getSystem()+"#"+c.getCode()+" '"+c.getDisplay()+"'"); if (!vr.isOk()) { @@ -1921,7 +1961,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat try { long t = System.nanoTime(); ValidationResult vr = checkCodeOnServer(stack, valueset, value, baseOptions); - ok = processTxIssues(errors, vr, element, path, null, "ex-checkMaxValueSet-3", false, maxVSUrl) && ok; + ok = processTxIssues(errors, vr, element, path, false, maxVSUrl, null) && ok; timeTracker.tx(t, "vc "+value); if (!vr.isOk()) { if (vr.getErrorClass() != null && vr.getErrorClass().isInfrastructure()) @@ -2045,7 +2085,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat checked.set(true); vr = checkCodeOnServer(stack, valueset, c); } - ok = processTxIssues(errors, vr, element, path, notFoundSeverityForBinding(strength), notFoundSeverityNoteForBinding(strength), strength == BindingStrength.EXTENSIBLE, vsRef) && ok; + ok = processTxIssues(errors, vr, element, path, strength == BindingStrength.EXTENSIBLE, vsRef, strength) && ok; timeTracker.tx(t, "vc "+c.getSystem()+"#"+c.getCode()+" '"+c.getDisplay()+"'"); if (strength == BindingStrength.REQUIRED) { @@ -3510,7 +3550,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat } vr = checkCodeOnServer(stack, vs, value, options); } - ok = processTxIssues(errors, vr, element, path, notFoundSeverityForBinding(binding.getStrength()), notFoundSeverityNoteForBinding(binding.getStrength()), binding.getStrength() != BindingStrength.REQUIRED, binding.getValueSet()) && ok; + ok = processTxIssues(errors, vr, element, path, binding.getStrength() != BindingStrength.REQUIRED, binding.getValueSet(), binding.getStrength()) && ok; timeTracker.tx(t, "vc "+value+""); if (binding.getStrength() == BindingStrength.REQUIRED) { @@ -7791,4 +7831,14 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat this.fetcher = value; return this; } + + public boolean isUnknownCodeSystemsCauseErrors() { + return unknownCodeSystemsCauseErrors; + } + + public void setUnknownCodeSystemsCauseErrors(boolean unknownCodeSystemsCauseErrors) { + this.unknownCodeSystemsCauseErrors = unknownCodeSystemsCauseErrors; + } + + } diff --git a/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/validation/tests/ValidationEngineTests.java b/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/validation/tests/ValidationEngineTests.java index bd27a6f41..320f1dd30 100644 --- a/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/validation/tests/ValidationEngineTests.java +++ b/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/validation/tests/ValidationEngineTests.java @@ -247,9 +247,9 @@ public class ValidationEngineTests { Assertions.assertTrue(checkOutcomes("testObs102", op, "Observation.text.div null error/invalid: Wrong namespace on the XHTML ('null', should be 'http://www.w3.org/1999/xhtml')\n"+ "Observation.category null information/business-rule: Reference to experimental CodeSystem http://hl7.org/fhir/observation-category\n"+ - "Observation.code.coding[2].system null information/not-found: A definition for CodeSystem 'http://acme.org/devices/clinical-codes' could not be found, so the code cannot be validated\n"+ "Observation null warning/invalid: Best Practice Recommendation: In general, all observations should have a performer\n"+ - "Observation null warning/invalid: Best Practice Recommendation: In general, all observations should have an effective[x] ()")); + "Observation null warning/invalid: Best Practice Recommendation: In general, all observations should have an effective[x] ()\n"+ + "Observation.code.coding[2].system null warning/not-found: A definition for CodeSystem 'http://acme.org/devices/clinical-codes' could not be found, so the code cannot be validated")); verifyNoTerminologyRequests(logger); } @@ -265,8 +265,8 @@ public class ValidationEngineTests { System.out.println(" .. load USCore"); OperationOutcome op = ve.validate(FhirFormat.XML, TestingUtilities.loadTestResourceStream("validator", "observation301.xml"), null); Assertions.assertTrue(checkOutcomes("test301", op, - "Observation.code.coding[3].system null information/not-found: A definition for CodeSystem 'http://acme.org/devices/clinical-codes' could not be found, so the code cannot be validated\n"+ - "Observation null warning/invalid: Best Practice Recommendation: In general, all observations should have a performer")); + "Observation null warning/invalid: Best Practice Recommendation: In general, all observations should have a performer\n"+ + "Observation.code.coding[3].system null warning/not-found: A definition for CodeSystem 'http://acme.org/devices/clinical-codes' could not be found, so the code cannot be validated")); verifyNoTerminologyRequests(logger); } From 51934de457b17331df7c6453d813f0a83f7b949f Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Mon, 9 Sep 2024 17:47:33 +0800 Subject: [PATCH 17/50] Fix bug processing value set includes / excludes that are just value sets (no system value) --- .../fhir/r5/context/BaseWorkerContext.java | 8 ++- .../expansion/ValueSetExpander.java | 53 ++++++++++--------- 2 files changed, 33 insertions(+), 28 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 e517398be..e33cc0bfa 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 @@ -934,10 +934,14 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte throw new Error(formatMessage(I18nConstants.NO_VALUE_SET_IN_URL)); } for (ConceptSetComponent inc : vs.getCompose().getInclude()) { - codeSystemsUsed.add(inc.getSystem()); + if (inc.hasSystem()) { + codeSystemsUsed.add(inc.getSystem()); + } } for (ConceptSetComponent inc : vs.getCompose().getExclude()) { - codeSystemsUsed.add(inc.getSystem()); + if (inc.hasSystem()) { + codeSystemsUsed.add(inc.getSystem()); + } } CacheToken cacheToken = txCache.generateExpandToken(vs, hierarchical); diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/terminologies/expansion/ValueSetExpander.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/terminologies/expansion/ValueSetExpander.java index 28058becb..7e1cfbbf7 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/terminologies/expansion/ValueSetExpander.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/terminologies/expansion/ValueSetExpander.java @@ -606,33 +606,35 @@ public class ValueSetExpander extends ValueSetProcessBase { excludeCodes(wc, importValueSetForExclude(wc, imp.getValue(), exp, expParams, false, vs).getExpansion()); } - CodeSystem cs = context.fetchSupplementedCodeSystem(exc.getSystem()); - if ((cs == null || cs.getContent() != CodeSystemContentMode.COMPLETE) && context.supportsSystem(exc.getSystem(), opContext.getOptions().getFhirVersion())) { - ValueSetExpansionOutcome vse = context.expandVS(exc, false, false); - ValueSet valueset = vse.getValueset(); - if (valueset == null) - throw failTSE("Error Expanding ValueSet: "+vse.getError()); - excludeCodes(wc, valueset.getExpansion()); - return; - } - - for (ConceptReferenceComponent c : exc.getConcept()) { - excludeCode(wc, exc.getSystem(), c.getCode()); - } - - if (exc.getFilter().size() > 0) { - if (cs.getContent() == CodeSystemContentMode.FRAGMENT) { - addFragmentWarning(exp, cs); + if (exc.hasSystem()) { + CodeSystem cs = context.fetchSupplementedCodeSystem(exc.getSystem()); + if ((cs == null || cs.getContent() != CodeSystemContentMode.COMPLETE) && context.supportsSystem(exc.getSystem(), opContext.getOptions().getFhirVersion())) { + ValueSetExpansionOutcome vse = context.expandVS(exc, false, false); + ValueSet valueset = vse.getValueset(); + if (valueset == null) + throw failTSE("Error Expanding ValueSet: "+vse.getError()); + excludeCodes(wc, valueset.getExpansion()); + return; } - List filters = new ArrayList<>(); - for (int i = 1; i < exc.getFilter().size(); i++) { - WorkingContext wc1 = new WorkingContext(); - filters.add(wc1); - processFilter(exc, exp, expParams, null, cs, false, exc.getFilter().get(i), wc1, null, true); + + for (ConceptReferenceComponent c : exc.getConcept()) { + excludeCode(wc, exc.getSystem(), c.getCode()); + } + + if (exc.getFilter().size() > 0) { + if (cs.getContent() == CodeSystemContentMode.FRAGMENT) { + addFragmentWarning(exp, cs); + } + List filters = new ArrayList<>(); + for (int i = 1; i < exc.getFilter().size(); i++) { + WorkingContext wc1 = new WorkingContext(); + filters.add(wc1); + processFilter(exc, exp, expParams, null, cs, false, exc.getFilter().get(i), wc1, null, true); + } + ConceptSetFilterComponent fc = exc.getFilter().get(0); + WorkingContext wc1 = dwc; + processFilter(exc, exp, expParams, null, cs, false, fc, wc1, filters, true); } - ConceptSetFilterComponent fc = exc.getFilter().get(0); - WorkingContext wc1 = dwc; - processFilter(exc, exp, expParams, null, cs, false, fc, wc1, filters, true); } } @@ -728,7 +730,6 @@ public class ValueSetExpander extends ValueSetProcessBase { expParams = makeDefaultExpansion(); altCodeParams.seeParameters(expParams); altCodeParams.seeValueSet(source); - source.checkNoModifiers("ValueSet", "expanding"); focus = source.copy(); focus.setIdBase(null); From 810f4b8e3186a392f7b78a29738c767e3c4125c0 Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Mon, 9 Sep 2024 17:48:01 +0800 Subject: [PATCH 18/50] fix value set rendering creating wrong references --- .../fhir/r5/renderers/ValueSetRenderer.java | 45 +++++++++---------- 1 file changed, 22 insertions(+), 23 deletions(-) diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/ValueSetRenderer.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/ValueSetRenderer.java index eb303d742..4a78a67c8 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/ValueSetRenderer.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/ValueSetRenderer.java @@ -754,16 +754,7 @@ public class ValueSetRenderer extends TerminologyRenderer { if (ref == null) { ref = (String) cs.getWebPath(); } - if (ref == null && cs.hasUserData("webroot")) { - ref = (String) cs.getUserData("webroot"); - } - if (ref == null) { - return "?ngen-14?.html"; - } - if (!ref.contains(".html")) { - ref = ref + ".html"; - } - return ref.replace("\\", "/"); + return ref == null ? null : ref.replace("\\", "/"); } private void scanForDesignations(ValueSetExpansionContainsComponent c, List langs, Map designations) { @@ -922,14 +913,18 @@ public class ValueSetRenderer extends TerminologyRenderer { td.addText(code); } else { String href = context.fixReference(getCsRef(e)); - if (href.contains("#")) - href = href + "-"+Utilities.nmtokenize(code); - else - href = href + "#"+e.getId()+"-"+Utilities.nmtokenize(code); - if (isAbstract) - td.ah(context.prefixLocalHref(href)).setAttribute("title", context.formatPhrase(RenderingContext.VS_ABSTRACT_CODE_HINT)).i().addText(code); - else - td.ah(context.prefixLocalHref(href)).addText(code); + if (href == null) { + td.code().tx(code); + } else { + if (href.contains("#")) + href = href + "-"+Utilities.nmtokenize(code); + else + href = href + "#"+e.getId()+"-"+Utilities.nmtokenize(code); + if (isAbstract) + td.ah(context.prefixLocalHref(href)).setAttribute("title", context.formatPhrase(RenderingContext.VS_ABSTRACT_CODE_HINT)).i().addText(code); + else + td.ah(context.prefixLocalHref(href)).addText(code); + } } } @@ -1247,11 +1242,15 @@ public class ValueSetRenderer extends TerminologyRenderer { wli.tx(f.getProperty()+" "+describe(f.getOp())+" "); if (e != null && codeExistsInValueSet(e, f.getValue())) { String href = getContext().fixReference(getCsRef(e)); - if (href.contains("#")) - href = href + "-"+Utilities.nmtokenize(f.getValue()); - else - href = href + "#"+e.getId()+"-"+Utilities.nmtokenize(f.getValue()); - wli.ah(context.prefixLocalHref(href)).addText(f.getValue()); + if (href == null) { + wli.code().tx(f.getValue()); + } else { + if (href.contains("#")) + href = href + "-"+Utilities.nmtokenize(f.getValue()); + else + href = href + "#"+e.getId()+"-"+Utilities.nmtokenize(f.getValue()); + wli.ah(context.prefixLocalHref(href)).addText(f.getValue()); + } } else if (inc.hasSystem()) { wli.addText(f.getValue()); ValidationResult vr = getContext().getWorker().validateCode(getContext().getTerminologyServiceOptions(), inc.getSystem(), inc.getVersion(), f.getValue(), null); From cfdd1f93803ecffdb7c4f7aab619bc927f1db3a3 Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Mon, 9 Sep 2024 17:48:46 +0800 Subject: [PATCH 19/50] Update SQL-On-FHIR implementation for latest cases, and clone test cases to general test care repository --- .../r5/renderers/utils/RenderingContext.java | 3 + .../org/hl7/fhir/r5/utils/sql/Runner.java | 65 ++++++--- .../hl7/fhir/r5/utils/sql/StorageJson.java | 17 +-- .../org/hl7/fhir/r5/utils/sql/Validator.java | 131 ++++++++++++------ .../org/hl7/fhir/r5/sql/SQLOnFhirTests.java | 29 ++-- 5 files changed, 157 insertions(+), 88 deletions(-) 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 572523a1e..687d7c672 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 @@ -554,6 +554,9 @@ public class RenderingContext extends RenderingI18nContext { } public String fixReference(String ref) { + if (ref == null) { + return null; + } if (!Utilities.isAbsoluteUrl(ref)) { return (localPrefix == null ? "" : localPrefix)+ref; } 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 432fff492..aa5d8b4e1 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 @@ -103,7 +103,7 @@ public class Runner implements IEvaluationContext { for (JsonObject w : vd.getJsonObjects("where")) { String expr = w.asString("path"); ExpressionNode node = fpe.parse(expr); - boolean pass = fpe.evaluateToBoolean(null, b, b, b, node); + boolean pass = fpe.evaluateToBoolean(vd, b, b, b, node); if (!pass) { ok = false; break; @@ -114,7 +114,7 @@ public class Runner implements IEvaluationContext { rows.add(new ArrayList()); for (JsonObject select : vd.getJsonObjects("select")) { - executeSelect(select, b, rows); + executeSelect(vd, select, b, rows); } for (List row : rows) { storage.addRow(store, row); @@ -124,14 +124,14 @@ public class Runner implements IEvaluationContext { storage.finish(store); } - private void executeSelect(JsonObject select, Base b, List> rows) { + private void executeSelect(JsonObject vd, JsonObject select, Base b, List> rows) { List focus = new ArrayList<>(); if (select.has("forEach")) { - focus.addAll(executeForEach(select, b)); + focus.addAll(executeForEach(vd, select, b)); } else if (select.has("forEachOrNull")) { - focus.addAll(executeForEachOrNull(select, b)); + focus.addAll(executeForEachOrNull(vd, select, b)); if (focus.isEmpty()) { List columns = (List) select.getUserData("columns"); for (List row : rows) { @@ -159,20 +159,20 @@ public class Runner implements IEvaluationContext { List> rowsToAdd = cloneRows(tempRows); for (JsonObject column : select.getJsonObjects("column")) { - executeColumn(column, f, rowsToAdd); + executeColumn(vd, column, f, rowsToAdd); } for (JsonObject sub : select.getJsonObjects("select")) { - executeSelect(sub, f, rowsToAdd); + executeSelect(vd, sub, f, rowsToAdd); } - executeUnionAll(select.getJsonObjects("unionAll"), f, rowsToAdd); + executeUnionAll(vd, select.getJsonObjects("unionAll"), f, rowsToAdd); rows.addAll(rowsToAdd); } } - private void executeUnionAll(List unionList, Base b, List> rows) { + private void executeUnionAll(JsonObject vd, List unionList, Base b, List> rows) { if (unionList.isEmpty()) { return; } @@ -183,7 +183,7 @@ public class Runner implements IEvaluationContext { for (JsonObject union : unionList) { List> tempRows = new ArrayList<>(); tempRows.addAll(sourceRows); - executeSelect(union, b, tempRows); + executeSelect(vd, union, b, tempRows); rows.addAll(tempRows); } } @@ -204,25 +204,25 @@ public class Runner implements IEvaluationContext { return list; } - private List executeForEach(JsonObject focus, Base b) { + private List executeForEach(JsonObject vd, JsonObject focus, Base b) { ExpressionNode n = (ExpressionNode) focus.getUserData("forEach"); List result = new ArrayList<>(); - result.addAll(fpe.evaluate(b, n)); + result.addAll(fpe.evaluate(vd, b, n)); return result; } - private List executeForEachOrNull(JsonObject focus, Base b) { + private List executeForEachOrNull(JsonObject vd, JsonObject focus, Base b) { ExpressionNode n = (ExpressionNode) focus.getUserData("forEachOrNull"); List result = new ArrayList<>(); - result.addAll(fpe.evaluate(b, n)); + result.addAll(fpe.evaluate(vd, b, n)); return result; } - private void executeColumn(JsonObject column, Base b, List> rows) { + private void executeColumn(JsonObject vd, JsonObject column, Base b, List> rows) { ExpressionNode n = (ExpressionNode) column.getUserData("path"); List bl2 = new ArrayList<>(); if (b != null) { - bl2.addAll(fpe.evaluate(b, n)); + bl2.addAll(fpe.evaluate(vd, b, n)); } Column col = (Column) column.getUserData("column"); if (col == null) { @@ -344,14 +344,43 @@ public class Runner implements IEvaluationContext { @Override public List resolveConstant(FHIRPathEngine engine, Object appContext, String name, boolean beforeContext, boolean explicitConstant) throws PathEngineException { - throw new Error("Not implemented yet: resolveConstant"); + List list = new ArrayList(); + if (explicitConstant) { + JsonObject vd = (JsonObject) appContext; + JsonObject constant = findConstant(vd, name); + if (constant != null) { + Base b = (Base) constant.getUserData("value"); + if (b != null) { + list.add(b); + } + } + } + return list; } @Override public TypeDetails resolveConstantType(FHIRPathEngine engine, Object appContext, String name, boolean explicitConstant) throws PathEngineException { - throw new Error("Not implemented yet: resolveConstantType"); + if (explicitConstant) { + JsonObject vd = (JsonObject) appContext; + JsonObject constant = findConstant(vd, name.substring(1)); + if (constant != null) { + Base b = (Base) constant.getUserData("value"); + if (b != null) { + return new TypeDetails(CollectionStatus.SINGLETON, b.fhirType()); + } + } + } + return null; } + private JsonObject findConstant(JsonObject vd, String name) { + for (JsonObject o : vd.getJsonObjects("constant")) { + if (name.equals(o.asString("name"))) { + return o; + } + } + return null; + } @Override public boolean log(String argument, List focus) { throw new Error("Not implemented yet: log"); 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 d0e3aaeed..d76404c03 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 @@ -2,6 +2,7 @@ package org.hl7.fhir.r5.utils.sql; import java.util.List; +import org.hl7.fhir.exceptions.FHIRException; import org.hl7.fhir.r5.model.Base; import org.hl7.fhir.utilities.json.model.JsonArray; import org.hl7.fhir.utilities.json.model.JsonBoolean; @@ -33,16 +34,16 @@ public class StorageJson implements Storage { JsonObject row = new JsonObject(); rows.add(row); for (Cell cell : cells) { - if (cell.getValues().size() == 0) { - row.add(cell.getColumn().getName(), new JsonNull()); - } else if (cell.getValues().size() == 1) { - row.add(cell.getColumn().getName(), makeJsonNode(cell.getValues().get(0))); - } else { + if (cell.getColumn().isColl() || cell.getValues().size() > 1) { JsonArray arr = new JsonArray(); - row.add(cell.getColumn().getName(), arr); + row.add(cell.getColumn().getName(), arr); for (Value value : cell.getValues()) { arr.add(makeJsonNode(value)); - } + } + } else if (cell.getValues().size() == 0) { + row.add(cell.getColumn().getName(), new JsonNull()); + } else { + row.add(cell.getColumn().getName(), makeJsonNode(cell.getValues().get(0))); } } } @@ -87,7 +88,7 @@ public class StorageJson implements Storage { @Override public String getKeyForSourceResource(Base res) { - return res.getIdBase(); + return res.fhirType()+"/"+res.getIdBase(); } @Override 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 669fa32de..00c862b5d 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 @@ -11,6 +11,27 @@ import org.hl7.fhir.r5.context.IWorkerContext; import org.hl7.fhir.r5.fhirpath.ExpressionNode; import org.hl7.fhir.r5.fhirpath.FHIRPathEngine; import org.hl7.fhir.r5.fhirpath.TypeDetails; +import org.hl7.fhir.r5.formats.JsonParser; +import org.hl7.fhir.r5.model.Base64BinaryType; +import org.hl7.fhir.r5.model.BooleanType; +import org.hl7.fhir.r5.model.CanonicalType; +import org.hl7.fhir.r5.model.CodeType; +import org.hl7.fhir.r5.model.DateTimeType; +import org.hl7.fhir.r5.model.DateType; +import org.hl7.fhir.r5.model.DecimalType; +import org.hl7.fhir.r5.model.IdType; +import org.hl7.fhir.r5.model.InstantType; +import org.hl7.fhir.r5.model.Integer64Type; +import org.hl7.fhir.r5.model.IntegerType; +import org.hl7.fhir.r5.model.OidType; +import org.hl7.fhir.r5.model.PositiveIntType; +import org.hl7.fhir.r5.model.PrimitiveType; +import org.hl7.fhir.r5.model.StringType; +import org.hl7.fhir.r5.model.TimeType; +import org.hl7.fhir.r5.model.UnsignedIntType; +import org.hl7.fhir.r5.model.UriType; +import org.hl7.fhir.r5.model.UrlType; +import org.hl7.fhir.r5.model.UuidType; import org.hl7.fhir.r5.fhirpath.ExpressionNode.CollectionStatus; import org.hl7.fhir.r5.fhirpath.FHIRPathEngine.IssueMessage; import org.hl7.fhir.utilities.Utilities; @@ -99,7 +120,7 @@ public class Validator { i = 0; if (checkAllObjects(path, viewDefinition, "where")) { for (JsonObject where : viewDefinition.getJsonObjects("where")) { - checkWhere(path+".where["+i+"]", where); + checkWhere(viewDefinition, path+".where["+i+"]", where); i++; } } @@ -108,7 +129,7 @@ public class Validator { i = 0; if (checkAllObjects(path, viewDefinition, "select")) { for (JsonObject select : viewDefinition.getJsonObjects("select")) { - columns.addAll(checkSelect(path+".select["+i+"]", select, t)); + columns.addAll(checkSelect(viewDefinition, path+".select["+i+"]", select, t)); i++; } if (i == 0) { @@ -119,15 +140,15 @@ public class Validator { } } - private List checkSelect(String path, JsonObject select, TypeDetails t) { + private List checkSelect(JsonObject vd, 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); + t = checkForEach(vd, path, select, select.get("forEach"), t); } else if (select.has("forEachOrNull")) { - t = checkForEachOrNull(path, select, select.get("forEachOrNull"), t); + t = checkForEachOrNull(vd, path, select, select.get("forEachOrNull"), t); } if (t != null) { @@ -142,7 +163,7 @@ public class Validator { if (!(e instanceof JsonObject)) { error(path+".column["+i+"]", a, "column["+i+"] is a "+e.type().toName()+" not an object", IssueType.INVALID); } else { - columns.add(checkColumn(path+".column["+i+"]", (JsonObject) e, t)); + columns.add(checkColumn(vd, path+".column["+i+"]", (JsonObject) e, t)); } } } @@ -158,14 +179,14 @@ public class Validator { if (!(e instanceof JsonObject)) { error(path+".select["+i+"]", e, "select["+i+"] is not an object", IssueType.INVALID); } else { - columns.addAll(checkSelect(path+".select["+i+"]", (JsonObject) e, t)); + columns.addAll(checkSelect(vd, path+".select["+i+"]", (JsonObject) e, t)); } } } } if (select.has("unionAll")) { - columns.addAll(checkUnion(path, select, select.get("unionAll"), t)); + columns.addAll(checkUnion(vd, path, select, select.get("unionAll"), t)); } if (columns.isEmpty()) { error(path, select, "The select has no columns or selects", IssueType.REQUIRED); @@ -191,7 +212,7 @@ public class Validator { } } - private List checkUnion(String path, JsonObject focus, JsonElement expression, TypeDetails t) { + private List checkUnion(JsonObject vd, String path, JsonObject focus, JsonElement expression, TypeDetails t) { JsonElement a = focus.get("unionAll"); if (!(a instanceof JsonArray)) { error(path+".unionAll", a, "union is not an array", IssueType.INVALID); @@ -203,7 +224,7 @@ public class Validator { if (!(e instanceof JsonObject)) { error(path+".unionAll["+i+"]", e, "unionAll["+i+"] is not an object", IssueType.INVALID); } else { - unionColumns.add(checkSelect(path+".unionAll["+i+"]", (JsonObject) e, t)); + unionColumns.add(checkSelect(vd, path+".unionAll["+i+"]", (JsonObject) e, t)); } i++; } @@ -242,7 +263,7 @@ public class Validator { } } - private Column checkColumn(String path, JsonObject column, TypeDetails t) { + private Column checkColumn(JsonObject vd, String path, JsonObject column, TypeDetails t) { checkProperties(column, path, "path", "name", "description", "collection", "type", "tag"); if (!column.has("path")) { @@ -260,7 +281,7 @@ public class Validator { try { node = fpe.parse(expr); column.setUserData("path", node); - td = fpe.checkOnTypes(null, resourceName, t, node, warnings); + td = fpe.checkOnTypes(vd, resourceName, t, node, warnings); } catch (Exception e) { error(path, expression, e.getMessage(), IssueType.INVALID); } @@ -296,25 +317,31 @@ public class Validator { // ok, name is sorted! if (columnName != null) { column.setUserData("name", columnName); - boolean isColl = (td.getCollectionStatus() != CollectionStatus.SINGLETON); + boolean isColl = false; if (column.has("collection")) { JsonElement collectionJ = column.get("collection"); if (!(collectionJ instanceof JsonBoolean)) { error(path+".collection", collectionJ, "collection is not a boolean", IssueType.INVALID); } else { boolean collection = collectionJ.asJsonBoolean().asBoolean(); - if (!collection && isColl) { - isColl = false; - warning(path, column, "collection is false, but the path statement(s) might return multiple values for the column '"+columnName+"' some inputs"); + if (collection) { + isColl = true; } } } if (isColl) { + if (td.getCollectionStatus() == CollectionStatus.SINGLETON) { + hint(path, column, "collection is true, but the path statement(s) can only return single values for the column '"+columnName+"'"); + } + } else { if (arrays == null) { warning(path, expression, "The column '"+columnName+"' appears to be a collection based on it's path. Collections are not supported in all execution contexts"); } else if (!arrays) { warning(path, expression, "The column '"+columnName+"' appears to be a collection based on it's path, but this is not allowed in the current execution context"); } + if (td.getCollectionStatus() != CollectionStatus.SINGLETON) { + warning(path, column, "collection is not true, but the path statement(s) might return multiple values for the column '"+columnName+"' for some inputs"); + } } Set types = new HashSet<>(); if (node.isNullSet()) { @@ -330,7 +357,7 @@ public class Validator { 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); + error(path+".type", typeJ, "The path expression does not return a value of the type '"+type+"' - found "+td.describe(), IssueType.VALUE); } else { types.clear(); types.add(simpleType(type)); @@ -377,6 +404,8 @@ public class Validator { case "integer": return ColumnKind.Integer; case "decimal": return ColumnKind.Decimal; case "string": return ColumnKind.String; + case "id": return ColumnKind.String; + case "code": return ColumnKind.String; case "base64Binary": return ColumnKind.Binary; case "time": return ColumnKind.Time; default: return ColumnKind.Complex; @@ -384,7 +413,7 @@ public class Validator { } private boolean isSimpleType(String type) { - return Utilities.existsInList(type, "dateTime", "boolean", "integer", "decimal", "string", "base64Binary"); + return Utilities.existsInList(type, "dateTime", "boolean", "integer", "decimal", "string", "base64Binary", "id", "code", "date", "time"); } private String simpleType(String type) { @@ -413,7 +442,7 @@ public class Validator { return type; } - private TypeDetails checkForEach(String path, JsonObject focus, JsonElement expression, TypeDetails t) { + private TypeDetails checkForEach(JsonObject vd, String path, JsonObject focus, JsonElement expression, TypeDetails t) { if (!(expression instanceof JsonString)) { error(path+".forEach", expression, "forEach is not a string", IssueType.INVALID); return null; @@ -425,7 +454,7 @@ public class Validator { try { ExpressionNode n = fpe.parse(expr); focus.setUserData("forEach", n); - td = fpe.checkOnTypes(null, resourceName, t, n, warnings); + td = fpe.checkOnTypes(vd, resourceName, t, n, warnings); } catch (Exception e) { error(path, expression, e.getMessage(), IssueType.INVALID); } @@ -438,7 +467,7 @@ public class Validator { } } - private TypeDetails checkForEachOrNull(String path, JsonObject focus, JsonElement expression, TypeDetails t) { + private TypeDetails checkForEachOrNull(JsonObject vd, String path, JsonObject focus, JsonElement expression, TypeDetails t) { if (!(expression instanceof JsonString)) { error(path+".forEachOrNull", expression, "forEachOrNull is not a string", IssueType.INVALID); return null; @@ -450,7 +479,7 @@ public class Validator { try { ExpressionNode n = fpe.parse(expr); focus.setUserData("forEachOrNull", n); - td = fpe.checkOnTypes(null, resourceName, t, n, warnings); + td = fpe.checkOnTypes(vd, resourceName, t, n, warnings); } catch (Exception e) { error(path, expression, e.getMessage(), IssueType.INVALID); } @@ -477,69 +506,79 @@ public class Validator { } } if (constant.has("valueBase64Binary")) { - checkIsString(path, constant, "valueBase64Binary"); + checkIsString(path, constant, "valueBase64Binary", new Base64BinaryType()); } else if (constant.has("valueBoolean")) { - checkIsBoolean(path, constant, "valueBoolean"); + checkIsBoolean(path, constant, "valueBoolean", new BooleanType()); } else if (constant.has("valueCanonical")) { - checkIsString(path, constant, "valueCanonical"); + checkIsString(path, constant, "valueCanonical", new CanonicalType()); } else if (constant.has("valueCode")) { - checkIsString(path, constant, "valueCode"); + checkIsString(path, constant, "valueCode", new CodeType()); } else if (constant.has("valueDate")) { - checkIsString(path, constant, "valueDate"); + checkIsString(path, constant, "valueDate", new DateType()); } else if (constant.has("valueDateTime")) { - checkIsString(path, constant, "valueDateTime"); + checkIsString(path, constant, "valueDateTime", new DateTimeType()); } else if (constant.has("valueDecimal")) { - checkIsNumber(path, constant, "valueDecimal"); + checkIsNumber(path, constant, "valueDecimal", new DecimalType()); } else if (constant.has("valueId")) { - checkIsString(path, constant, "valueId"); + checkIsString(path, constant, "valueId", new IdType()); } else if (constant.has("valueInstant")) { - checkIsString(path, constant, "valueInstant"); + checkIsString(path, constant, "valueInstant", new InstantType()); } else if (constant.has("valueInteger")) { - checkIsNumber(path, constant, "valueInteger"); + checkIsNumber(path, constant, "valueInteger", new IntegerType()); } else if (constant.has("valueInteger64")) { - checkIsNumber(path, constant, "valueInteger64"); + checkIsNumber(path, constant, "valueInteger64", new Integer64Type()); } else if (constant.has("valueOid")) { - checkIsString(path, constant, "valueOid"); + checkIsString(path, constant, "valueOid", new OidType()); } else if (constant.has("valueString")) { - checkIsString(path, constant, "valueString"); + checkIsString(path, constant, "valueString", new StringType()); } else if (constant.has("valuePositiveInt")) { - checkIsNumber(path, constant, "valuePositiveInt"); + checkIsNumber(path, constant, "valuePositiveInt", new PositiveIntType()); } else if (constant.has("valueTime")) { - checkIsString(path, constant, "valueTime"); + checkIsString(path, constant, "valueTime", new TimeType()); } else if (constant.has("valueUnsignedInt")) { - checkIsNumber(path, constant, "valueUnsignedInt"); + checkIsNumber(path, constant, "valueUnsignedInt", new UnsignedIntType()); } else if (constant.has("valueUri")) { - checkIsString(path, constant, "valueUri"); + checkIsString(path, constant, "valueUri", new UriType()); } else if (constant.has("valueUrl")) { - checkIsString(path, constant, "valueUrl"); + checkIsString(path, constant, "valueUrl", new UrlType()); } else if (constant.has("valueUuid")) { - checkIsString(path, constant, "valueUuid"); + checkIsString(path, constant, "valueUuid", new UuidType()); } else { error(path, constant, "No value found", IssueType.REQUIRED); } } - private void checkIsString(String path, JsonObject constant, String name) { + private void checkIsString(String path, JsonObject constant, String name, PrimitiveType value) { JsonElement j = constant.get(name); if (!(j instanceof JsonString)) { error(path+"."+name, j, name+" must be a string", IssueType.INVALID); + } else { + value.setValueAsString(j.asString()); + constant.setUserData("value", value); } } - private void checkIsBoolean(String path, JsonObject constant, String name) { + private void checkIsBoolean(String path, JsonObject constant, String name, PrimitiveType value) { JsonElement j = constant.get(name); if (!(j instanceof JsonBoolean)) { error(path+"."+name, j, name+" must be a boolean", IssueType.INVALID); + } else { + value.setValueAsString(j.asString()); + constant.setUserData("value", value); } } - private void checkIsNumber(String path, JsonObject constant, String name) { + private void checkIsNumber(String path, JsonObject constant, String name, PrimitiveType value) { JsonElement j = constant.get(name); if (!(j instanceof JsonNumber)) { error(path+"."+name, j, name+" must be a number", IssueType.INVALID); + } else { + value.setValueAsString(j.asString()); + constant.setUserData("value", value); } } - private void checkWhere(String path, JsonObject where) { + + private void checkWhere(JsonObject vd, String path, JsonObject where) { checkProperties(where, path, "path", "description"); String expr = where.asString("path"); @@ -553,7 +592,7 @@ public class Validator { try { ExpressionNode n = fpe.parse(expr); where.setUserData("path", n); - td = fpe.checkOnTypes(null, resourceName, types, n, warnings); + td = fpe.checkOnTypes(vd, resourceName, types, n, warnings); } catch (Exception e) { error(path, where.get("path"), e.getMessage(), IssueType.INVALID); } 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 9dba811a8..d650980fb 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 @@ -83,23 +83,21 @@ public class SQLOnFhirTests { this.resources = resources; this.testCase = testCase; } - } public static Stream data() throws ParserConfigurationException, SAXException, IOException { List objects = new ArrayList<>(); - File dir = ManagedFileAccess.file("/Users/grahamegrieve/work/sql-on-fhir-v2/tests/content"); - for (File f : dir.listFiles()) { - if (f.getName().endsWith(".json")) { - JsonObject json = JsonParser.parseObject(f); - String name1 = f.getName().replace(".json", ""); - List resources = json.getJsonObjects("resources"); - int i = 0; - for (JsonObject test : json.getJsonObjects("tests")) { - String name2 = test.asString("title"); - objects.add(Arguments.of(name1+":"+name2, new TestDetails(name1+":"+name2, "$.tests["+i+"]", resources, test))); - i++; - } + JsonArray testFiles = (JsonArray) JsonParser.parse(TestingUtilities.loadTestResourceStream("sql-on-fhir", "manifest.json")); + + for (String s : testFiles.asStrings()) { + JsonObject json = JsonParser.parseObject(TestingUtilities.loadTestResourceStream("sql-on-fhir", s)); + String name1 = s.replace(".json", ""); + List resources = json.getJsonObjects("resources"); + int i = 0; + for (JsonObject test : json.getJsonObjects("tests")) { + String name2 = test.asString("title"); + objects.add(Arguments.of(name1+":"+name2, new TestDetails(name1+":"+name2, "$.tests["+i+"]", resources, test))); + i++; } } return objects.stream(); @@ -110,7 +108,6 @@ public class SQLOnFhirTests { @SuppressWarnings("deprecation") @ParameterizedTest(name = "{index}: file {0}") @MethodSource("data") - @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(); @@ -137,8 +134,8 @@ public class SQLOnFhirTests { rows.add("rows", results); JsonObject exp = new JsonObject(); exp.add("rows", test.testCase.getJsonArray("expect")); - sortResults(exp); - sortResults(rows); +// sortResults(exp); +// sortResults(rows); String expS = JsonParser.compose(exp, true); String rowS = JsonParser.compose(rows, true); String c = CompareUtilities.checkJsonSrcIsSame(name, expS, rowS, null); From ef69d12111c68f069c5df4bc8cf3082f4a7560f7 Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Mon, 9 Sep 2024 17:49:07 +0800 Subject: [PATCH 20/50] Fix expression for con-3 properly (fix validation problem on some condition resources) --- .../fhir/validation/instance/utils/FHIRPathExpressionFixer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/utils/FHIRPathExpressionFixer.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/utils/FHIRPathExpressionFixer.java index c4437511c..55376a293 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/utils/FHIRPathExpressionFixer.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/utils/FHIRPathExpressionFixer.java @@ -61,7 +61,7 @@ public class FHIRPathExpressionFixer { } // con-3 in R4 if (expr.equals("clinicalStatus.exists() or verificationStatus.coding.where(system='http://terminology.hl7.org/CodeSystem/condition-ver-status' and code = 'entered-in-error').exists() or category.select($this='problem-list-item').empty()")) { - return "clinicalStatus.exists() or verificationStatus.coding.where(system='http://terminology.hl7.org/CodeSystem/condition-ver-status' and code = 'entered-in-error').exists() or category.coding.exists(system='http://terminology.hl7.org/CodeSystem/condition-category' and code ='problem-list-item').empty()"; + return "(verificationStatus.coding.where(system='http://terminology.hl7.org/CodeSystem/condition-ver-status' and code = 'entered-in-error').exists() and category.coding.exists(system='http://terminology.hl7.org/CodeSystem/condition-category' and code ='problem-list-item').empty()) implies (clinicalStatus.exists())"; } // R5 ballot From d219a20de89a6846b5b4b747ae10da14794fb27c Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Mon, 9 Sep 2024 17:49:28 +0800 Subject: [PATCH 21/50] FHIRPath: Allow _ in constant names (per FHIRPath spec) --- .../src/main/java/org/hl7/fhir/r5/fhirpath/FHIRLexer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/fhirpath/FHIRLexer.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/fhirpath/FHIRLexer.java index b0d101cdc..080600c69 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/fhirpath/FHIRLexer.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/fhirpath/FHIRLexer.java @@ -187,7 +187,7 @@ public class FHIRLexer { cursor++; } else while (cursor < source.length() && ((source.charAt(cursor) >= 'A' && source.charAt(cursor) <= 'Z') || (source.charAt(cursor) >= 'a' && source.charAt(cursor) <= 'z') || - (source.charAt(cursor) >= '0' && source.charAt(cursor) <= '9') || source.charAt(cursor) == ':' || source.charAt(cursor) == '-')) + (source.charAt(cursor) >= '0' && source.charAt(cursor) <= '9') || source.charAt(cursor) == ':' || source.charAt(cursor) == '-' || source.charAt(cursor) == '_')) cursor++; current = source.substring(currentStart, cursor); } else if (ch == '/') { From 07a2b7d2e70728c654b6dbba35db02f62a433d01 Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Mon, 9 Sep 2024 17:51:38 +0800 Subject: [PATCH 22/50] Fix FHIRPath bug using wrong type on simple elements when checking FHIRPath types --- .../hl7/fhir/r5/fhirpath/FHIRPathEngine.java | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/fhirpath/FHIRPathEngine.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/fhirpath/FHIRPathEngine.java index 5d1efdcec..7a63e0c59 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/fhirpath/FHIRPathEngine.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/fhirpath/FHIRPathEngine.java @@ -773,6 +773,25 @@ public class FHIRPathEngine { return execute(new ExecutionContext(null, base != null && base.isResource() ? base : null, base != null && base.isResource() ? base : null, base, base), list, ExpressionNode, true); } + + /** + * evaluate a path and return the matching elements + * + * @param base - the object against which the path is being evaluated + * @param ExpressionNode - the parsed ExpressionNode statement to use + * @return + * @throws FHIRException + * @ + */ + public List evaluate(Object appContext, Base base, ExpressionNode ExpressionNode) throws FHIRException { + List list = new ArrayList(); + if (base != null) { + list.add(base); + } + log = new StringBuilder(); + return execute(new ExecutionContext(appContext, base != null && base.isResource() ? base : null, base != null && base.isResource() ? base : null, base, base), list, ExpressionNode, true); + } + /** * evaluate a path and return the matching elements * @@ -3741,6 +3760,8 @@ public class FHIRPathEngine { } if ((focus.hasType("date") || focus.hasType("datetime") || focus.hasType("instant"))) { return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Decimal, TypeDetails.FP_DateTime); + } else if ((focus.hasType("time"))) { + return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Time, TypeDetails.FP_Time); } else if (focus.hasType("decimal") || focus.hasType("integer")) { return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Decimal); } else { @@ -6351,7 +6372,7 @@ public class FHIRPathEngine { } result.addTypes(worker.getResourceNames()); } else { - pt = new ProfiledType(t.getCode()); + pt = new ProfiledType(t.getWorkingCode()); } if (pt != null) { if (t.hasProfile()) { From 4692962820aa2acc6b7575a4ed078fc0da17b94e Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Mon, 9 Sep 2024 17:56:07 +0800 Subject: [PATCH 23/50] release notes --- RELEASE_NOTES.md | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 7b06c6ab5..f9e202bce 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,7 +1,18 @@ ## Validator Changes -* no changes +* Fix expression for con-3 properly (fix validation problem on some condition resources) +* Fix FHIRPath bug using wrong type on simple elements when checking FHIRPath types +* FHIRPath: Allow _ in constant names (per FHIRPath spec) +* Fix value set rendering creating wrong references +* Fix bug processing value set includes / excludes that are just value sets (no system value) +* Alter processing of unknown code systems per discussion at ,https://chat.fhir.org/#narrow/stream/179252-IG-creation/topic/Don't.20error.20when.20you.20can't.20find.20code.20system and implement unknown-codesystems-cause-errors +* Improve message for when elements are out of order in profile differentials + ## Other code changes -* no changes \ No newline at end of file +* fix problem where profile rendering had spurious 'slices for' nodes everywhere +* Update SQL-On-FHIR implementation for latest cases, and clone test cases to general test care repository +* Fix problem generating value set spreadsheets +* fix concurrent modification error processing language translations +* Check for null fetcher processing ConceptMaps (#1728) From 52668c1c7897cd579f30d17aac3c4b8bf0cdac33 Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Mon, 9 Sep 2024 21:23:42 +0800 Subject: [PATCH 24/50] fix sql-on-fhir tests --- .../main/java/org/hl7/fhir/utilities/Utilities.java | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) 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 5c117d455..4042ee2f1 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 @@ -1819,9 +1819,14 @@ public class Utilities { private static Object applyDatePrecision(String v, int precision) { switch (precision) { - case 4: return v.substring(0, 4); - case 6: return v.substring(0, 7); - case 8: return v.substring(0, 10); + case 4: + return v.substring(0, 4); + case 6: + case 7: + return v.substring(0, 7); + case 8: + case 10: + return v.substring(0, 10); case 14: return v.substring(0, 17); case 17: return v; } From ffe0ab6414121c56bc8acecce7497f6af4a738ff Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Tue, 10 Sep 2024 00:27:08 +0800 Subject: [PATCH 25/50] 2024 09 gg vs sql (#1738) * Fix bug processing value set includes / excludes that are just value sets (no system value) * fix value set rendering creating wrong references * Update SQL-On-FHIR implementation for latest cases, and clone test cases to general test care repository * Fix expression for con-3 properly (fix validation problem on some condition resources) * FHIRPath: Allow _ in constant names (per FHIRPath spec) * Fix FHIRPath bug using wrong type on simple elements when checking FHIRPath types * release notes * fix sql-on-fhir tests --------- Co-authored-by: Grahame Grieve --- RELEASE_NOTES.md | 15 +- .../fhir/r5/context/BaseWorkerContext.java | 8 +- .../org/hl7/fhir/r5/fhirpath/FHIRLexer.java | 2 +- .../hl7/fhir/r5/fhirpath/FHIRPathEngine.java | 23 ++- .../fhir/r5/renderers/ValueSetRenderer.java | 45 +++--- .../r5/renderers/utils/RenderingContext.java | 3 + .../expansion/ValueSetExpander.java | 53 +++---- .../org/hl7/fhir/r5/utils/sql/Runner.java | 65 ++++++--- .../hl7/fhir/r5/utils/sql/StorageJson.java | 17 +-- .../org/hl7/fhir/r5/utils/sql/Validator.java | 131 ++++++++++++------ .../org/hl7/fhir/r5/sql/SQLOnFhirTests.java | 29 ++-- .../org/hl7/fhir/utilities/Utilities.java | 11 +- .../utils/FHIRPathExpressionFixer.java | 2 +- 13 files changed, 257 insertions(+), 147 deletions(-) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 7b06c6ab5..f9e202bce 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,7 +1,18 @@ ## Validator Changes -* no changes +* Fix expression for con-3 properly (fix validation problem on some condition resources) +* Fix FHIRPath bug using wrong type on simple elements when checking FHIRPath types +* FHIRPath: Allow _ in constant names (per FHIRPath spec) +* Fix value set rendering creating wrong references +* Fix bug processing value set includes / excludes that are just value sets (no system value) +* Alter processing of unknown code systems per discussion at ,https://chat.fhir.org/#narrow/stream/179252-IG-creation/topic/Don't.20error.20when.20you.20can't.20find.20code.20system and implement unknown-codesystems-cause-errors +* Improve message for when elements are out of order in profile differentials + ## Other code changes -* no changes \ No newline at end of file +* fix problem where profile rendering had spurious 'slices for' nodes everywhere +* Update SQL-On-FHIR implementation for latest cases, and clone test cases to general test care repository +* Fix problem generating value set spreadsheets +* fix concurrent modification error processing language translations +* Check for null fetcher processing ConceptMaps (#1728) 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 e517398be..e33cc0bfa 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 @@ -934,10 +934,14 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte throw new Error(formatMessage(I18nConstants.NO_VALUE_SET_IN_URL)); } for (ConceptSetComponent inc : vs.getCompose().getInclude()) { - codeSystemsUsed.add(inc.getSystem()); + if (inc.hasSystem()) { + codeSystemsUsed.add(inc.getSystem()); + } } for (ConceptSetComponent inc : vs.getCompose().getExclude()) { - codeSystemsUsed.add(inc.getSystem()); + if (inc.hasSystem()) { + codeSystemsUsed.add(inc.getSystem()); + } } CacheToken cacheToken = txCache.generateExpandToken(vs, hierarchical); diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/fhirpath/FHIRLexer.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/fhirpath/FHIRLexer.java index b0d101cdc..080600c69 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/fhirpath/FHIRLexer.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/fhirpath/FHIRLexer.java @@ -187,7 +187,7 @@ public class FHIRLexer { cursor++; } else while (cursor < source.length() && ((source.charAt(cursor) >= 'A' && source.charAt(cursor) <= 'Z') || (source.charAt(cursor) >= 'a' && source.charAt(cursor) <= 'z') || - (source.charAt(cursor) >= '0' && source.charAt(cursor) <= '9') || source.charAt(cursor) == ':' || source.charAt(cursor) == '-')) + (source.charAt(cursor) >= '0' && source.charAt(cursor) <= '9') || source.charAt(cursor) == ':' || source.charAt(cursor) == '-' || source.charAt(cursor) == '_')) cursor++; current = source.substring(currentStart, cursor); } else if (ch == '/') { diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/fhirpath/FHIRPathEngine.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/fhirpath/FHIRPathEngine.java index 5d1efdcec..7a63e0c59 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/fhirpath/FHIRPathEngine.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/fhirpath/FHIRPathEngine.java @@ -773,6 +773,25 @@ public class FHIRPathEngine { return execute(new ExecutionContext(null, base != null && base.isResource() ? base : null, base != null && base.isResource() ? base : null, base, base), list, ExpressionNode, true); } + + /** + * evaluate a path and return the matching elements + * + * @param base - the object against which the path is being evaluated + * @param ExpressionNode - the parsed ExpressionNode statement to use + * @return + * @throws FHIRException + * @ + */ + public List evaluate(Object appContext, Base base, ExpressionNode ExpressionNode) throws FHIRException { + List list = new ArrayList(); + if (base != null) { + list.add(base); + } + log = new StringBuilder(); + return execute(new ExecutionContext(appContext, base != null && base.isResource() ? base : null, base != null && base.isResource() ? base : null, base, base), list, ExpressionNode, true); + } + /** * evaluate a path and return the matching elements * @@ -3741,6 +3760,8 @@ public class FHIRPathEngine { } if ((focus.hasType("date") || focus.hasType("datetime") || focus.hasType("instant"))) { return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Decimal, TypeDetails.FP_DateTime); + } else if ((focus.hasType("time"))) { + return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Time, TypeDetails.FP_Time); } else if (focus.hasType("decimal") || focus.hasType("integer")) { return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Decimal); } else { @@ -6351,7 +6372,7 @@ public class FHIRPathEngine { } result.addTypes(worker.getResourceNames()); } else { - pt = new ProfiledType(t.getCode()); + pt = new ProfiledType(t.getWorkingCode()); } if (pt != null) { if (t.hasProfile()) { diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/ValueSetRenderer.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/ValueSetRenderer.java index eb303d742..4a78a67c8 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/ValueSetRenderer.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/ValueSetRenderer.java @@ -754,16 +754,7 @@ public class ValueSetRenderer extends TerminologyRenderer { if (ref == null) { ref = (String) cs.getWebPath(); } - if (ref == null && cs.hasUserData("webroot")) { - ref = (String) cs.getUserData("webroot"); - } - if (ref == null) { - return "?ngen-14?.html"; - } - if (!ref.contains(".html")) { - ref = ref + ".html"; - } - return ref.replace("\\", "/"); + return ref == null ? null : ref.replace("\\", "/"); } private void scanForDesignations(ValueSetExpansionContainsComponent c, List langs, Map designations) { @@ -922,14 +913,18 @@ public class ValueSetRenderer extends TerminologyRenderer { td.addText(code); } else { String href = context.fixReference(getCsRef(e)); - if (href.contains("#")) - href = href + "-"+Utilities.nmtokenize(code); - else - href = href + "#"+e.getId()+"-"+Utilities.nmtokenize(code); - if (isAbstract) - td.ah(context.prefixLocalHref(href)).setAttribute("title", context.formatPhrase(RenderingContext.VS_ABSTRACT_CODE_HINT)).i().addText(code); - else - td.ah(context.prefixLocalHref(href)).addText(code); + if (href == null) { + td.code().tx(code); + } else { + if (href.contains("#")) + href = href + "-"+Utilities.nmtokenize(code); + else + href = href + "#"+e.getId()+"-"+Utilities.nmtokenize(code); + if (isAbstract) + td.ah(context.prefixLocalHref(href)).setAttribute("title", context.formatPhrase(RenderingContext.VS_ABSTRACT_CODE_HINT)).i().addText(code); + else + td.ah(context.prefixLocalHref(href)).addText(code); + } } } @@ -1247,11 +1242,15 @@ public class ValueSetRenderer extends TerminologyRenderer { wli.tx(f.getProperty()+" "+describe(f.getOp())+" "); if (e != null && codeExistsInValueSet(e, f.getValue())) { String href = getContext().fixReference(getCsRef(e)); - if (href.contains("#")) - href = href + "-"+Utilities.nmtokenize(f.getValue()); - else - href = href + "#"+e.getId()+"-"+Utilities.nmtokenize(f.getValue()); - wli.ah(context.prefixLocalHref(href)).addText(f.getValue()); + if (href == null) { + wli.code().tx(f.getValue()); + } else { + if (href.contains("#")) + href = href + "-"+Utilities.nmtokenize(f.getValue()); + else + href = href + "#"+e.getId()+"-"+Utilities.nmtokenize(f.getValue()); + wli.ah(context.prefixLocalHref(href)).addText(f.getValue()); + } } else if (inc.hasSystem()) { wli.addText(f.getValue()); ValidationResult vr = getContext().getWorker().validateCode(getContext().getTerminologyServiceOptions(), inc.getSystem(), inc.getVersion(), f.getValue(), null); 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 572523a1e..687d7c672 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 @@ -554,6 +554,9 @@ public class RenderingContext extends RenderingI18nContext { } public String fixReference(String ref) { + if (ref == null) { + return null; + } if (!Utilities.isAbsoluteUrl(ref)) { return (localPrefix == null ? "" : localPrefix)+ref; } diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/terminologies/expansion/ValueSetExpander.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/terminologies/expansion/ValueSetExpander.java index 28058becb..7e1cfbbf7 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/terminologies/expansion/ValueSetExpander.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/terminologies/expansion/ValueSetExpander.java @@ -606,33 +606,35 @@ public class ValueSetExpander extends ValueSetProcessBase { excludeCodes(wc, importValueSetForExclude(wc, imp.getValue(), exp, expParams, false, vs).getExpansion()); } - CodeSystem cs = context.fetchSupplementedCodeSystem(exc.getSystem()); - if ((cs == null || cs.getContent() != CodeSystemContentMode.COMPLETE) && context.supportsSystem(exc.getSystem(), opContext.getOptions().getFhirVersion())) { - ValueSetExpansionOutcome vse = context.expandVS(exc, false, false); - ValueSet valueset = vse.getValueset(); - if (valueset == null) - throw failTSE("Error Expanding ValueSet: "+vse.getError()); - excludeCodes(wc, valueset.getExpansion()); - return; - } - - for (ConceptReferenceComponent c : exc.getConcept()) { - excludeCode(wc, exc.getSystem(), c.getCode()); - } - - if (exc.getFilter().size() > 0) { - if (cs.getContent() == CodeSystemContentMode.FRAGMENT) { - addFragmentWarning(exp, cs); + if (exc.hasSystem()) { + CodeSystem cs = context.fetchSupplementedCodeSystem(exc.getSystem()); + if ((cs == null || cs.getContent() != CodeSystemContentMode.COMPLETE) && context.supportsSystem(exc.getSystem(), opContext.getOptions().getFhirVersion())) { + ValueSetExpansionOutcome vse = context.expandVS(exc, false, false); + ValueSet valueset = vse.getValueset(); + if (valueset == null) + throw failTSE("Error Expanding ValueSet: "+vse.getError()); + excludeCodes(wc, valueset.getExpansion()); + return; } - List filters = new ArrayList<>(); - for (int i = 1; i < exc.getFilter().size(); i++) { - WorkingContext wc1 = new WorkingContext(); - filters.add(wc1); - processFilter(exc, exp, expParams, null, cs, false, exc.getFilter().get(i), wc1, null, true); + + for (ConceptReferenceComponent c : exc.getConcept()) { + excludeCode(wc, exc.getSystem(), c.getCode()); + } + + if (exc.getFilter().size() > 0) { + if (cs.getContent() == CodeSystemContentMode.FRAGMENT) { + addFragmentWarning(exp, cs); + } + List filters = new ArrayList<>(); + for (int i = 1; i < exc.getFilter().size(); i++) { + WorkingContext wc1 = new WorkingContext(); + filters.add(wc1); + processFilter(exc, exp, expParams, null, cs, false, exc.getFilter().get(i), wc1, null, true); + } + ConceptSetFilterComponent fc = exc.getFilter().get(0); + WorkingContext wc1 = dwc; + processFilter(exc, exp, expParams, null, cs, false, fc, wc1, filters, true); } - ConceptSetFilterComponent fc = exc.getFilter().get(0); - WorkingContext wc1 = dwc; - processFilter(exc, exp, expParams, null, cs, false, fc, wc1, filters, true); } } @@ -728,7 +730,6 @@ public class ValueSetExpander extends ValueSetProcessBase { expParams = makeDefaultExpansion(); altCodeParams.seeParameters(expParams); altCodeParams.seeValueSet(source); - source.checkNoModifiers("ValueSet", "expanding"); focus = source.copy(); focus.setIdBase(null); 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 432fff492..aa5d8b4e1 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 @@ -103,7 +103,7 @@ public class Runner implements IEvaluationContext { for (JsonObject w : vd.getJsonObjects("where")) { String expr = w.asString("path"); ExpressionNode node = fpe.parse(expr); - boolean pass = fpe.evaluateToBoolean(null, b, b, b, node); + boolean pass = fpe.evaluateToBoolean(vd, b, b, b, node); if (!pass) { ok = false; break; @@ -114,7 +114,7 @@ public class Runner implements IEvaluationContext { rows.add(new ArrayList()); for (JsonObject select : vd.getJsonObjects("select")) { - executeSelect(select, b, rows); + executeSelect(vd, select, b, rows); } for (List row : rows) { storage.addRow(store, row); @@ -124,14 +124,14 @@ public class Runner implements IEvaluationContext { storage.finish(store); } - private void executeSelect(JsonObject select, Base b, List> rows) { + private void executeSelect(JsonObject vd, JsonObject select, Base b, List> rows) { List focus = new ArrayList<>(); if (select.has("forEach")) { - focus.addAll(executeForEach(select, b)); + focus.addAll(executeForEach(vd, select, b)); } else if (select.has("forEachOrNull")) { - focus.addAll(executeForEachOrNull(select, b)); + focus.addAll(executeForEachOrNull(vd, select, b)); if (focus.isEmpty()) { List columns = (List) select.getUserData("columns"); for (List row : rows) { @@ -159,20 +159,20 @@ public class Runner implements IEvaluationContext { List> rowsToAdd = cloneRows(tempRows); for (JsonObject column : select.getJsonObjects("column")) { - executeColumn(column, f, rowsToAdd); + executeColumn(vd, column, f, rowsToAdd); } for (JsonObject sub : select.getJsonObjects("select")) { - executeSelect(sub, f, rowsToAdd); + executeSelect(vd, sub, f, rowsToAdd); } - executeUnionAll(select.getJsonObjects("unionAll"), f, rowsToAdd); + executeUnionAll(vd, select.getJsonObjects("unionAll"), f, rowsToAdd); rows.addAll(rowsToAdd); } } - private void executeUnionAll(List unionList, Base b, List> rows) { + private void executeUnionAll(JsonObject vd, List unionList, Base b, List> rows) { if (unionList.isEmpty()) { return; } @@ -183,7 +183,7 @@ public class Runner implements IEvaluationContext { for (JsonObject union : unionList) { List> tempRows = new ArrayList<>(); tempRows.addAll(sourceRows); - executeSelect(union, b, tempRows); + executeSelect(vd, union, b, tempRows); rows.addAll(tempRows); } } @@ -204,25 +204,25 @@ public class Runner implements IEvaluationContext { return list; } - private List executeForEach(JsonObject focus, Base b) { + private List executeForEach(JsonObject vd, JsonObject focus, Base b) { ExpressionNode n = (ExpressionNode) focus.getUserData("forEach"); List result = new ArrayList<>(); - result.addAll(fpe.evaluate(b, n)); + result.addAll(fpe.evaluate(vd, b, n)); return result; } - private List executeForEachOrNull(JsonObject focus, Base b) { + private List executeForEachOrNull(JsonObject vd, JsonObject focus, Base b) { ExpressionNode n = (ExpressionNode) focus.getUserData("forEachOrNull"); List result = new ArrayList<>(); - result.addAll(fpe.evaluate(b, n)); + result.addAll(fpe.evaluate(vd, b, n)); return result; } - private void executeColumn(JsonObject column, Base b, List> rows) { + private void executeColumn(JsonObject vd, JsonObject column, Base b, List> rows) { ExpressionNode n = (ExpressionNode) column.getUserData("path"); List bl2 = new ArrayList<>(); if (b != null) { - bl2.addAll(fpe.evaluate(b, n)); + bl2.addAll(fpe.evaluate(vd, b, n)); } Column col = (Column) column.getUserData("column"); if (col == null) { @@ -344,14 +344,43 @@ public class Runner implements IEvaluationContext { @Override public List resolveConstant(FHIRPathEngine engine, Object appContext, String name, boolean beforeContext, boolean explicitConstant) throws PathEngineException { - throw new Error("Not implemented yet: resolveConstant"); + List list = new ArrayList(); + if (explicitConstant) { + JsonObject vd = (JsonObject) appContext; + JsonObject constant = findConstant(vd, name); + if (constant != null) { + Base b = (Base) constant.getUserData("value"); + if (b != null) { + list.add(b); + } + } + } + return list; } @Override public TypeDetails resolveConstantType(FHIRPathEngine engine, Object appContext, String name, boolean explicitConstant) throws PathEngineException { - throw new Error("Not implemented yet: resolveConstantType"); + if (explicitConstant) { + JsonObject vd = (JsonObject) appContext; + JsonObject constant = findConstant(vd, name.substring(1)); + if (constant != null) { + Base b = (Base) constant.getUserData("value"); + if (b != null) { + return new TypeDetails(CollectionStatus.SINGLETON, b.fhirType()); + } + } + } + return null; } + private JsonObject findConstant(JsonObject vd, String name) { + for (JsonObject o : vd.getJsonObjects("constant")) { + if (name.equals(o.asString("name"))) { + return o; + } + } + return null; + } @Override public boolean log(String argument, List focus) { throw new Error("Not implemented yet: log"); 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 d0e3aaeed..d76404c03 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 @@ -2,6 +2,7 @@ package org.hl7.fhir.r5.utils.sql; import java.util.List; +import org.hl7.fhir.exceptions.FHIRException; import org.hl7.fhir.r5.model.Base; import org.hl7.fhir.utilities.json.model.JsonArray; import org.hl7.fhir.utilities.json.model.JsonBoolean; @@ -33,16 +34,16 @@ public class StorageJson implements Storage { JsonObject row = new JsonObject(); rows.add(row); for (Cell cell : cells) { - if (cell.getValues().size() == 0) { - row.add(cell.getColumn().getName(), new JsonNull()); - } else if (cell.getValues().size() == 1) { - row.add(cell.getColumn().getName(), makeJsonNode(cell.getValues().get(0))); - } else { + if (cell.getColumn().isColl() || cell.getValues().size() > 1) { JsonArray arr = new JsonArray(); - row.add(cell.getColumn().getName(), arr); + row.add(cell.getColumn().getName(), arr); for (Value value : cell.getValues()) { arr.add(makeJsonNode(value)); - } + } + } else if (cell.getValues().size() == 0) { + row.add(cell.getColumn().getName(), new JsonNull()); + } else { + row.add(cell.getColumn().getName(), makeJsonNode(cell.getValues().get(0))); } } } @@ -87,7 +88,7 @@ public class StorageJson implements Storage { @Override public String getKeyForSourceResource(Base res) { - return res.getIdBase(); + return res.fhirType()+"/"+res.getIdBase(); } @Override 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 669fa32de..00c862b5d 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 @@ -11,6 +11,27 @@ import org.hl7.fhir.r5.context.IWorkerContext; import org.hl7.fhir.r5.fhirpath.ExpressionNode; import org.hl7.fhir.r5.fhirpath.FHIRPathEngine; import org.hl7.fhir.r5.fhirpath.TypeDetails; +import org.hl7.fhir.r5.formats.JsonParser; +import org.hl7.fhir.r5.model.Base64BinaryType; +import org.hl7.fhir.r5.model.BooleanType; +import org.hl7.fhir.r5.model.CanonicalType; +import org.hl7.fhir.r5.model.CodeType; +import org.hl7.fhir.r5.model.DateTimeType; +import org.hl7.fhir.r5.model.DateType; +import org.hl7.fhir.r5.model.DecimalType; +import org.hl7.fhir.r5.model.IdType; +import org.hl7.fhir.r5.model.InstantType; +import org.hl7.fhir.r5.model.Integer64Type; +import org.hl7.fhir.r5.model.IntegerType; +import org.hl7.fhir.r5.model.OidType; +import org.hl7.fhir.r5.model.PositiveIntType; +import org.hl7.fhir.r5.model.PrimitiveType; +import org.hl7.fhir.r5.model.StringType; +import org.hl7.fhir.r5.model.TimeType; +import org.hl7.fhir.r5.model.UnsignedIntType; +import org.hl7.fhir.r5.model.UriType; +import org.hl7.fhir.r5.model.UrlType; +import org.hl7.fhir.r5.model.UuidType; import org.hl7.fhir.r5.fhirpath.ExpressionNode.CollectionStatus; import org.hl7.fhir.r5.fhirpath.FHIRPathEngine.IssueMessage; import org.hl7.fhir.utilities.Utilities; @@ -99,7 +120,7 @@ public class Validator { i = 0; if (checkAllObjects(path, viewDefinition, "where")) { for (JsonObject where : viewDefinition.getJsonObjects("where")) { - checkWhere(path+".where["+i+"]", where); + checkWhere(viewDefinition, path+".where["+i+"]", where); i++; } } @@ -108,7 +129,7 @@ public class Validator { i = 0; if (checkAllObjects(path, viewDefinition, "select")) { for (JsonObject select : viewDefinition.getJsonObjects("select")) { - columns.addAll(checkSelect(path+".select["+i+"]", select, t)); + columns.addAll(checkSelect(viewDefinition, path+".select["+i+"]", select, t)); i++; } if (i == 0) { @@ -119,15 +140,15 @@ public class Validator { } } - private List checkSelect(String path, JsonObject select, TypeDetails t) { + private List checkSelect(JsonObject vd, 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); + t = checkForEach(vd, path, select, select.get("forEach"), t); } else if (select.has("forEachOrNull")) { - t = checkForEachOrNull(path, select, select.get("forEachOrNull"), t); + t = checkForEachOrNull(vd, path, select, select.get("forEachOrNull"), t); } if (t != null) { @@ -142,7 +163,7 @@ public class Validator { if (!(e instanceof JsonObject)) { error(path+".column["+i+"]", a, "column["+i+"] is a "+e.type().toName()+" not an object", IssueType.INVALID); } else { - columns.add(checkColumn(path+".column["+i+"]", (JsonObject) e, t)); + columns.add(checkColumn(vd, path+".column["+i+"]", (JsonObject) e, t)); } } } @@ -158,14 +179,14 @@ public class Validator { if (!(e instanceof JsonObject)) { error(path+".select["+i+"]", e, "select["+i+"] is not an object", IssueType.INVALID); } else { - columns.addAll(checkSelect(path+".select["+i+"]", (JsonObject) e, t)); + columns.addAll(checkSelect(vd, path+".select["+i+"]", (JsonObject) e, t)); } } } } if (select.has("unionAll")) { - columns.addAll(checkUnion(path, select, select.get("unionAll"), t)); + columns.addAll(checkUnion(vd, path, select, select.get("unionAll"), t)); } if (columns.isEmpty()) { error(path, select, "The select has no columns or selects", IssueType.REQUIRED); @@ -191,7 +212,7 @@ public class Validator { } } - private List checkUnion(String path, JsonObject focus, JsonElement expression, TypeDetails t) { + private List checkUnion(JsonObject vd, String path, JsonObject focus, JsonElement expression, TypeDetails t) { JsonElement a = focus.get("unionAll"); if (!(a instanceof JsonArray)) { error(path+".unionAll", a, "union is not an array", IssueType.INVALID); @@ -203,7 +224,7 @@ public class Validator { if (!(e instanceof JsonObject)) { error(path+".unionAll["+i+"]", e, "unionAll["+i+"] is not an object", IssueType.INVALID); } else { - unionColumns.add(checkSelect(path+".unionAll["+i+"]", (JsonObject) e, t)); + unionColumns.add(checkSelect(vd, path+".unionAll["+i+"]", (JsonObject) e, t)); } i++; } @@ -242,7 +263,7 @@ public class Validator { } } - private Column checkColumn(String path, JsonObject column, TypeDetails t) { + private Column checkColumn(JsonObject vd, String path, JsonObject column, TypeDetails t) { checkProperties(column, path, "path", "name", "description", "collection", "type", "tag"); if (!column.has("path")) { @@ -260,7 +281,7 @@ public class Validator { try { node = fpe.parse(expr); column.setUserData("path", node); - td = fpe.checkOnTypes(null, resourceName, t, node, warnings); + td = fpe.checkOnTypes(vd, resourceName, t, node, warnings); } catch (Exception e) { error(path, expression, e.getMessage(), IssueType.INVALID); } @@ -296,25 +317,31 @@ public class Validator { // ok, name is sorted! if (columnName != null) { column.setUserData("name", columnName); - boolean isColl = (td.getCollectionStatus() != CollectionStatus.SINGLETON); + boolean isColl = false; if (column.has("collection")) { JsonElement collectionJ = column.get("collection"); if (!(collectionJ instanceof JsonBoolean)) { error(path+".collection", collectionJ, "collection is not a boolean", IssueType.INVALID); } else { boolean collection = collectionJ.asJsonBoolean().asBoolean(); - if (!collection && isColl) { - isColl = false; - warning(path, column, "collection is false, but the path statement(s) might return multiple values for the column '"+columnName+"' some inputs"); + if (collection) { + isColl = true; } } } if (isColl) { + if (td.getCollectionStatus() == CollectionStatus.SINGLETON) { + hint(path, column, "collection is true, but the path statement(s) can only return single values for the column '"+columnName+"'"); + } + } else { if (arrays == null) { warning(path, expression, "The column '"+columnName+"' appears to be a collection based on it's path. Collections are not supported in all execution contexts"); } else if (!arrays) { warning(path, expression, "The column '"+columnName+"' appears to be a collection based on it's path, but this is not allowed in the current execution context"); } + if (td.getCollectionStatus() != CollectionStatus.SINGLETON) { + warning(path, column, "collection is not true, but the path statement(s) might return multiple values for the column '"+columnName+"' for some inputs"); + } } Set types = new HashSet<>(); if (node.isNullSet()) { @@ -330,7 +357,7 @@ public class Validator { 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); + error(path+".type", typeJ, "The path expression does not return a value of the type '"+type+"' - found "+td.describe(), IssueType.VALUE); } else { types.clear(); types.add(simpleType(type)); @@ -377,6 +404,8 @@ public class Validator { case "integer": return ColumnKind.Integer; case "decimal": return ColumnKind.Decimal; case "string": return ColumnKind.String; + case "id": return ColumnKind.String; + case "code": return ColumnKind.String; case "base64Binary": return ColumnKind.Binary; case "time": return ColumnKind.Time; default: return ColumnKind.Complex; @@ -384,7 +413,7 @@ public class Validator { } private boolean isSimpleType(String type) { - return Utilities.existsInList(type, "dateTime", "boolean", "integer", "decimal", "string", "base64Binary"); + return Utilities.existsInList(type, "dateTime", "boolean", "integer", "decimal", "string", "base64Binary", "id", "code", "date", "time"); } private String simpleType(String type) { @@ -413,7 +442,7 @@ public class Validator { return type; } - private TypeDetails checkForEach(String path, JsonObject focus, JsonElement expression, TypeDetails t) { + private TypeDetails checkForEach(JsonObject vd, String path, JsonObject focus, JsonElement expression, TypeDetails t) { if (!(expression instanceof JsonString)) { error(path+".forEach", expression, "forEach is not a string", IssueType.INVALID); return null; @@ -425,7 +454,7 @@ public class Validator { try { ExpressionNode n = fpe.parse(expr); focus.setUserData("forEach", n); - td = fpe.checkOnTypes(null, resourceName, t, n, warnings); + td = fpe.checkOnTypes(vd, resourceName, t, n, warnings); } catch (Exception e) { error(path, expression, e.getMessage(), IssueType.INVALID); } @@ -438,7 +467,7 @@ public class Validator { } } - private TypeDetails checkForEachOrNull(String path, JsonObject focus, JsonElement expression, TypeDetails t) { + private TypeDetails checkForEachOrNull(JsonObject vd, String path, JsonObject focus, JsonElement expression, TypeDetails t) { if (!(expression instanceof JsonString)) { error(path+".forEachOrNull", expression, "forEachOrNull is not a string", IssueType.INVALID); return null; @@ -450,7 +479,7 @@ public class Validator { try { ExpressionNode n = fpe.parse(expr); focus.setUserData("forEachOrNull", n); - td = fpe.checkOnTypes(null, resourceName, t, n, warnings); + td = fpe.checkOnTypes(vd, resourceName, t, n, warnings); } catch (Exception e) { error(path, expression, e.getMessage(), IssueType.INVALID); } @@ -477,69 +506,79 @@ public class Validator { } } if (constant.has("valueBase64Binary")) { - checkIsString(path, constant, "valueBase64Binary"); + checkIsString(path, constant, "valueBase64Binary", new Base64BinaryType()); } else if (constant.has("valueBoolean")) { - checkIsBoolean(path, constant, "valueBoolean"); + checkIsBoolean(path, constant, "valueBoolean", new BooleanType()); } else if (constant.has("valueCanonical")) { - checkIsString(path, constant, "valueCanonical"); + checkIsString(path, constant, "valueCanonical", new CanonicalType()); } else if (constant.has("valueCode")) { - checkIsString(path, constant, "valueCode"); + checkIsString(path, constant, "valueCode", new CodeType()); } else if (constant.has("valueDate")) { - checkIsString(path, constant, "valueDate"); + checkIsString(path, constant, "valueDate", new DateType()); } else if (constant.has("valueDateTime")) { - checkIsString(path, constant, "valueDateTime"); + checkIsString(path, constant, "valueDateTime", new DateTimeType()); } else if (constant.has("valueDecimal")) { - checkIsNumber(path, constant, "valueDecimal"); + checkIsNumber(path, constant, "valueDecimal", new DecimalType()); } else if (constant.has("valueId")) { - checkIsString(path, constant, "valueId"); + checkIsString(path, constant, "valueId", new IdType()); } else if (constant.has("valueInstant")) { - checkIsString(path, constant, "valueInstant"); + checkIsString(path, constant, "valueInstant", new InstantType()); } else if (constant.has("valueInteger")) { - checkIsNumber(path, constant, "valueInteger"); + checkIsNumber(path, constant, "valueInteger", new IntegerType()); } else if (constant.has("valueInteger64")) { - checkIsNumber(path, constant, "valueInteger64"); + checkIsNumber(path, constant, "valueInteger64", new Integer64Type()); } else if (constant.has("valueOid")) { - checkIsString(path, constant, "valueOid"); + checkIsString(path, constant, "valueOid", new OidType()); } else if (constant.has("valueString")) { - checkIsString(path, constant, "valueString"); + checkIsString(path, constant, "valueString", new StringType()); } else if (constant.has("valuePositiveInt")) { - checkIsNumber(path, constant, "valuePositiveInt"); + checkIsNumber(path, constant, "valuePositiveInt", new PositiveIntType()); } else if (constant.has("valueTime")) { - checkIsString(path, constant, "valueTime"); + checkIsString(path, constant, "valueTime", new TimeType()); } else if (constant.has("valueUnsignedInt")) { - checkIsNumber(path, constant, "valueUnsignedInt"); + checkIsNumber(path, constant, "valueUnsignedInt", new UnsignedIntType()); } else if (constant.has("valueUri")) { - checkIsString(path, constant, "valueUri"); + checkIsString(path, constant, "valueUri", new UriType()); } else if (constant.has("valueUrl")) { - checkIsString(path, constant, "valueUrl"); + checkIsString(path, constant, "valueUrl", new UrlType()); } else if (constant.has("valueUuid")) { - checkIsString(path, constant, "valueUuid"); + checkIsString(path, constant, "valueUuid", new UuidType()); } else { error(path, constant, "No value found", IssueType.REQUIRED); } } - private void checkIsString(String path, JsonObject constant, String name) { + private void checkIsString(String path, JsonObject constant, String name, PrimitiveType value) { JsonElement j = constant.get(name); if (!(j instanceof JsonString)) { error(path+"."+name, j, name+" must be a string", IssueType.INVALID); + } else { + value.setValueAsString(j.asString()); + constant.setUserData("value", value); } } - private void checkIsBoolean(String path, JsonObject constant, String name) { + private void checkIsBoolean(String path, JsonObject constant, String name, PrimitiveType value) { JsonElement j = constant.get(name); if (!(j instanceof JsonBoolean)) { error(path+"."+name, j, name+" must be a boolean", IssueType.INVALID); + } else { + value.setValueAsString(j.asString()); + constant.setUserData("value", value); } } - private void checkIsNumber(String path, JsonObject constant, String name) { + private void checkIsNumber(String path, JsonObject constant, String name, PrimitiveType value) { JsonElement j = constant.get(name); if (!(j instanceof JsonNumber)) { error(path+"."+name, j, name+" must be a number", IssueType.INVALID); + } else { + value.setValueAsString(j.asString()); + constant.setUserData("value", value); } } - private void checkWhere(String path, JsonObject where) { + + private void checkWhere(JsonObject vd, String path, JsonObject where) { checkProperties(where, path, "path", "description"); String expr = where.asString("path"); @@ -553,7 +592,7 @@ public class Validator { try { ExpressionNode n = fpe.parse(expr); where.setUserData("path", n); - td = fpe.checkOnTypes(null, resourceName, types, n, warnings); + td = fpe.checkOnTypes(vd, resourceName, types, n, warnings); } catch (Exception e) { error(path, where.get("path"), e.getMessage(), IssueType.INVALID); } 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 9dba811a8..d650980fb 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 @@ -83,23 +83,21 @@ public class SQLOnFhirTests { this.resources = resources; this.testCase = testCase; } - } public static Stream data() throws ParserConfigurationException, SAXException, IOException { List objects = new ArrayList<>(); - File dir = ManagedFileAccess.file("/Users/grahamegrieve/work/sql-on-fhir-v2/tests/content"); - for (File f : dir.listFiles()) { - if (f.getName().endsWith(".json")) { - JsonObject json = JsonParser.parseObject(f); - String name1 = f.getName().replace(".json", ""); - List resources = json.getJsonObjects("resources"); - int i = 0; - for (JsonObject test : json.getJsonObjects("tests")) { - String name2 = test.asString("title"); - objects.add(Arguments.of(name1+":"+name2, new TestDetails(name1+":"+name2, "$.tests["+i+"]", resources, test))); - i++; - } + JsonArray testFiles = (JsonArray) JsonParser.parse(TestingUtilities.loadTestResourceStream("sql-on-fhir", "manifest.json")); + + for (String s : testFiles.asStrings()) { + JsonObject json = JsonParser.parseObject(TestingUtilities.loadTestResourceStream("sql-on-fhir", s)); + String name1 = s.replace(".json", ""); + List resources = json.getJsonObjects("resources"); + int i = 0; + for (JsonObject test : json.getJsonObjects("tests")) { + String name2 = test.asString("title"); + objects.add(Arguments.of(name1+":"+name2, new TestDetails(name1+":"+name2, "$.tests["+i+"]", resources, test))); + i++; } } return objects.stream(); @@ -110,7 +108,6 @@ public class SQLOnFhirTests { @SuppressWarnings("deprecation") @ParameterizedTest(name = "{index}: file {0}") @MethodSource("data") - @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(); @@ -137,8 +134,8 @@ public class SQLOnFhirTests { rows.add("rows", results); JsonObject exp = new JsonObject(); exp.add("rows", test.testCase.getJsonArray("expect")); - sortResults(exp); - sortResults(rows); +// sortResults(exp); +// sortResults(rows); String expS = JsonParser.compose(exp, true); String rowS = JsonParser.compose(rows, true); String c = CompareUtilities.checkJsonSrcIsSame(name, expS, rowS, null); 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 5c117d455..4042ee2f1 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 @@ -1819,9 +1819,14 @@ public class Utilities { private static Object applyDatePrecision(String v, int precision) { switch (precision) { - case 4: return v.substring(0, 4); - case 6: return v.substring(0, 7); - case 8: return v.substring(0, 10); + case 4: + return v.substring(0, 4); + case 6: + case 7: + return v.substring(0, 7); + case 8: + case 10: + return v.substring(0, 10); case 14: return v.substring(0, 17); case 17: return v; } diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/utils/FHIRPathExpressionFixer.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/utils/FHIRPathExpressionFixer.java index c4437511c..55376a293 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/utils/FHIRPathExpressionFixer.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/utils/FHIRPathExpressionFixer.java @@ -61,7 +61,7 @@ public class FHIRPathExpressionFixer { } // con-3 in R4 if (expr.equals("clinicalStatus.exists() or verificationStatus.coding.where(system='http://terminology.hl7.org/CodeSystem/condition-ver-status' and code = 'entered-in-error').exists() or category.select($this='problem-list-item').empty()")) { - return "clinicalStatus.exists() or verificationStatus.coding.where(system='http://terminology.hl7.org/CodeSystem/condition-ver-status' and code = 'entered-in-error').exists() or category.coding.exists(system='http://terminology.hl7.org/CodeSystem/condition-category' and code ='problem-list-item').empty()"; + return "(verificationStatus.coding.where(system='http://terminology.hl7.org/CodeSystem/condition-ver-status' and code = 'entered-in-error').exists() and category.coding.exists(system='http://terminology.hl7.org/CodeSystem/condition-category' and code ='problem-list-item').empty()) implies (clinicalStatus.exists())"; } // R5 ballot From 4cbf1860d7b89f5990a55d769a996b579c05c01c Mon Sep 17 00:00:00 2001 From: dotasek Date: Mon, 9 Sep 2024 13:06:57 -0400 Subject: [PATCH 26/50] Bump fhir-test-cases to release version --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index be5e3727d..ca79ada7c 100644 --- a/pom.xml +++ b/pom.xml @@ -21,7 +21,7 @@ 1.26.0 32.0.1-jre 6.4.1 - 1.5.21-SNAPSHOT + 1.5.21 2.17.0 5.9.2 1.8.2 From 813f8200a2b7f15b4724b14511fac3f4f6d21b76 Mon Sep 17 00:00:00 2001 From: markiantorno Date: Mon, 9 Sep 2024 18:23:37 +0000 Subject: [PATCH 27/50] Release: v6.3.24 ## Validator Changes * Fix expression for con-3 properly (fix validation problem on some condition resources) * Fix FHIRPath bug using wrong type on simple elements when checking FHIRPath types * FHIRPath: Allow _ in constant names (per FHIRPath spec) * Fix value set rendering creating wrong references * Fix bug processing value set includes / excludes that are just value sets (no system value) * Alter processing of unknown code systems per discussion at ,https://chat.fhir.org/#narrow/stream/179252-IG-creation/topic/Don't.20error.20when.20you.20can't.20find.20code.20system and implement unknown-codesystems-cause-errors * Improve message for when elements are out of order in profile differentials ## Other code changes * fix problem where profile rendering had spurious 'slices for' nodes everywhere * Update SQL-On-FHIR implementation for latest cases, and clone test cases to general test care repository * Fix problem generating value set spreadsheets * fix concurrent modification error processing language translations * Check for null fetcher processing ConceptMaps (#1728) ***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 a0a3869df..50b3e6401 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.3.24-SNAPSHOT + 6.3.24 ../pom.xml diff --git a/org.hl7.fhir.dstu2/pom.xml b/org.hl7.fhir.dstu2/pom.xml index 8055af71e..a6d0a504b 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.3.24-SNAPSHOT + 6.3.24 ../pom.xml diff --git a/org.hl7.fhir.dstu2016may/pom.xml b/org.hl7.fhir.dstu2016may/pom.xml index da50ebb03..786d46709 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.3.24-SNAPSHOT + 6.3.24 ../pom.xml diff --git a/org.hl7.fhir.dstu3/pom.xml b/org.hl7.fhir.dstu3/pom.xml index 0a6da6acf..b1ed5bb99 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.3.24-SNAPSHOT + 6.3.24 ../pom.xml diff --git a/org.hl7.fhir.r4/pom.xml b/org.hl7.fhir.r4/pom.xml index 9fa2bbaa8..f69788507 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.3.24-SNAPSHOT + 6.3.24 ../pom.xml diff --git a/org.hl7.fhir.r4b/pom.xml b/org.hl7.fhir.r4b/pom.xml index 25f7e8516..c4656a156 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.3.24-SNAPSHOT + 6.3.24 ../pom.xml diff --git a/org.hl7.fhir.r5/pom.xml b/org.hl7.fhir.r5/pom.xml index 9c76d955d..1ff84dbc5 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.3.24-SNAPSHOT + 6.3.24 ../pom.xml diff --git a/org.hl7.fhir.report/pom.xml b/org.hl7.fhir.report/pom.xml index 7889e540c..c0c0a6af2 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.3.24-SNAPSHOT + 6.3.24 ../pom.xml diff --git a/org.hl7.fhir.utilities/pom.xml b/org.hl7.fhir.utilities/pom.xml index 76ea1bc06..2471e5442 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.3.24-SNAPSHOT + 6.3.24 ../pom.xml diff --git a/org.hl7.fhir.validation.cli/pom.xml b/org.hl7.fhir.validation.cli/pom.xml index f0907cd29..65839379b 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.3.24-SNAPSHOT + 6.3.24 ../pom.xml diff --git a/org.hl7.fhir.validation/pom.xml b/org.hl7.fhir.validation/pom.xml index 9bf7272b5..d20acce66 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.3.24-SNAPSHOT + 6.3.24 ../pom.xml diff --git a/pom.xml b/pom.xml index ca79ada7c..5cbe8d761 100644 --- a/pom.xml +++ b/pom.xml @@ -14,7 +14,7 @@ HAPI FHIR --> org.hl7.fhir.core - 6.3.24-SNAPSHOT + 6.3.24 pom From 2c8122a42eeec607133f26b1bef14c4611ea13e4 Mon Sep 17 00:00:00 2001 From: markiantorno Date: Mon, 9 Sep 2024 19:09:24 +0000 Subject: [PATCH 28/50] Updating version to: 6.3.25-SNAPSHOT and incrementing test cases dependency. --- RELEASE_NOTES.md | 15 ++------------- 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(+), 25 deletions(-) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index f9e202bce..7b06c6ab5 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,18 +1,7 @@ ## Validator Changes -* Fix expression for con-3 properly (fix validation problem on some condition resources) -* Fix FHIRPath bug using wrong type on simple elements when checking FHIRPath types -* FHIRPath: Allow _ in constant names (per FHIRPath spec) -* Fix value set rendering creating wrong references -* Fix bug processing value set includes / excludes that are just value sets (no system value) -* Alter processing of unknown code systems per discussion at ,https://chat.fhir.org/#narrow/stream/179252-IG-creation/topic/Don't.20error.20when.20you.20can't.20find.20code.20system and implement unknown-codesystems-cause-errors -* Improve message for when elements are out of order in profile differentials - +* no changes ## Other code changes -* fix problem where profile rendering had spurious 'slices for' nodes everywhere -* Update SQL-On-FHIR implementation for latest cases, and clone test cases to general test care repository -* Fix problem generating value set spreadsheets -* fix concurrent modification error processing language translations -* Check for null fetcher processing ConceptMaps (#1728) +* 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 50b3e6401..370eb607f 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.3.24 + 6.3.25-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.dstu2/pom.xml b/org.hl7.fhir.dstu2/pom.xml index a6d0a504b..317170b7b 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.3.24 + 6.3.25-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.dstu2016may/pom.xml b/org.hl7.fhir.dstu2016may/pom.xml index 786d46709..c804e1719 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.3.24 + 6.3.25-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.dstu3/pom.xml b/org.hl7.fhir.dstu3/pom.xml index b1ed5bb99..0e79f835a 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.3.24 + 6.3.25-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.r4/pom.xml b/org.hl7.fhir.r4/pom.xml index f69788507..032363f4c 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.3.24 + 6.3.25-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.r4b/pom.xml b/org.hl7.fhir.r4b/pom.xml index c4656a156..147230f24 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.3.24 + 6.3.25-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.r5/pom.xml b/org.hl7.fhir.r5/pom.xml index 1ff84dbc5..7e6fb6a09 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.3.24 + 6.3.25-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.report/pom.xml b/org.hl7.fhir.report/pom.xml index c0c0a6af2..990d2b2a9 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.3.24 + 6.3.25-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.utilities/pom.xml b/org.hl7.fhir.utilities/pom.xml index 2471e5442..b2817b460 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.3.24 + 6.3.25-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.validation.cli/pom.xml b/org.hl7.fhir.validation.cli/pom.xml index 65839379b..e0b001a4a 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.3.24 + 6.3.25-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.validation/pom.xml b/org.hl7.fhir.validation/pom.xml index d20acce66..1dcd143bb 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.3.24 + 6.3.25-SNAPSHOT ../pom.xml diff --git a/pom.xml b/pom.xml index 5cbe8d761..4f8248ecc 100644 --- a/pom.xml +++ b/pom.xml @@ -14,7 +14,7 @@ HAPI FHIR --> org.hl7.fhir.core - 6.3.24 + 6.3.25-SNAPSHOT pom From 44464de8077de575b1530b14aa770fd050fb88c2 Mon Sep 17 00:00:00 2001 From: dotasek Date: Tue, 10 Sep 2024 09:38:02 -0400 Subject: [PATCH 29/50] Remove cqlframework dependencies --- org.hl7.fhir.validation/pom.xml | 31 ------------------- .../instance/InstanceValidator.java | 2 +- .../validation/special/TxTesterSorters.java | 4 +-- 3 files changed, 3 insertions(+), 34 deletions(-) diff --git a/org.hl7.fhir.validation/pom.xml b/org.hl7.fhir.validation/pom.xml index 1dcd143bb..cc68b5cb2 100644 --- a/org.hl7.fhir.validation/pom.xml +++ b/org.hl7.fhir.validation/pom.xml @@ -119,37 +119,6 @@ true - - - info.cqframework - cql - ${info_cqframework_version} - - - info.cqframework - model - ${info_cqframework_version} - - - info.cqframework - elm - ${info_cqframework_version} - - - info.cqframework - cql-to-elm - ${info_cqframework_version} - - - info.cqframework - quick - ${info_cqframework_version} - - - info.cqframework - qdm - ${info_cqframework_version} - com.squareup.okhttp3 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 dbc8eb164..302bc448d 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 @@ -46,7 +46,7 @@ import javax.annotation.Nonnull; import org.apache.commons.lang3.NotImplementedException; import org.apache.commons.lang3.StringUtils; import org.fhir.ucum.Decimal; -import org.hl7.elm.r1.Code; + import org.hl7.fhir.exceptions.DefinitionException; import org.hl7.fhir.exceptions.FHIRException; import org.hl7.fhir.exceptions.PathEngineException; diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/special/TxTesterSorters.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/special/TxTesterSorters.java index 35d069e8a..a85c4db8b 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/special/TxTesterSorters.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/special/TxTesterSorters.java @@ -8,10 +8,10 @@ import java.util.Collections; import java.util.Comparator; import java.util.List; -import org.hl7.fhir.ParametersParameter; + import org.hl7.fhir.r5.formats.IParser.OutputStyle; import org.hl7.fhir.r5.formats.JsonParser; -import org.hl7.fhir.r5.model.Base; + import org.hl7.fhir.r5.model.Extension; import org.hl7.fhir.r5.model.OperationOutcome; import org.hl7.fhir.r5.model.OperationOutcome.OperationOutcomeIssueComponent; From bc0303535a02697c9cc942c6fcf83cfebbdf5924 Mon Sep 17 00:00:00 2001 From: dotasek Date: Wed, 11 Sep 2024 12:05:17 -0400 Subject: [PATCH 30/50] Fix for cache init on existing directories (#1743) * Add tests+fix for cache init on existing directories * Clear the cache if it is the wrong version * Link to FHIR spec docs for .index.json --- .../npm/FilesystemPackageCacheManager.java | 22 ++-- .../hl7/fhir/utilities/npm/NpmPackage.java | 12 +- .../npm/FilesystemPackageManagerTests.java | 118 +++++++++++++++++- 3 files changed, 140 insertions(+), 12 deletions(-) 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 df192cc19..ec0495874 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 @@ -210,26 +210,30 @@ public class FilesystemPackageCacheManager extends BasePackageCacheManager imple Utilities.createDirectory(cacheFolder.getAbsolutePath()); createIniFile(); } else { - if (!isCacheFolderValid()) { + if (!iniFileExists()) { + createIniFile(); + } + if (!isIniFileCurrentVersion()) { clearCache(); createIniFile(); - } else { - deleteOldTempDirectories(); } + deleteOldTempDirectories(); } return null; }); } - private boolean isCacheFolderValid() throws IOException { + private boolean iniFileExists() throws IOException { String iniPath = getPackagesIniPath(); File iniFile = ManagedFileAccess.file(iniPath); - if (!(iniFile.exists())) { - return false; - } + return iniFile.exists(); + } + + private boolean isIniFileCurrentVersion() throws IOException { + String iniPath = getPackagesIniPath(); IniFile ini = new IniFile(iniPath); - String v = ini.getStringProperty("cache", "version"); - return CACHE_VERSION.equals(v); + String version = ini.getStringProperty("cache", "version"); + return CACHE_VERSION.equals(version); } private void deleteOldTempDirectories() throws IOException { diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/npm/NpmPackage.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/npm/NpmPackage.java index 5ab8a9113..f599f6758 100644 --- a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/npm/NpmPackage.java +++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/npm/NpmPackage.java @@ -648,7 +648,17 @@ public class NpmPackage { } - + /** + * Create a package .index.json file for a package folder. + *

+ * See the FHIR specification for details on .index.json + * format and usage. + * + * @param desc + * @param folder + * @throws FileNotFoundException + * @throws IOException + */ public void indexFolder(String desc, NpmPackageFolder folder) throws FileNotFoundException, IOException { List remove = new ArrayList<>(); NpmPackageIndexBuilder indexer = new NpmPackageIndexBuilder(); diff --git a/org.hl7.fhir.utilities/src/test/java/org/hl7/fhir/utilities/npm/FilesystemPackageManagerTests.java b/org.hl7.fhir.utilities/src/test/java/org/hl7/fhir/utilities/npm/FilesystemPackageManagerTests.java index 96754c2b8..eba7b198a 100644 --- a/org.hl7.fhir.utilities/src/test/java/org/hl7/fhir/utilities/npm/FilesystemPackageManagerTests.java +++ b/org.hl7.fhir.utilities/src/test/java/org/hl7/fhir/utilities/npm/FilesystemPackageManagerTests.java @@ -1,22 +1,25 @@ package org.hl7.fhir.utilities.npm; +import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import java.io.File; +import java.io.FileWriter; import java.io.IOException; import java.nio.file.Files; import java.util.ArrayList; import java.util.List; import java.util.Random; +import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Stream; import javax.annotation.Nonnull; +import org.hl7.fhir.utilities.IniFile; import org.hl7.fhir.utilities.filesystem.ManagedFileAccess; -import org.junit.jupiter.api.RepeatedTest; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.condition.DisabledOnOs; import org.junit.jupiter.api.condition.EnabledOnOs; @@ -100,7 +103,6 @@ public class FilesystemPackageManagerTests { @DisabledOnOs(OS.WINDOWS) public void testSystemCacheDirectory() throws IOException { File folder = new FilesystemPackageCacheManager.Builder().withSystemCacheFolder().getCacheFolder(); - assertEquals( "/var/lib/.fhir/packages", folder.getAbsolutePath()); } @@ -124,6 +126,118 @@ public class FilesystemPackageManagerTests { return params.stream(); } + private void createDummyTemp(File cacheDirectory, String lowerCase) throws IOException { + createDummyPackage(cacheDirectory, lowerCase); + } + + private void createDummyPackage(File cacheDirectory, String packageName, String packageVersion) throws IOException { + String directoryName = packageName + "#" + packageVersion; + createDummyPackage(cacheDirectory, directoryName); + } + + private static void createDummyPackage(File cacheDirectory, String directoryName) throws IOException { + File packageDirectory = ManagedFileAccess.file(cacheDirectory.getAbsolutePath(), directoryName); + packageDirectory.mkdirs(); + + File dummyContentFile = ManagedFileAccess.file(packageDirectory.getAbsolutePath(), "dummy.txt"); + FileWriter wr = new FileWriter(dummyContentFile); + wr.write("Ain't nobody here but us chickens"); + wr.flush(); + wr.close(); + } + + private void assertThatDummyTempExists(File cacheDirectory, String dummyTempPackage) throws IOException { + File dummyTempDirectory = ManagedFileAccess.file(cacheDirectory.getAbsolutePath(), dummyTempPackage); + assertThat(dummyTempDirectory).exists(); + + File dummyContentFile = ManagedFileAccess.file(dummyTempDirectory.getAbsolutePath(), "dummy.txt"); + assertThat(dummyContentFile).exists(); + } + + @Test + public void testCreatesIniIfDoesntExistAndCacheStaysIntact() throws IOException { + File cacheDirectory = ManagedFileAccess.fromPath(Files.createTempDirectory("fpcm-multithreadingTest")); + File cacheIni = ManagedFileAccess.file(cacheDirectory.getAbsolutePath(), "packages.ini"); + + createDummyPackage(cacheDirectory, "example.fhir.uv.myig", "1.2.3"); + + String dummyTempPackage = UUID.randomUUID().toString().toLowerCase(); + createDummyTemp(cacheDirectory, dummyTempPackage); + assertThatDummyTempExists(cacheDirectory, dummyTempPackage); + + assertThat(cacheIni).doesNotExist(); + FilesystemPackageCacheManager filesystemPackageCacheManager = new FilesystemPackageCacheManager.Builder().withCacheFolder(cacheDirectory.getAbsolutePath()).build(); + assertInitializedTestCacheIsValid(cacheDirectory, true); + } + + + + @Test + public void testClearsCacheIfVersionIsWrong() throws IOException { + File cacheDirectory = ManagedFileAccess.fromPath(Files.createTempDirectory("fpcm-multithreadingTest")); + File cacheIni = ManagedFileAccess.file(cacheDirectory.getAbsolutePath(), "packages.ini"); + + createDummyPackage(cacheDirectory, "example.fhir.uv.myig", "1.2.3"); + String dummyTempPackage = UUID.randomUUID().toString().toLowerCase(); + createDummyTemp(cacheDirectory, dummyTempPackage); + assertThatDummyTempExists(cacheDirectory, dummyTempPackage); + + + IniFile ini = new IniFile(cacheIni.getAbsolutePath()); + ini.setStringProperty("cache", "version", "2", null); + ini.save(); + + assertThat(cacheIni).exists(); + FilesystemPackageCacheManager filesystemPackageCacheManager = new FilesystemPackageCacheManager.Builder().withCacheFolder(cacheDirectory.getAbsolutePath()).build(); + assertInitializedTestCacheIsValid(cacheDirectory, false); + } + + @Test + public void testCacheStaysIntactIfVersionIsTheSame() throws IOException { + File cacheDirectory = ManagedFileAccess.fromPath(Files.createTempDirectory("fpcm-multithreadingTest")); + File cacheIni = ManagedFileAccess.file(cacheDirectory.getAbsolutePath(), "packages.ini"); + + createDummyPackage(cacheDirectory, "example.fhir.uv.myig", "1.2.3"); + String dummyTempPackage = UUID.randomUUID().toString().toLowerCase(); + createDummyTemp(cacheDirectory, dummyTempPackage); + assertThatDummyTempExists(cacheDirectory, dummyTempPackage); + + + IniFile ini = new IniFile(cacheIni.getAbsolutePath()); + ini.setStringProperty("cache", "version", "3", null); + ini.save(); + + assertThat(cacheIni).exists(); + FilesystemPackageCacheManager filesystemPackageCacheManager = new FilesystemPackageCacheManager.Builder().withCacheFolder(cacheDirectory.getAbsolutePath()).build(); + assertInitializedTestCacheIsValid(cacheDirectory, true); + } + + private void assertInitializedTestCacheIsValid(File cacheDirectory, boolean dummyPackageShouldExist) throws IOException { + assertThat(cacheDirectory).exists(); + File iniFile = ManagedFileAccess.file(cacheDirectory.getAbsolutePath(), "packages.ini"); + assertThat(ManagedFileAccess.file(cacheDirectory.getAbsolutePath(), "packages.ini")).exists(); + IniFile ini = new IniFile(iniFile.getAbsolutePath()); + String version = ini.getStringProperty("cache", "version"); + assertThat(version).isEqualTo("3"); + + File[] files = cacheDirectory.listFiles(); + if (dummyPackageShouldExist) { + // Check that only packages.ini and our dummy package are in the cache. Our previous temp should be deleted. + assertThat(files).hasSize(2); // packages.ini and example.fhir.uv.myig#1.2.3 (directory) + + File dummyPackage = ManagedFileAccess.file(cacheDirectory.getAbsolutePath(), "example.fhir.uv.myig#1.2.3"); + assertThat(dummyPackage).exists(); + + File dummyContentFile = ManagedFileAccess.file(dummyPackage.getAbsolutePath(), "dummy.txt"); + assertThat(dummyContentFile).exists(); + } else { + // Check that only packages.ini is in the cache. + assertThat(files).hasSize(1); + } + + + } + @MethodSource("packageCacheMultiThreadTestParams") @ParameterizedTest public void packageCacheMultiThreadTest(final int threadTotal, final int packageCacheManagerTotal) throws IOException { From 3524fd78c7e306f470a4ce1c25d545590d0d1040 Mon Sep 17 00:00:00 2001 From: dotasek Date: Wed, 11 Sep 2024 12:06:49 -0400 Subject: [PATCH 31/50] Update RELEASE_NOTES.md ***NO_CI*** --- RELEASE_NOTES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 7b06c6ab5..f965d2ad5 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -4,4 +4,4 @@ ## Other code changes -* no changes \ No newline at end of file +* Fix logic for cache clearing on package cache initialization From f09bc48f7d3c3e165c39ad66b1747ce3bb8d8b11 Mon Sep 17 00:00:00 2001 From: markiantorno Date: Wed, 11 Sep 2024 17:40:08 +0000 Subject: [PATCH 32/50] Release: v6.3.25 ## Validator Changes * no changes ## Other code changes * Fix logic for cache clearing on package cache initialization ***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 370eb607f..7b91b779c 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.3.25-SNAPSHOT + 6.3.25 ../pom.xml diff --git a/org.hl7.fhir.dstu2/pom.xml b/org.hl7.fhir.dstu2/pom.xml index 317170b7b..3933f0255 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.3.25-SNAPSHOT + 6.3.25 ../pom.xml diff --git a/org.hl7.fhir.dstu2016may/pom.xml b/org.hl7.fhir.dstu2016may/pom.xml index c804e1719..aff212b64 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.3.25-SNAPSHOT + 6.3.25 ../pom.xml diff --git a/org.hl7.fhir.dstu3/pom.xml b/org.hl7.fhir.dstu3/pom.xml index 0e79f835a..67d2867d9 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.3.25-SNAPSHOT + 6.3.25 ../pom.xml diff --git a/org.hl7.fhir.r4/pom.xml b/org.hl7.fhir.r4/pom.xml index 032363f4c..2451791b8 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.3.25-SNAPSHOT + 6.3.25 ../pom.xml diff --git a/org.hl7.fhir.r4b/pom.xml b/org.hl7.fhir.r4b/pom.xml index 147230f24..5606df2e1 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.3.25-SNAPSHOT + 6.3.25 ../pom.xml diff --git a/org.hl7.fhir.r5/pom.xml b/org.hl7.fhir.r5/pom.xml index 7e6fb6a09..74651cb14 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.3.25-SNAPSHOT + 6.3.25 ../pom.xml diff --git a/org.hl7.fhir.report/pom.xml b/org.hl7.fhir.report/pom.xml index 990d2b2a9..36f4c16a5 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.3.25-SNAPSHOT + 6.3.25 ../pom.xml diff --git a/org.hl7.fhir.utilities/pom.xml b/org.hl7.fhir.utilities/pom.xml index b2817b460..b43b89875 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.3.25-SNAPSHOT + 6.3.25 ../pom.xml diff --git a/org.hl7.fhir.validation.cli/pom.xml b/org.hl7.fhir.validation.cli/pom.xml index e0b001a4a..873bb1d94 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.3.25-SNAPSHOT + 6.3.25 ../pom.xml diff --git a/org.hl7.fhir.validation/pom.xml b/org.hl7.fhir.validation/pom.xml index 1dcd143bb..b59bfc076 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.3.25-SNAPSHOT + 6.3.25 ../pom.xml diff --git a/pom.xml b/pom.xml index 4f8248ecc..abf77b819 100644 --- a/pom.xml +++ b/pom.xml @@ -14,7 +14,7 @@ HAPI FHIR --> org.hl7.fhir.core - 6.3.25-SNAPSHOT + 6.3.25 pom From 4af3deff26023c8dd7242b136145b3c0754795be Mon Sep 17 00:00:00 2001 From: markiantorno Date: Wed, 11 Sep 2024 18:28:22 +0000 Subject: [PATCH 33/50] Updating version to: 6.3.26-SNAPSHOT and incrementing test cases dependency. --- RELEASE_NOTES.md | 2 +- 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, 13 insertions(+), 13 deletions(-) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index f965d2ad5..7b06c6ab5 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -4,4 +4,4 @@ ## Other code changes -* Fix logic for cache clearing on package cache initialization +* 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 7b91b779c..497a67ca5 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.3.25 + 6.3.26-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.dstu2/pom.xml b/org.hl7.fhir.dstu2/pom.xml index 3933f0255..1ef5e9c18 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.3.25 + 6.3.26-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.dstu2016may/pom.xml b/org.hl7.fhir.dstu2016may/pom.xml index aff212b64..10836492e 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.3.25 + 6.3.26-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.dstu3/pom.xml b/org.hl7.fhir.dstu3/pom.xml index 67d2867d9..9b9f1ede2 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.3.25 + 6.3.26-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.r4/pom.xml b/org.hl7.fhir.r4/pom.xml index 2451791b8..bc3634f35 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.3.25 + 6.3.26-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.r4b/pom.xml b/org.hl7.fhir.r4b/pom.xml index 5606df2e1..df709cb6a 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.3.25 + 6.3.26-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.r5/pom.xml b/org.hl7.fhir.r5/pom.xml index 74651cb14..8bb7cfbb9 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.3.25 + 6.3.26-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.report/pom.xml b/org.hl7.fhir.report/pom.xml index 36f4c16a5..f0adc1c86 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.3.25 + 6.3.26-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.utilities/pom.xml b/org.hl7.fhir.utilities/pom.xml index b43b89875..e4d08a59f 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.3.25 + 6.3.26-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.validation.cli/pom.xml b/org.hl7.fhir.validation.cli/pom.xml index 873bb1d94..54e5ebfa8 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.3.25 + 6.3.26-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.validation/pom.xml b/org.hl7.fhir.validation/pom.xml index b59bfc076..d2b328684 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.3.25 + 6.3.26-SNAPSHOT ../pom.xml diff --git a/pom.xml b/pom.xml index abf77b819..23d34f2b9 100644 --- a/pom.xml +++ b/pom.xml @@ -14,7 +14,7 @@ HAPI FHIR --> org.hl7.fhir.core - 6.3.25 + 6.3.26-SNAPSHOT pom From 337aaf80cfa83946d5fe5266a8c78dcfd3e20eff Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Thu, 12 Sep 2024 11:54:40 +0800 Subject: [PATCH 34/50] Process relative URLs properly in base when generating snapshots --- .../profile/ProfilePathProcessor.java | 24 ++++++++--------- .../conformance/profile/ProfileUtilities.java | 27 ++++++++++--------- 2 files changed, 26 insertions(+), 25 deletions(-) diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/conformance/profile/ProfilePathProcessor.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/conformance/profile/ProfilePathProcessor.java index 6a939f95a..a26d81569 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/conformance/profile/ProfilePathProcessor.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/conformance/profile/ProfilePathProcessor.java @@ -289,7 +289,7 @@ public class ProfilePathProcessor { start++; } else { // we're just going to accept the differential slicing at face value - ElementDefinition outcome = profileUtilities.updateURLs(getUrl(), getWebUrl(), currentBase.copy()); + ElementDefinition outcome = profileUtilities.updateURLs(getUrl(), getWebUrl(), currentBase.copy(), true); outcome.setPath(profileUtilities.fixedPathDest(getContextPathTarget(), outcome.getPath(), getRedirector(), getContextPathSource())); profileUtilities.updateFromBase(outcome, currentBase, getSourceStructureDefinition().getUrl()); @@ -667,14 +667,14 @@ public class ProfilePathProcessor { // some of what's in currentBase overrides template template = profileUtilities.fillOutFromBase(template, currentBase); - ElementDefinition outcome = profileUtilities.updateURLs(getUrl(), getWebUrl(), template); + ElementDefinition outcome = profileUtilities.updateURLs(getUrl(), getWebUrl(), template, true); outcome.setPath(profileUtilities.fixedPathDest(getContextPathTarget(), outcome.getPath(), getRedirector(), getContextPathSource())); res = outcome; profileUtilities.updateFromBase(outcome, currentBase, getSourceStructureDefinition().getUrl()); if (diffMatches.get(0).hasSliceName()) { template = currentBase.copy(); - template = profileUtilities.updateURLs(getUrl(), getWebUrl(), template); + template = profileUtilities.updateURLs(getUrl(), getWebUrl(), template, true); template.setPath(profileUtilities.fixedPathDest(getContextPathTarget(), template.getPath(), getRedirector(), getContextPathSource())); checkToSeeIfSlicingExists(diffMatches.get(0), template); @@ -866,13 +866,13 @@ public class ProfilePathProcessor { private void processSimplePathWithEmptyDiffMatches(ElementDefinition currentBase, String currentBasePath, List diffMatches, ProfilePathProcessorState cursors, MappingAssistant mapHelper) { - ElementDefinition outcome = profileUtilities.updateURLs(getUrl(), getWebUrl(), currentBase.copy()); + ElementDefinition outcome = profileUtilities.updateURLs(getUrl(), getWebUrl(), currentBase.copy(), true); outcome.setPath(profileUtilities.fixedPathDest(getContextPathTarget(), outcome.getPath(), getRedirector(), getContextPathSource())); profileUtilities.updateFromBase(outcome, currentBase, getSourceStructureDefinition().getUrl()); profileUtilities.updateConstraintSources(outcome, getSourceStructureDefinition().getUrl()); profileUtilities.checkExtensions(outcome); profileUtilities.updateFromObligationProfiles(outcome); - profileUtilities.updateURLs(url, webUrl, outcome); + profileUtilities.updateURLs(url, webUrl, outcome, true); profileUtilities.markDerived(outcome); if (cursors.resultPathBase == null) cursors.resultPathBase = outcome.getPath(); @@ -1033,7 +1033,7 @@ public class ProfilePathProcessor { if (!currentBase.isChoice() && !profileUtilities.ruleMatches(dSlice.getRules(), bSlice.getRules())) throw new DefinitionException(profileUtilities.getContext().formatMessage(I18nConstants.SLICING_RULES_ON_DIFFERENTIAL__DO_NOT_MATCH_THOSE_ON_BASE___RULE___, profileUtilities.summarizeSlicing(dSlice), profileUtilities.summarizeSlicing(bSlice), path, cursors.contextName)); } - ElementDefinition outcome = profileUtilities.updateURLs(getUrl(), getWebUrl(), currentBase.copy()); + ElementDefinition outcome = profileUtilities.updateURLs(getUrl(), getWebUrl(), currentBase.copy(), true); outcome.setPath(profileUtilities.fixedPathDest(getContextPathTarget(), outcome.getPath(), getRedirector(), getContextPathSource())); profileUtilities.updateFromBase(outcome, currentBase, getSourceStructureDefinition().getUrl()); if (diffMatches.get(0).hasSlicing() || !diffMatches.get(0).hasSliceName()) { @@ -1095,7 +1095,7 @@ public class ProfilePathProcessor { // We need to copy children of the backbone element before we start messing around with slices int newBaseLimit = profileUtilities.findEndOfElement(cursors.base, cursors.baseCursor); for (int i = cursors.baseCursor + 1; i <= newBaseLimit; i++) { - outcome = profileUtilities.updateURLs(getUrl(), getWebUrl(), cursors.base.getElement().get(i).copy()); + outcome = profileUtilities.updateURLs(getUrl(), getWebUrl(), cursors.base.getElement().get(i).copy(), true); outcome.setPath(profileUtilities.fixedPathDest(getContextPathTarget(), outcome.getPath(), getRedirector(), getContextPathSource())); debugCheck(outcome); getResult().getElement().add(outcome); @@ -1106,7 +1106,7 @@ public class ProfilePathProcessor { List baseMatches = profileUtilities.getSiblings(cursors.base.getElement(), currentBase); for (ElementDefinition baseItem : baseMatches) { cursors.baseCursor = cursors.base.getElement().indexOf(baseItem); - outcome = profileUtilities.updateURLs(getUrl(), getWebUrl(), baseItem.copy()); + outcome = profileUtilities.updateURLs(getUrl(), getWebUrl(), baseItem.copy(), true); profileUtilities.updateFromBase(outcome, currentBase, getSourceStructureDefinition().getUrl()); outcome.setPath(profileUtilities.fixedPathDest(getContextPathTarget(), outcome.getPath(), getRedirector(), getContextPathSource())); outcome.setSlicing(null); @@ -1139,7 +1139,7 @@ public class ProfilePathProcessor { cursors.baseCursor++; // just copy any children on the base while (cursors.baseCursor < cursors.base.getElement().size() && cursors.base.getElement().get(cursors.baseCursor).getPath().startsWith(path) && !cursors.base.getElement().get(cursors.baseCursor).getPath().equals(path)) { - outcome = profileUtilities.updateURLs(getUrl(), getWebUrl(), cursors.base.getElement().get(cursors.baseCursor).copy()); + outcome = profileUtilities.updateURLs(getUrl(), getWebUrl(), cursors.base.getElement().get(cursors.baseCursor).copy(), true); outcome.setPath(profileUtilities.fixedPathDest(getContextPathTarget(), outcome.getPath(), getRedirector(), getContextPathSource())); if (!outcome.getPath().startsWith(cursors.resultPathBase)) throw new DefinitionException(profileUtilities.getContext().formatMessage(I18nConstants.ADDING_WRONG_PATH)); @@ -1166,7 +1166,7 @@ public class ProfilePathProcessor { for (ElementDefinition baseItem : baseMatches) if (baseItem.getSliceName().equals(diffItem.getSliceName())) throw new DefinitionException(profileUtilities.getContext().formatMessage(I18nConstants.NAMED_ITEMS_ARE_OUT_OF_ORDER_IN_THE_SLICE)); - outcome = profileUtilities.updateURLs(getUrl(), getWebUrl(), currentBase.copy()); + outcome = profileUtilities.updateURLs(getUrl(), getWebUrl(), currentBase.copy(), true); // outcome = updateURLs(url, diffItem.copy()); outcome.setPath(profileUtilities.fixedPathDest(getContextPathTarget(), outcome.getPath(), getRedirector(), getContextPathSource())); profileUtilities.updateFromBase(outcome, currentBase, getSourceStructureDefinition().getUrl()); @@ -1409,7 +1409,7 @@ public class ProfilePathProcessor { private void processPathWithSlicedBaseAndEmptyDiffMatches(ElementDefinition currentBase, String currentBasePath, List diffMatches, ProfilePathProcessorState cursors, String path, MappingAssistant mapHelper) { if (profileUtilities.hasInnerDiffMatches(getDifferential(), path, cursors.diffCursor, getDiffLimit(), cursors.base.getElement(), true)) { // so we just copy it in - ElementDefinition outcome = profileUtilities.updateURLs(getUrl(), getWebUrl(), currentBase.copy()); + ElementDefinition outcome = profileUtilities.updateURLs(getUrl(), getWebUrl(), currentBase.copy(), true); outcome.setPath(profileUtilities.fixedPathDest(getContextPathTarget(), outcome.getPath(), getRedirector(), getContextPathSource())); profileUtilities.updateFromBase(outcome, currentBase, getSourceStructureDefinition().getUrl()); profileUtilities.markDerived(outcome); @@ -1457,7 +1457,7 @@ public class ProfilePathProcessor { // the differential doesn't say anything about this item // copy across the currentbase, and all of its children and siblings while (cursors.baseCursor < cursors.base.getElement().size() && cursors.base.getElement().get(cursors.baseCursor).getPath().startsWith(path)) { - ElementDefinition outcome = profileUtilities.updateURLs(getUrl(), getWebUrl(), cursors.base.getElement().get(cursors.baseCursor).copy()); + ElementDefinition outcome = profileUtilities.updateURLs(getUrl(), getWebUrl(), cursors.base.getElement().get(cursors.baseCursor).copy(), true); outcome.setPath(profileUtilities.fixedPathDest(getContextPathTarget(), outcome.getPath(), getRedirector(), getContextPathSource())); if (!outcome.getPath().startsWith(cursors.resultPathBase)) throw new DefinitionException(profileUtilities.getContext().formatMessage(I18nConstants.ADDING_WRONG_PATH_IN_PROFILE___VS_, getProfileName(), outcome.getPath(), cursors.resultPathBase)); diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/conformance/profile/ProfileUtilities.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/conformance/profile/ProfileUtilities.java index 79d668b36..7a75e0358 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/conformance/profile/ProfileUtilities.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/conformance/profile/ProfileUtilities.java @@ -739,7 +739,7 @@ public class ProfileUtilities { if (existing != null) { updateFromDefinition(existing, e, profileName, false, url, base, derived, "StructureDefinition.differential.element["+i+"]", mappingDetails); } else { - ElementDefinition outcome = updateURLs(url, webUrl, e.copy()); + ElementDefinition outcome = updateURLs(url, webUrl, e.copy(), true); e.setUserData(UD_GENERATED_IN_SNAPSHOT, outcome); derived.getSnapshot().addElement(outcome); if (walksInto(diff.getElement(), e)) { @@ -1042,7 +1042,7 @@ public class ProfileUtilities { // don't do this. should already be in snapshot ... addInheritedElementsForSpecialization(snapshot, focus, sd.getBaseDefinition(), path, url, weburl); for (ElementDefinition ed : sd.getSnapshot().getElement()) { if (ed.getPath().contains(".")) { - ElementDefinition outcome = updateURLs(url, weburl, ed.copy()); + ElementDefinition outcome = updateURLs(url, weburl, ed.copy(), true); outcome.setPath(outcome.getPath().replace(sd.getTypeName(), path)); snapshot.getElement().add(outcome); } else { @@ -1548,7 +1548,6 @@ public class ProfileUtilities { protected void removeStatusExtensions(ElementDefinition outcome) { outcome.removeExtension(ToolingExtensions.EXT_FMM_LEVEL); outcome.removeExtension(ToolingExtensions.EXT_FMM_SUPPORT); - outcome.removeExtension(ToolingExtensions.EXT_FMM_DERIVED); outcome.removeExtension(ToolingExtensions.EXT_STANDARDS_STATUS); outcome.removeExtension(ToolingExtensions.EXT_NORMATIVE_VERSION); outcome.removeExtension(ToolingExtensions.EXT_WORKGROUP); @@ -1911,7 +1910,7 @@ public class ProfileUtilities { * @param element - the Element to update * @return - the updated Element */ - public ElementDefinition updateURLs(String url, String webUrl, ElementDefinition element) { + public ElementDefinition updateURLs(String url, String webUrl, ElementDefinition element, boolean processRelatives) { if (element != null) { ElementDefinition defn = element; if (defn.hasBinding() && defn.getBinding().hasValueSet() && defn.getBinding().getValueSet().startsWith("#")) @@ -1929,24 +1928,24 @@ public class ProfileUtilities { if (webUrl != null) { // also, must touch up the markdown if (element.hasDefinition()) { - element.setDefinition(processRelativeUrls(element.getDefinition(), webUrl, context.getSpecUrl(), context.getResourceNames(), masterSourceFileNames, localFileNames, false)); + element.setDefinition(processRelativeUrls(element.getDefinition(), webUrl, context.getSpecUrl(), context.getResourceNames(), masterSourceFileNames, localFileNames, processRelatives)); } if (element.hasComment()) { - element.setComment(processRelativeUrls(element.getComment(), webUrl, context.getSpecUrl(), context.getResourceNames(), masterSourceFileNames, localFileNames, false)); + element.setComment(processRelativeUrls(element.getComment(), webUrl, context.getSpecUrl(), context.getResourceNames(), masterSourceFileNames, localFileNames, processRelatives)); } if (element.hasRequirements()) { - element.setRequirements(processRelativeUrls(element.getRequirements(), webUrl, context.getSpecUrl(), context.getResourceNames(), masterSourceFileNames, localFileNames, false)); + element.setRequirements(processRelativeUrls(element.getRequirements(), webUrl, context.getSpecUrl(), context.getResourceNames(), masterSourceFileNames, localFileNames, processRelatives)); } if (element.hasMeaningWhenMissing()) { - element.setMeaningWhenMissing(processRelativeUrls(element.getMeaningWhenMissing(), webUrl, context.getSpecUrl(), context.getResourceNames(), masterSourceFileNames, localFileNames, false)); + element.setMeaningWhenMissing(processRelativeUrls(element.getMeaningWhenMissing(), webUrl, context.getSpecUrl(), context.getResourceNames(), masterSourceFileNames, localFileNames, processRelatives)); } if (element.hasBinding() && element.getBinding().hasDescription()) { - element.getBinding().setDescription(processRelativeUrls(element.getBinding().getDescription(), webUrl, context.getSpecUrl(), context.getResourceNames(), masterSourceFileNames, localFileNames, false)); + element.getBinding().setDescription(processRelativeUrls(element.getBinding().getDescription(), webUrl, context.getSpecUrl(), context.getResourceNames(), masterSourceFileNames, localFileNames, processRelatives)); } for (Extension ext : element.getExtension()) { if (ext.hasValueMarkdownType()) { MarkdownType md = ext.getValueMarkdownType(); - md.setValue(processRelativeUrls(md.getValue(), webUrl, context.getSpecUrl(), context.getResourceNames(), masterSourceFileNames, localFileNames, false)); + md.setValue(processRelativeUrls(md.getValue(), webUrl, context.getSpecUrl(), context.getResourceNames(), masterSourceFileNames, localFileNames, processRelatives)); } } } @@ -2371,7 +2370,6 @@ public class ProfileUtilities { if (elist.size() == 2) { dest.getExtension().remove(elist.get(1)); } - updateExtensionsFromDefinition(dest, source); for (ElementDefinition ed : obligationProfileElements) { @@ -2423,6 +2421,9 @@ public class ProfileUtilities { if (e.hasDefinition()) { base.setDefinition(processRelativeUrls(e.getDefinition(), webroot, context.getSpecUrl(), context.getResourceNames(), masterSourceFileNames, localFileNames, true)); } + if (e.getBinding().hasDescription()) { + base.getBinding().setDescription(processRelativeUrls(e.getBinding().getDescription(), webroot, context.getSpecUrl(), context.getResourceNames(), masterSourceFileNames, localFileNames, true)); + } base.setShort(e.getShort()); if (e.hasCommentElement()) base.setCommentElement(e.getCommentElement()); @@ -2466,9 +2467,9 @@ public class ProfileUtilities { if (derived.hasDefinitionElement()) { if (derived.getDefinition().startsWith("...")) base.setDefinition(Utilities.appendDerivedTextToBase(base.getDefinition(), derived.getDefinition())); - else if (!Base.compareDeep(derived.getDefinitionElement(), base.getDefinitionElement(), false)) + else if (!Base.compareDeep(derived.getDefinitionElement(), base.getDefinitionElement(), false)) { base.setDefinitionElement(derived.getDefinitionElement().copy()); - else if (trimDifferential) + } else if (trimDifferential) derived.setDefinitionElement(null); else if (derived.hasDefinitionElement()) derived.getDefinitionElement().setUserData(UD_DERIVATION_EQUALS, true); From 8056dced3efb3a44d66178aa52351dac367dd389 Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Thu, 12 Sep 2024 11:55:24 +0800 Subject: [PATCH 35/50] Allow JSON named extensions to be structure types other than logical --- .../main/java/org/hl7/fhir/r5/context/ContextUtilities.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/ContextUtilities.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/ContextUtilities.java index 02890a037..12bc847a2 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/ContextUtilities.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/ContextUtilities.java @@ -366,7 +366,11 @@ public class ContextUtilities implements ProfileKnowledgeProvider { public StructureDefinition fetchByJsonName(String key) { for (StructureDefinition sd : context.fetchResourcesByType(StructureDefinition.class)) { ElementDefinition ed = sd.getSnapshot().getElementFirstRep(); - if (sd.getKind() == StructureDefinitionKind.LOGICAL && ed != null && ed.hasExtension(ToolingExtensions.EXT_JSON_NAME, ToolingExtensions.EXT_JSON_NAME_DEPRECATED) && + if (/*sd.getKind() == StructureDefinitionKind.LOGICAL && */ + // this is turned off because it's valid to use a FHIR type directly in + // an extension of this kind, and that can't be a logical model. Any profile on + // a type is acceptable as long as it has the json name on it + ed != null && ed.hasExtension(ToolingExtensions.EXT_JSON_NAME, ToolingExtensions.EXT_JSON_NAME_DEPRECATED) && key.equals(ToolingExtensions.readStringExtension(ed, ToolingExtensions.EXT_JSON_NAME, ToolingExtensions.EXT_JSON_NAME_DEPRECATED))) { return sd; } From 07f1981a8c49d1843e1391977bddd33ff0b7e6ae Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Thu, 12 Sep 2024 11:56:04 +0800 Subject: [PATCH 36/50] Fix for NPE processing packages --- .../fhir/r5/renderers/StructureDefinitionRenderer.java | 2 +- .../main/java/org/hl7/fhir/utilities/npm/NpmPackage.java | 8 +++++--- pom.xml | 2 +- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/StructureDefinitionRenderer.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/StructureDefinitionRenderer.java index bcb245cc6..5e7b63d20 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/StructureDefinitionRenderer.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/StructureDefinitionRenderer.java @@ -3431,7 +3431,7 @@ public class StructureDefinitionRenderer extends ResourceRenderer { sdMapCache.put(url, sdCache); String webroot = sd.getUserString("webroot"); for (ElementDefinition e : sd.getSnapshot().getElement()) { - context.getProfileUtilities().updateURLs(sd.getUrl(), webroot, e); + context.getProfileUtilities().updateURLs(sd.getUrl(), webroot, e, false); sdCache.put(e.getId(), e); } } diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/npm/NpmPackage.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/npm/NpmPackage.java index 5ab8a9113..6daa184af 100644 --- a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/npm/NpmPackage.java +++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/npm/NpmPackage.java @@ -237,9 +237,11 @@ public class NpmPackage { public List listFiles() { List res = new ArrayList<>(); if (folder != null) { - for (File f : folder.listFiles()) { - if (!f.isDirectory() && !Utilities.existsInList(f.getName(), "package.json", ".index.json", ".index.db", ".oids.json", ".oids.db")) { - res.add(f.getName()); + if (folder.exists()) { + for (File f : folder.listFiles()) { + if (!f.isDirectory() && !Utilities.existsInList(f.getName(), "package.json", ".index.json", ".index.db", ".oids.json", ".oids.db")) { + res.add(f.getName()); + } } } } else { diff --git a/pom.xml b/pom.xml index 4f8248ecc..e842abb9d 100644 --- a/pom.xml +++ b/pom.xml @@ -21,7 +21,7 @@ 1.26.0 32.0.1-jre 6.4.1 - 1.5.21 + 1.5.22-SNAPSHOT 2.17.0 5.9.2 1.8.2 From 9dae4118ae843e3380d845ee0a29d6bc1d277f94 Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Sat, 14 Sep 2024 08:26:07 +0800 Subject: [PATCH 37/50] refactor error handling in ProfileUtilities --- .../conformance/profile/ProfileUtilities.java | 95 ++++++++++--------- 1 file changed, 48 insertions(+), 47 deletions(-) diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/conformance/profile/ProfileUtilities.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/conformance/profile/ProfileUtilities.java index 7a75e0358..bc8d243a2 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/conformance/profile/ProfileUtilities.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/conformance/profile/ProfileUtilities.java @@ -413,11 +413,10 @@ public class ProfileUtilities { // note that ProfileUtilities are used re-entrantly internally, so nothing with process state can be here private final IWorkerContext context; private FHIRPathEngine fpe; - private List messages; + private List messages = new ArrayList(); private List snapshotStack = new ArrayList(); private ProfileKnowledgeProvider pkp; // private boolean igmode; - private boolean exception; private ValidationOptions terminologyServiceOptions = new ValidationOptions(FhirPublication.R5); private boolean newSlicingProcessing; private String defWebRoot; @@ -431,11 +430,16 @@ public class ProfileUtilities { private MappingMergeModeOption mappingMergeMode = MappingMergeModeOption.APPEND; private boolean forPublication; private List obligationProfiles = new ArrayList<>(); + private boolean wantThrowExceptions; public ProfileUtilities(IWorkerContext context, List messages, ProfileKnowledgeProvider pkp, FHIRPathEngine fpe) { super(); this.context = context; - this.messages = messages; + if (messages != null) { + this.messages = messages; + } else { + wantThrowExceptions = true; + } this.pkp = pkp; this.fpe = fpe; @@ -447,7 +451,11 @@ public class ProfileUtilities { public ProfileUtilities(IWorkerContext context, List messages, ProfileKnowledgeProvider pkp) { super(); this.context = context; - this.messages = messages; + if (messages != null) { + this.messages = messages; + } else { + wantThrowExceptions = true; + } this.pkp = pkp; if (context != null) { this.fpe = new FHIRPathEngine(context, this); @@ -789,7 +797,7 @@ public class ProfileUtilities { ce++; if (e.hasId()) { String msg = "No match found for "+e.getId()+" in the generated snapshot: check that the path and definitions are legal in the differential (including order)"; - messages.add(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.VALUE, "StructureDefinition.differential.element["+i+"]", msg, ValidationMessage.IssueSeverity.ERROR)); + addMessage(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.VALUE, "StructureDefinition.differential.element["+i+"]", msg, ValidationMessage.IssueSeverity.ERROR)); } } i++; @@ -862,19 +870,19 @@ public class ProfileUtilities { slice.getFocus().setMin(count); } else { String msg = "The slice definition for "+slice.getFocus().getId()+" has a minimum of "+slice.getFocus().getMin()+" but the slices add up to a minimum of "+count; - messages.add(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.VALUE, + addMessage(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.VALUE, "StructureDefinition.snapshot.element["+slice.getIndex()+"]", msg, forPublication ? ValidationMessage.IssueSeverity.ERROR : ValidationMessage.IssueSeverity.INFORMATION).setIgnorableError(true)); } } count = slice.checkMax(); if (count > -1 && repeats) { String msg = "The slice definition for "+slice.getFocus().getId()+" has a maximum of "+slice.getFocus().getMax()+" but the slices add up to a maximum of "+count+". Check that this is what is intended"; - messages.add(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.VALUE, + addMessage(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.VALUE, "StructureDefinition.snapshot.element["+slice.getIndex()+"]", msg, ValidationMessage.IssueSeverity.INFORMATION)); } if (!slice.checkMinMax()) { String msg = "The slice definition for "+slice.getFocus().getId()+" has a maximum of "+slice.getFocus().getMax()+" which is less than the minimum of "+slice.getFocus().getMin(); - messages.add(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.VALUE, + addMessage(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.VALUE, "StructureDefinition.snapshot.element["+slice.getIndex()+"]", msg, ValidationMessage.IssueSeverity.WARNING)); } slices.remove(s); @@ -885,13 +893,13 @@ public class ProfileUtilities { } if (ed.hasSliceName() && !slices.containsKey(ed.getPath())) { String msg = "The element "+ed.getId()+" launches straight into slicing without the slicing being set up properly first"; - messages.add(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.VALUE, + addMessage(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.VALUE, "StructureDefinition.snapshot.element["+i+"]", msg, ValidationMessage.IssueSeverity.ERROR).setIgnorableError(true)); } if (ed.hasSliceName() && slices.containsKey(ed.getPath())) { if (!slices.get(ed.getPath()).count(ed, ed.getSliceName())) { String msg = "Duplicate slice name "+ed.getSliceName()+" on "+ed.getId()+" (["+i+"])"; - messages.add(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.VALUE, + addMessage(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.VALUE, "StructureDefinition.snapshot.element["+i+"]", msg, ValidationMessage.IssueSeverity.ERROR).setIgnorableError(true)); } } @@ -910,10 +918,8 @@ public class ProfileUtilities { } } if (sd == null) { - if (messages != null) { - messages.add(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.VALUE, + addMessage(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.VALUE, "StructureDefinition.snapshot.element["+i+"]", "The type of profile "+u.getValue()+" cannot be checked as the profile is not known", IssueSeverity.WARNING)); - } } else { String wt = t.getWorkingCode(); if (ed.getPath().equals("Bundle.entry.response.outcome")) { @@ -1012,13 +1018,15 @@ public class ProfileUtilities { } private void handleError(String url, String msg) { - if (exception) - throw new DefinitionException(msg); - else - messages.add(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.VALUE, url, msg, ValidationMessage.IssueSeverity.ERROR)); + addMessage(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.VALUE, url, msg, ValidationMessage.IssueSeverity.ERROR)); } - + private void addMessage(ValidationMessage msg) { + messages.add(msg); + if (msg.getLevel() == IssueSeverity.ERROR && wantThrowExceptions) { + throw new DefinitionException(msg.getMessage()); + } + } private void copyInheritedExtensions(StructureDefinition base, StructureDefinition derived, String webUrl) { @@ -2249,7 +2257,7 @@ public class ProfileUtilities { * Not sure we have enough information here to do the check properly. Might be better done when we're sorting the profile? if (i != start && result.isEmpty() && !path.startsWith(context.getElement().get(start).getPath())) - messages.add(new ValidationMessage(Source.ProfileValidator, IssueType.VALUE, "StructureDefinition.differential.element["+Integer.toString(start)+"]", "Error: unknown element '"+context.getElement().get(start).getPath()+"' (or it is out of order) in profile '"+url+"' (looking for '"+path+"')", IssueSeverity.WARNING)); + addMessage(new ValidationMessage(Source.ProfileValidator, IssueType.VALUE, "StructureDefinition.differential.element["+Integer.toString(start)+"]", "Error: unknown element '"+context.getElement().get(start).getPath()+"' (or it is out of order) in profile '"+url+"' (looking for '"+path+"')", IssueSeverity.WARNING)); */ result.add(context.getElement().get(i)); @@ -2529,7 +2537,7 @@ public class ProfileUtilities { if (derived.hasMinElement()) { if (!Base.compareDeep(derived.getMinElement(), base.getMinElement(), false)) { if (derived.getMin() < base.getMin() && !derived.hasSliceName()) // in a slice, minimum cardinality rules do not apply - messages.add(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.BUSINESSRULE, pn+"."+source.getPath(), "Element "+base.getPath()+": derived min ("+Integer.toString(derived.getMin())+") cannot be less than the base min ("+Integer.toString(base.getMin())+") in "+srcSD.getVersionedUrl(), ValidationMessage.IssueSeverity.ERROR)); + addMessage(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.BUSINESSRULE, pn+"."+source.getPath(), "Element "+base.getPath()+": derived min ("+Integer.toString(derived.getMin())+") cannot be less than the base min ("+Integer.toString(base.getMin())+") in "+srcSD.getVersionedUrl(), ValidationMessage.IssueSeverity.ERROR)); base.setMinElement(derived.getMinElement().copy()); } else if (trimDifferential) derived.setMinElement(null); @@ -2540,7 +2548,7 @@ public class ProfileUtilities { if (derived.hasMaxElement()) { if (!Base.compareDeep(derived.getMaxElement(), base.getMaxElement(), false)) { if (isLargerMax(derived.getMax(), base.getMax())) - messages.add(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.BUSINESSRULE, pn+"."+source.getPath(), "Element "+base.getPath()+": derived max ("+derived.getMax()+") cannot be greater than the base max ("+base.getMax()+")", ValidationMessage.IssueSeverity.ERROR)); + addMessage(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.BUSINESSRULE, pn+"."+source.getPath(), "Element "+base.getPath()+": derived max ("+derived.getMax()+") cannot be greater than the base max ("+base.getMax()+")", ValidationMessage.IssueSeverity.ERROR)); base.setMaxElement(derived.getMaxElement().copy()); } else if (trimDifferential) derived.setMaxElement(null); @@ -2642,7 +2650,7 @@ public class ProfileUtilities { } if (!(base.hasMustSupportElement() && Base.compareDeep(base.getMustSupportElement(), mse, false))) { if (base.hasMustSupport() && base.getMustSupport() && !derived.getMustSupport()) { - messages.add(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.BUSINESSRULE, pn+"."+derived.getPath(), "Illegal constraint [must-support = false] when [must-support = true] in the base profile", ValidationMessage.IssueSeverity.ERROR)); + addMessage(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.BUSINESSRULE, pn+"."+derived.getPath(), "Illegal constraint [must-support = false] when [must-support = true] in the base profile", ValidationMessage.IssueSeverity.ERROR)); } base.setMustSupportElement(mse); } else if (trimDifferential) @@ -2654,7 +2662,7 @@ public class ProfileUtilities { if (derived.hasMustHaveValueElement()) { if (!(base.hasMustHaveValueElement() && Base.compareDeep(derived.getMustHaveValueElement(), base.getMustHaveValueElement(), false))) { if (base.hasMustHaveValue() && base.getMustHaveValue() && !derived.getMustHaveValue()) { - messages.add(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.BUSINESSRULE, pn+"."+derived.getPath(), "Illegal constraint [must-have-value = false] when [must-have-value = true] in the base profile", ValidationMessage.IssueSeverity.ERROR)); + addMessage(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.BUSINESSRULE, pn+"."+derived.getPath(), "Illegal constraint [must-have-value = false] when [must-have-value = true] in the base profile", ValidationMessage.IssueSeverity.ERROR)); } base.setMustHaveValueElement(derived.getMustHaveValueElement().copy()); } else if (trimDifferential) @@ -2721,25 +2729,25 @@ public class ProfileUtilities { if (!base.hasBinding() || !Base.compareDeep(derived.getBinding(), base.getBinding(), false)) { if (base.hasBinding() && base.getBinding().getStrength() == BindingStrength.REQUIRED && derived.getBinding().getStrength() != BindingStrength.REQUIRED) - messages.add(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.BUSINESSRULE, pn+"."+derived.getPath(), "illegal attempt to change the binding on "+derived.getPath()+" from "+base.getBinding().getStrength().toCode()+" to "+derived.getBinding().getStrength().toCode(), ValidationMessage.IssueSeverity.ERROR)); + addMessage(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.BUSINESSRULE, pn+"."+derived.getPath(), "illegal attempt to change the binding on "+derived.getPath()+" from "+base.getBinding().getStrength().toCode()+" to "+derived.getBinding().getStrength().toCode(), ValidationMessage.IssueSeverity.ERROR)); // throw new DefinitionException("StructureDefinition "+pn+" at "+derived.getPath()+": illegal attempt to change a binding from "+base.getBinding().getStrength().toCode()+" to "+derived.getBinding().getStrength().toCode()); else if (base.hasBinding() && derived.hasBinding() && base.getBinding().getStrength() == BindingStrength.REQUIRED && base.getBinding().hasValueSet() && derived.getBinding().hasValueSet()) { ValueSet baseVs = context.findTxResource(ValueSet.class, base.getBinding().getValueSet(), srcSD); ValueSet contextVs = context.findTxResource(ValueSet.class, derived.getBinding().getValueSet(), derivedSrc); if (baseVs == null) { - messages.add(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.BUSINESSRULE, pn+"."+base.getPath(), "Binding "+base.getBinding().getValueSet()+" could not be located", ValidationMessage.IssueSeverity.WARNING)); + addMessage(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.BUSINESSRULE, pn+"."+base.getPath(), "Binding "+base.getBinding().getValueSet()+" could not be located", ValidationMessage.IssueSeverity.WARNING)); } else if (contextVs == null) { - messages.add(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.BUSINESSRULE, pn+"."+derived.getPath(), "Binding "+derived.getBinding().getValueSet()+" could not be located", ValidationMessage.IssueSeverity.WARNING)); + addMessage(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.BUSINESSRULE, pn+"."+derived.getPath(), "Binding "+derived.getBinding().getValueSet()+" could not be located", ValidationMessage.IssueSeverity.WARNING)); } else { ValueSetExpansionOutcome expBase = context.expandVS(baseVs, true, false); ValueSetExpansionOutcome expDerived = context.expandVS(contextVs, true, false); if (expBase.getValueset() == null) - messages.add(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.BUSINESSRULE, pn+"."+base.getPath(), "Binding "+base.getBinding().getValueSet()+" could not be expanded", ValidationMessage.IssueSeverity.WARNING)); + addMessage(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.BUSINESSRULE, pn+"."+base.getPath(), "Binding "+base.getBinding().getValueSet()+" could not be expanded", ValidationMessage.IssueSeverity.WARNING)); else if (expDerived.getValueset() == null) - messages.add(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.BUSINESSRULE, pn+"."+derived.getPath(), "Binding "+derived.getBinding().getValueSet()+" could not be expanded", ValidationMessage.IssueSeverity.WARNING)); + addMessage(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.BUSINESSRULE, pn+"."+derived.getPath(), "Binding "+derived.getBinding().getValueSet()+" could not be expanded", ValidationMessage.IssueSeverity.WARNING)); else if (ToolingExtensions.hasExtension(expBase.getValueset().getExpansion(), ToolingExtensions.EXT_EXP_TOOCOSTLY)) { if (ToolingExtensions.hasExtension(expDerived.getValueset().getExpansion(), ToolingExtensions.EXT_EXP_TOOCOSTLY) || expDerived.getValueset().getExpansion().getContains().size() > 100) { - messages.add(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.BUSINESSRULE, pn+"."+derived.getPath(), "Unable to check if "+derived.getBinding().getValueSet()+" is a proper subset of " +base.getBinding().getValueSet()+" - base value set is too large to check", ValidationMessage.IssueSeverity.WARNING)); + addMessage(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.BUSINESSRULE, pn+"."+derived.getPath(), "Unable to check if "+derived.getBinding().getValueSet()+" is a proper subset of " +base.getBinding().getValueSet()+" - base value set is too large to check", ValidationMessage.IssueSeverity.WARNING)); } else { boolean ok = true; for (ValueSetExpansionContainsComponent cc : expDerived.getValueset().getExpansion().getContains()) { @@ -2750,11 +2758,11 @@ public class ProfileUtilities { } } if (!ok) { - messages.add(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.BUSINESSRULE, pn+"."+derived.getPath(), "Binding "+derived.getBinding().getValueSet()+" is not a subset of binding "+base.getBinding().getValueSet(), ValidationMessage.IssueSeverity.ERROR)); + addMessage(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.BUSINESSRULE, pn+"."+derived.getPath(), "Binding "+derived.getBinding().getValueSet()+" is not a subset of binding "+base.getBinding().getValueSet(), ValidationMessage.IssueSeverity.ERROR)); } } } else if (!isSubset(expBase.getValueset(), expDerived.getValueset())) - messages.add(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.BUSINESSRULE, pn+"."+derived.getPath(), "Binding "+derived.getBinding().getValueSet()+" is not a subset of binding "+base.getBinding().getValueSet(), ValidationMessage.IssueSeverity.ERROR)); + addMessage(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.BUSINESSRULE, pn+"."+derived.getPath(), "Binding "+derived.getBinding().getValueSet()+" is not a subset of binding "+base.getBinding().getValueSet(), ValidationMessage.IssueSeverity.ERROR)); } } ElementDefinitionBindingComponent d = derived.getBinding(); @@ -2965,11 +2973,7 @@ public class ProfileUtilities { if (tgtOk) { ok = true; } else { - if (messages == null) { - throw new FHIRException(context.formatMessage(I18nConstants.ERROR_AT__THE_TARGET_PROFILE__IS_NOT__VALID_CONSTRAINT_ON_THE_BASE_, purl, derived.getPath(), url, td.getTargetProfile())); - } else { - messages.add(new ValidationMessage(Source.InstanceValidator, IssueType.BUSINESSRULE, derived.getPath(), "The target profile " + u.getValue() + " is not a valid constraint on the base (" + td.getTargetProfile() + ") at " + derived.getPath(), IssueSeverity.ERROR)); - } + addMessage(new ValidationMessage(Source.InstanceValidator, IssueType.BUSINESSRULE, derived.getPath(), context.formatMessage(I18nConstants.ERROR_AT__THE_TARGET_PROFILE__IS_NOT__VALID_CONSTRAINT_ON_THE_BASE_, purl, derived.getPath(), url, td.getTargetProfile()), IssueSeverity.ERROR)); } } } else { @@ -2989,9 +2993,7 @@ public class ProfileUtilities { } StructureDefinition sd = context.fetchResource(StructureDefinition.class, url); if (sd == null) { - if (messages != null) { - messages.add(new ValidationMessage(Source.InstanceValidator, IssueType.BUSINESSRULE, path, "Cannot check whether the target profile " + url + " on "+dPath+" is valid constraint on the base because it is not known", IssueSeverity.WARNING)); - } + addMessage(new ValidationMessage(Source.InstanceValidator, IssueType.BUSINESSRULE, path, "Cannot check whether the target profile " + url + " on "+dPath+" is valid constraint on the base because it is not known", IssueSeverity.WARNING)); return true; } else { if (sd.hasBaseDefinition() && sdConformsToTargets(path, dPath, sd.getBaseDefinition(), td)) { @@ -3022,7 +3024,7 @@ public class ProfileUtilities { } if (!ok) { - messages.add(new ValidationMessage(Source.InstanceValidator, IssueType.CONFLICT, dest.getId(), "The "+fieldName+" value has type '"+ft+"' which is not valid (valid "+Utilities.pluralize("type", dest.getType().size())+": "+types.toString()+")", IssueSeverity.ERROR)); + addMessage(new ValidationMessage(Source.InstanceValidator, IssueType.CONFLICT, dest.getId(), "The "+fieldName+" value has type '"+ft+"' which is not valid (valid "+Utilities.pluralize("type", dest.getType().size())+": "+types.toString()+")", IssueSeverity.ERROR)); } } @@ -3936,10 +3938,7 @@ public class ProfileUtilities { } ed.setId(bs); if (idList.containsKey(bs)) { - if (exception || messages == null) { - throw new DefinitionException(context.formatMessage(I18nConstants.SAME_ID_ON_MULTIPLE_ELEMENTS__IN_, bs, idList.get(bs), ed.getPath(), name)); - } else - messages.add(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.BUSINESSRULE, name+"."+bs, "Duplicate Element id "+bs, ValidationMessage.IssueSeverity.ERROR)); + addMessage(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.BUSINESSRULE, name+"."+bs, context.formatMessage(I18nConstants.SAME_ID_ON_MULTIPLE_ELEMENTS__IN_, bs, idList.get(bs), ed.getPath(), name), ValidationMessage.IssueSeverity.ERROR)); } idList.put(bs, ed.getPath()); if (ed.hasContentReference() && ed.getContentReference().startsWith("#")) { @@ -4315,12 +4314,12 @@ public class ProfileUtilities { public boolean isThrowException() { - return exception; + return wantThrowExceptions; } public void setThrowException(boolean exception) { - this.exception = exception; + this.wantThrowExceptions = exception; } @@ -4578,7 +4577,9 @@ public class ProfileUtilities { } public void setMessages(List messages) { - this.messages = messages; + if (messages != null) { + this.messages = messages; + } } private Map> propertyCache = new HashMap<>(); From dd01e008ca6fdc4742293f38a9c99d77c7e33d74 Mon Sep 17 00:00:00 2001 From: dotasek Date: Sun, 15 Sep 2024 10:01:53 -0400 Subject: [PATCH 38/50] Revert "Merge pull request #1649 from hapifhir/do-20240606-fix-classname-typo" This reverts commit 0c7e6ce9ac037170ff5af169fbade1e0232321e0, reversing changes made to bfed8a15d535dc040a92931baddc0457568ea379. --- .../resources30_40/Consent30_40.java | 13 +-- .../resources40_50/Consent40_50.java | 9 +- .../org/hl7/fhir/r4/formats/RdfParser.java | 2 +- .../org/hl7/fhir/r4/formats/XmlParser.java | 12 +- .../java/org/hl7/fhir/r4/model/Consent.java | 104 +++++++++--------- 5 files changed, 69 insertions(+), 71 deletions(-) diff --git a/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/conv30_40/resources30_40/Consent30_40.java b/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/conv30_40/resources30_40/Consent30_40.java index eaf5aba5a..1c783f74c 100644 --- a/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/conv30_40/resources30_40/Consent30_40.java +++ b/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/conv30_40/resources30_40/Consent30_40.java @@ -13,7 +13,6 @@ import org.hl7.fhir.convertors.conv30_40.datatypes30_40.primitivetypes30_40.Date import org.hl7.fhir.convertors.conv30_40.datatypes30_40.primitivetypes30_40.Uri30_40; import org.hl7.fhir.exceptions.FHIRException; import org.hl7.fhir.r4.model.CodeableConcept; -import org.hl7.fhir.r4.model.Consent; import org.hl7.fhir.r4.model.Identifier; public class Consent30_40 { @@ -48,7 +47,7 @@ public class Consent30_40 { tgt.setPolicyRule(new CodeableConcept(c)); } if (src.hasSecurityLabel() || src.hasPeriod() || src.hasActor() || src.hasAction() || src.hasPurpose() || src.hasDataPeriod() || src.hasData() || src.hasExcept()) { - Consent.ProvisionComponent pc = new Consent.ProvisionComponent(); + org.hl7.fhir.r4.model.Consent.provisionComponent pc = new org.hl7.fhir.r4.model.Consent.provisionComponent(); if (src.hasPeriod()) pc.setPeriod(Period30_40.convertPeriod(src.getPeriod())); for (org.hl7.fhir.dstu3.model.Consent.ConsentActorComponent t : src.getActor()) @@ -105,7 +104,7 @@ public class Consent30_40 { } } if (src.hasProvision()) { - Consent.ProvisionComponent p = src.getProvision(); + org.hl7.fhir.r4.model.Consent.provisionComponent p = src.getProvision(); if (p.hasPeriod()) tgt.setPeriod(Period30_40.convertPeriod(p.getPeriod())); for (org.hl7.fhir.r4.model.Consent.provisionActorComponent t : p.getActor()) @@ -118,7 +117,7 @@ public class Consent30_40 { tgt.setDataPeriod(Period30_40.convertPeriod(p.getDataPeriod())); for (org.hl7.fhir.r4.model.Consent.provisionDataComponent t : p.getData()) tgt.addData(convertConsentDataComponent(t)); - for (Consent.ProvisionComponent t : p.getProvision()) + for (org.hl7.fhir.r4.model.Consent.provisionComponent t : p.getProvision()) tgt.addExcept(convertExceptComponent(t)); } return tgt; @@ -370,7 +369,7 @@ public class Consent30_40 { return tgt; } - static public org.hl7.fhir.dstu3.model.Consent.ExceptComponent convertExceptComponent(Consent.ProvisionComponent src) throws FHIRException { + static public org.hl7.fhir.dstu3.model.Consent.ExceptComponent convertExceptComponent(org.hl7.fhir.r4.model.Consent.provisionComponent src) throws FHIRException { if (src == null) return null; org.hl7.fhir.dstu3.model.Consent.ExceptComponent tgt = new org.hl7.fhir.dstu3.model.Consent.ExceptComponent(); @@ -394,10 +393,10 @@ public class Consent30_40 { return tgt; } - static public Consent.ProvisionComponent convertExceptComponent(org.hl7.fhir.dstu3.model.Consent.ExceptComponent src) throws FHIRException { + static public org.hl7.fhir.r4.model.Consent.provisionComponent convertExceptComponent(org.hl7.fhir.dstu3.model.Consent.ExceptComponent src) throws FHIRException { if (src == null) return null; - Consent.ProvisionComponent tgt = new Consent.ProvisionComponent(); + org.hl7.fhir.r4.model.Consent.provisionComponent tgt = new org.hl7.fhir.r4.model.Consent.provisionComponent(); ConversionContext30_40.INSTANCE.getVersionConvertor_30_40().copyBackboneElement(src,tgt); if (src.hasType()) tgt.setTypeElement(convertConsentExceptType(src.getTypeElement())); diff --git a/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/conv40_50/resources40_50/Consent40_50.java b/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/conv40_50/resources40_50/Consent40_50.java index d5fa94f0f..0fe389de5 100644 --- a/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/conv40_50/resources40_50/Consent40_50.java +++ b/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/conv40_50/resources40_50/Consent40_50.java @@ -10,7 +10,6 @@ import org.hl7.fhir.convertors.conv40_50.datatypes40_50.primitive40_50.Boolean40 import org.hl7.fhir.convertors.conv40_50.datatypes40_50.primitive40_50.DateTime40_50; import org.hl7.fhir.convertors.conv40_50.datatypes40_50.special40_50.Reference40_50; import org.hl7.fhir.exceptions.FHIRException; -import org.hl7.fhir.r4.model.Consent; /* Copyright (c) 2011+, HL7, Inc. @@ -221,7 +220,7 @@ public class Consent40_50 { return tgt; } - public static org.hl7.fhir.r5.model.Consent.ProvisionComponent convertprovisionComponent(Consent.ProvisionComponent src) throws FHIRException { + public static org.hl7.fhir.r5.model.Consent.ProvisionComponent convertprovisionComponent(org.hl7.fhir.r4.model.Consent.provisionComponent src) throws FHIRException { if (src == null) return null; org.hl7.fhir.r5.model.Consent.ProvisionComponent tgt = new org.hl7.fhir.r5.model.Consent.ProvisionComponent(); @@ -243,15 +242,15 @@ public class Consent40_50 { tgt.setDataPeriod(Period40_50.convertPeriod(src.getDataPeriod())); for (org.hl7.fhir.r4.model.Consent.provisionDataComponent t : src.getData()) tgt.addData(convertprovisionDataComponent(t)); - for (Consent.ProvisionComponent t : src.getProvision()) + for (org.hl7.fhir.r4.model.Consent.provisionComponent t : src.getProvision()) tgt.addProvision(convertprovisionComponent(t)); return tgt; } - public static Consent.ProvisionComponent convertprovisionComponent(org.hl7.fhir.r5.model.Consent.ProvisionComponent src) throws FHIRException { + public static org.hl7.fhir.r4.model.Consent.provisionComponent convertprovisionComponent(org.hl7.fhir.r5.model.Consent.ProvisionComponent src) throws FHIRException { if (src == null) return null; - Consent.ProvisionComponent tgt = new Consent.ProvisionComponent(); + org.hl7.fhir.r4.model.Consent.provisionComponent tgt = new org.hl7.fhir.r4.model.Consent.provisionComponent(); ConversionContext40_50.INSTANCE.getVersionConvertor_40_50().copyBackboneElement(src, tgt); // if (src.hasType()) // tgt.setTypeElement(convertConsentProvisionType(src.getTypeElement())); diff --git a/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/formats/RdfParser.java b/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/formats/RdfParser.java index ee7a21d82..e09127adc 100644 --- a/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/formats/RdfParser.java +++ b/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/formats/RdfParser.java @@ -4917,7 +4917,7 @@ public class RdfParser extends RdfParserBase { } protected void composeConsentprovisionComponent(Complex parent, String parentType, String name, - Consent.ProvisionComponent element, int index) { + Consent.provisionComponent element, int index) { if (element == null) return; Complex t; diff --git a/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/formats/XmlParser.java b/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/formats/XmlParser.java index 6c46487ea..7ccf6fdd6 100644 --- a/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/formats/XmlParser.java +++ b/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/formats/XmlParser.java @@ -6924,9 +6924,9 @@ public class XmlParser extends XmlParserBase { return true; } - protected Consent.ProvisionComponent parseConsentprovisionComponent(XmlPullParser xpp, Consent owner) + protected Consent.provisionComponent parseConsentprovisionComponent(XmlPullParser xpp, Consent owner) throws XmlPullParserException, IOException, FHIRFormatError { - Consent.ProvisionComponent res = new Consent.ProvisionComponent(); + Consent.provisionComponent res = new Consent.provisionComponent(); parseBackboneAttributes(xpp, res); next(xpp); int eventType = nextNoWhitespace(xpp); @@ -6941,7 +6941,7 @@ public class XmlParser extends XmlParserBase { } protected boolean parseConsentprovisionComponentContent(int eventType, XmlPullParser xpp, Consent owner, - Consent.ProvisionComponent res) throws XmlPullParserException, IOException, FHIRFormatError { + Consent.provisionComponent res) throws XmlPullParserException, IOException, FHIRFormatError { if (eventType == XmlPullParser.START_TAG && xpp.getName().equals("type")) { res.setTypeElement( parseEnumeration(xpp, Consent.ConsentProvisionType.NULL, new Consent.ConsentProvisionTypeEnumFactory())); @@ -34008,7 +34008,7 @@ public class XmlParser extends XmlParserBase { } } - protected void composeConsentprovisionComponent(String name, Consent.ProvisionComponent element) throws IOException { + protected void composeConsentprovisionComponent(String name, Consent.provisionComponent element) throws IOException { if (element != null) { composeElementAttributes(element); xml.enter(FHIR_NS, name); @@ -34018,7 +34018,7 @@ public class XmlParser extends XmlParserBase { } } - protected void composeConsentprovisionComponentElements(Consent.ProvisionComponent element) throws IOException { + protected void composeConsentprovisionComponentElements(Consent.provisionComponent element) throws IOException { composeBackboneElementElements(element); if (element.hasTypeElement()) composeEnumeration("type", element.getTypeElement(), new Consent.ConsentProvisionTypeEnumFactory()); @@ -34057,7 +34057,7 @@ public class XmlParser extends XmlParserBase { composeConsentprovisionDataComponent("data", e); } if (element.hasProvision()) { - for (Consent.ProvisionComponent e : element.getProvision()) + for (Consent.provisionComponent e : element.getProvision()) composeConsentprovisionComponent("provision", e); } } diff --git a/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/model/Consent.java b/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/model/Consent.java index eb2e25345..1560c3f27 100644 --- a/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/model/Consent.java +++ b/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/model/Consent.java @@ -1221,7 +1221,7 @@ public class Consent extends DomainResource { } @Block() - public static class ProvisionComponent extends BackboneElement implements IBaseBackboneElement { + public static class provisionComponent extends BackboneElement implements IBaseBackboneElement { /** * Action to take - permit or deny - when the rule conditions are met. Not * permitted in root rule, required in all nested rules. @@ -1314,16 +1314,16 @@ public class Consent extends DomainResource { * Rules which provide exceptions to the base rule or subrules. */ @Child(name = "provision", type = { - ProvisionComponent.class }, order = 11, min = 0, max = Child.MAX_UNLIMITED, modifier = false, summary = false) + provisionComponent.class }, order = 11, min = 0, max = Child.MAX_UNLIMITED, modifier = false, summary = false) @Description(shortDefinition = "Nested Exception Rules", formalDefinition = "Rules which provide exceptions to the base rule or subrules.") - protected List provision; + protected List provision; private static final long serialVersionUID = -1280172451L; /** * Constructor */ - public ProvisionComponent() { + public provisionComponent() { super(); } @@ -1357,7 +1357,7 @@ public class Consent extends DomainResource { * extensions. The accessor "getType" gives direct access to the * value */ - public ProvisionComponent setTypeElement(Enumeration value) { + public provisionComponent setTypeElement(Enumeration value) { this.type = value; return this; } @@ -1374,7 +1374,7 @@ public class Consent extends DomainResource { * @param value Action to take - permit or deny - when the rule conditions are * met. Not permitted in root rule, required in all nested rules. */ - public ProvisionComponent setType(ConsentProvisionType value) { + public provisionComponent setType(ConsentProvisionType value) { if (value == null) this.type = null; else { @@ -1404,7 +1404,7 @@ public class Consent extends DomainResource { /** * @param value {@link #period} (The timeframe in this rule is valid.) */ - public ProvisionComponent setPeriod(Period value) { + public provisionComponent setPeriod(Period value) { this.period = value; return this; } @@ -1423,7 +1423,7 @@ public class Consent extends DomainResource { /** * @return Returns a reference to this for easy method chaining */ - public ProvisionComponent setActor(List theActor) { + public provisionComponent setActor(List theActor) { this.actor = theActor; return this; } @@ -1445,7 +1445,7 @@ public class Consent extends DomainResource { return t; } - public ProvisionComponent addActor(provisionActorComponent t) { // 3 + public provisionComponent addActor(provisionActorComponent t) { // 3 if (t == null) return this; if (this.actor == null) @@ -1477,7 +1477,7 @@ public class Consent extends DomainResource { /** * @return Returns a reference to this for easy method chaining */ - public ProvisionComponent setAction(List theAction) { + public provisionComponent setAction(List theAction) { this.action = theAction; return this; } @@ -1499,7 +1499,7 @@ public class Consent extends DomainResource { return t; } - public ProvisionComponent addAction(CodeableConcept t) { // 3 + public provisionComponent addAction(CodeableConcept t) { // 3 if (t == null) return this; if (this.action == null) @@ -1533,7 +1533,7 @@ public class Consent extends DomainResource { /** * @return Returns a reference to this for easy method chaining */ - public ProvisionComponent setSecurityLabel(List theSecurityLabel) { + public provisionComponent setSecurityLabel(List theSecurityLabel) { this.securityLabel = theSecurityLabel; return this; } @@ -1555,7 +1555,7 @@ public class Consent extends DomainResource { return t; } - public ProvisionComponent addSecurityLabel(Coding t) { // 3 + public provisionComponent addSecurityLabel(Coding t) { // 3 if (t == null) return this; if (this.securityLabel == null) @@ -1589,7 +1589,7 @@ public class Consent extends DomainResource { /** * @return Returns a reference to this for easy method chaining */ - public ProvisionComponent setPurpose(List thePurpose) { + public provisionComponent setPurpose(List thePurpose) { this.purpose = thePurpose; return this; } @@ -1611,7 +1611,7 @@ public class Consent extends DomainResource { return t; } - public ProvisionComponent addPurpose(Coding t) { // 3 + public provisionComponent addPurpose(Coding t) { // 3 if (t == null) return this; if (this.purpose == null) @@ -1646,7 +1646,7 @@ public class Consent extends DomainResource { /** * @return Returns a reference to this for easy method chaining */ - public ProvisionComponent setClass_(List theClass_) { + public provisionComponent setClass_(List theClass_) { this.class_ = theClass_; return this; } @@ -1668,7 +1668,7 @@ public class Consent extends DomainResource { return t; } - public ProvisionComponent addClass_(Coding t) { // 3 + public provisionComponent addClass_(Coding t) { // 3 if (t == null) return this; if (this.class_ == null) @@ -1701,7 +1701,7 @@ public class Consent extends DomainResource { /** * @return Returns a reference to this for easy method chaining */ - public ProvisionComponent setCode(List theCode) { + public provisionComponent setCode(List theCode) { this.code = theCode; return this; } @@ -1723,7 +1723,7 @@ public class Consent extends DomainResource { return t; } - public ProvisionComponent addCode(CodeableConcept t) { // 3 + public provisionComponent addCode(CodeableConcept t) { // 3 if (t == null) return this; if (this.code == null) @@ -1764,7 +1764,7 @@ public class Consent extends DomainResource { * @param value {@link #dataPeriod} (Clinical or Operational Relevant period of * time that bounds the data controlled by this rule.) */ - public ProvisionComponent setDataPeriod(Period value) { + public provisionComponent setDataPeriod(Period value) { this.dataPeriod = value; return this; } @@ -1782,7 +1782,7 @@ public class Consent extends DomainResource { /** * @return Returns a reference to this for easy method chaining */ - public ProvisionComponent setData(List theData) { + public provisionComponent setData(List theData) { this.data = theData; return this; } @@ -1804,7 +1804,7 @@ public class Consent extends DomainResource { return t; } - public ProvisionComponent addData(provisionDataComponent t) { // 3 + public provisionComponent addData(provisionDataComponent t) { // 3 if (t == null) return this; if (this.data == null) @@ -1828,16 +1828,16 @@ public class Consent extends DomainResource { * @return {@link #provision} (Rules which provide exceptions to the base rule * or subrules.) */ - public List getProvision() { + public List getProvision() { if (this.provision == null) - this.provision = new ArrayList(); + this.provision = new ArrayList(); return this.provision; } /** * @return Returns a reference to this for easy method chaining */ - public ProvisionComponent setProvision(List theProvision) { + public provisionComponent setProvision(List theProvision) { this.provision = theProvision; return this; } @@ -1845,25 +1845,25 @@ public class Consent extends DomainResource { public boolean hasProvision() { if (this.provision == null) return false; - for (ProvisionComponent item : this.provision) + for (provisionComponent item : this.provision) if (!item.isEmpty()) return true; return false; } - public ProvisionComponent addProvision() { // 3 - ProvisionComponent t = new ProvisionComponent(); + public provisionComponent addProvision() { // 3 + provisionComponent t = new provisionComponent(); if (this.provision == null) - this.provision = new ArrayList(); + this.provision = new ArrayList(); this.provision.add(t); return t; } - public ProvisionComponent addProvision(ProvisionComponent t) { // 3 + public provisionComponent addProvision(provisionComponent t) { // 3 if (t == null) return this; if (this.provision == null) - this.provision = new ArrayList(); + this.provision = new ArrayList(); this.provision.add(t); return this; } @@ -1872,7 +1872,7 @@ public class Consent extends DomainResource { * @return The first repetition of repeating field {@link #provision}, creating * it if it does not already exist */ - public ProvisionComponent getProvisionFirstRep() { + public provisionComponent getProvisionFirstRep() { if (getProvision().isEmpty()) { addProvision(); } @@ -2027,7 +2027,7 @@ public class Consent extends DomainResource { this.getData().add((provisionDataComponent) value); // provisionDataComponent return value; case -547120939: // provision - this.getProvision().add((ProvisionComponent) value); // provisionComponent + this.getProvision().add((provisionComponent) value); // provisionComponent return value; default: return super.setProperty(hash, name, value); @@ -2059,7 +2059,7 @@ public class Consent extends DomainResource { } else if (name.equals("data")) { this.getData().add((provisionDataComponent) value); } else if (name.equals("provision")) { - this.getProvision().add((ProvisionComponent) value); + this.getProvision().add((provisionComponent) value); } else return super.setProperty(name, value); return value; @@ -2088,7 +2088,7 @@ public class Consent extends DomainResource { } else if (name.equals("data")) { this.getData().remove((provisionDataComponent) value); } else if (name.equals("provision")) { - this.getProvision().remove((ProvisionComponent) value); + this.getProvision().remove((provisionComponent) value); } else super.removeChild(name, value); @@ -2186,13 +2186,13 @@ public class Consent extends DomainResource { return super.addChild(name); } - public ProvisionComponent copy() { - ProvisionComponent dst = new ProvisionComponent(); + public provisionComponent copy() { + provisionComponent dst = new provisionComponent(); copyValues(dst); return dst; } - public void copyValues(ProvisionComponent dst) { + public void copyValues(provisionComponent dst) { super.copyValues(dst); dst.type = type == null ? null : type.copy(); dst.period = period == null ? null : period.copy(); @@ -2240,8 +2240,8 @@ public class Consent extends DomainResource { } ; if (provision != null) { - dst.provision = new ArrayList(); - for (ProvisionComponent i : provision) + dst.provision = new ArrayList(); + for (provisionComponent i : provision) dst.provision.add(i.copy()); } ; @@ -2251,9 +2251,9 @@ public class Consent extends DomainResource { public boolean equalsDeep(Base other_) { if (!super.equalsDeep(other_)) return false; - if (!(other_ instanceof ProvisionComponent)) + if (!(other_ instanceof provisionComponent)) return false; - ProvisionComponent o = (ProvisionComponent) other_; + provisionComponent o = (provisionComponent) other_; return compareDeep(type, o.type, true) && compareDeep(period, o.period, true) && compareDeep(actor, o.actor, true) && compareDeep(action, o.action, true) && compareDeep(securityLabel, o.securityLabel, true) && compareDeep(purpose, o.purpose, true) && compareDeep(class_, o.class_, true) @@ -2265,9 +2265,9 @@ public class Consent extends DomainResource { public boolean equalsShallow(Base other_) { if (!super.equalsShallow(other_)) return false; - if (!(other_ instanceof ProvisionComponent)) + if (!(other_ instanceof provisionComponent)) return false; - ProvisionComponent o = (ProvisionComponent) other_; + provisionComponent o = (provisionComponent) other_; return compareValues(type, o.type, true); } @@ -3002,7 +3002,7 @@ public class Consent extends DomainResource { */ @Child(name = "provision", type = {}, order = 12, min = 0, max = 1, modifier = false, summary = true) @Description(shortDefinition = "Constraints to the base Consent.policyRule", formalDefinition = "An exception to the base policy of this consent. An exception can be an addition or removal of access permissions.") - protected ProvisionComponent provision; + protected provisionComponent provision; private static final long serialVersionUID = 206528051L; @@ -3669,12 +3669,12 @@ public class Consent extends DomainResource { * @return {@link #provision} (An exception to the base policy of this consent. * An exception can be an addition or removal of access permissions.) */ - public ProvisionComponent getProvision() { + public provisionComponent getProvision() { if (this.provision == null) if (Configuration.errorOnAutoCreate()) throw new Error("Attempt to auto-create Consent.provision"); else if (Configuration.doAutoCreate()) - this.provision = new ProvisionComponent(); // cc + this.provision = new provisionComponent(); // cc return this.provision; } @@ -3687,7 +3687,7 @@ public class Consent extends DomainResource { * consent. An exception can be an addition or removal of access * permissions.) */ - public Consent setProvision(ProvisionComponent value) { + public Consent setProvision(provisionComponent value) { this.provision = value; return this; } @@ -3883,7 +3883,7 @@ public class Consent extends DomainResource { this.getVerification().add((ConsentVerificationComponent) value); // ConsentVerificationComponent return value; case -547120939: // provision - this.provision = (ProvisionComponent) value; // provisionComponent + this.provision = (provisionComponent) value; // provisionComponent return value; default: return super.setProperty(hash, name, value); @@ -3919,7 +3919,7 @@ public class Consent extends DomainResource { } else if (name.equals("verification")) { this.getVerification().add((ConsentVerificationComponent) value); } else if (name.equals("provision")) { - this.provision = (ProvisionComponent) value; // provisionComponent + this.provision = (provisionComponent) value; // provisionComponent } else return super.setProperty(name, value); return value; @@ -3952,7 +3952,7 @@ public class Consent extends DomainResource { } else if (name.equals("verification")) { this.getVerification().remove((ConsentVerificationComponent) value); } else if (name.equals("provision")) { - this.provision = (ProvisionComponent) value; // provisionComponent + this.provision = (provisionComponent) value; // provisionComponent } else super.removeChild(name, value); @@ -4064,7 +4064,7 @@ public class Consent extends DomainResource { } else if (name.equals("verification")) { return addVerification(); } else if (name.equals("provision")) { - this.provision = new ProvisionComponent(); + this.provision = new provisionComponent(); return this.provision; } else return super.addChild(name); From 0d8c5942e799ad718dc1e5e688064cf02c17434b Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Tue, 17 Sep 2024 14:11:13 +0800 Subject: [PATCH 39/50] Fix rendering path for value set references for kindling --- .../main/java/org/hl7/fhir/r5/renderers/ValueSetRenderer.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/ValueSetRenderer.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/ValueSetRenderer.java index 4a78a67c8..16adae09a 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/ValueSetRenderer.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/ValueSetRenderer.java @@ -750,9 +750,9 @@ public class ValueSetRenderer extends TerminologyRenderer { if (cs == null) { return "?cs-n?"; } - String ref = (String) cs.getUserData("filename"); + String ref = cs.getWebPath(); if (ref == null) { - ref = (String) cs.getWebPath(); + ref = cs.getUserString("filename"); } return ref == null ? null : ref.replace("\\", "/"); } From 11efed6635c40f077924c7650b301fe5981bb9dd Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Tue, 17 Sep 2024 16:16:09 +0800 Subject: [PATCH 40/50] Validation of experimental property --- .../fhir/utilities/i18n/I18nConstants.java | 3 +++ .../src/main/resources/Messages.properties | 4 +++- .../hl7/fhir/validation/ValidationEngine.java | 2 ++ .../fhir/validation/cli/model/CliContext.java | 18 +++++++++++++- .../cli/services/ValidationService.java | 1 + .../hl7/fhir/validation/cli/utils/Params.java | 5 +++- .../instance/InstanceValidator.java | 13 ++++++++++ .../type/StructureDefinitionValidator.java | 24 ++++++++++++------- .../validation/tests/ValidationTests.java | 3 +++ 9 files changed, 62 insertions(+), 11 deletions(-) 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 db81c97c3..e8af42a88 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 @@ -1108,4 +1108,7 @@ public class I18nConstants { public static final String SM_TARGET_TYPE_UNKNOWN = "SM_TARGET_TYPE_UNKNOWN"; public static final String XHTML_XHTML_ATTRIBUTE_XML_SPACE = "XHTML_XHTML_ATTRIBUTE_XML_SPACE"; public static final String VALIDATION_HL7_PUBLISHER_MULTIPLE_WGS = "VALIDATION_HL7_PUBLISHER_MULTIPLE_WGS"; + public static final String SD_BASE_EXPERIMENTAL = "SD_BASE_EXPERIMENTAL"; + public static final String SD_ED_EXPERIMENTAL_BINDING = "SD_ED_EXPERIMENTAL_BINDING"; + public static final String VALIDATION_NO_EXPERIMENTAL_CONTENT = "VALIDATION_NO_EXPERIMENTAL_CONTENT"; } diff --git a/org.hl7.fhir.utilities/src/main/resources/Messages.properties b/org.hl7.fhir.utilities/src/main/resources/Messages.properties index bae41d4af..35811c33e 100644 --- a/org.hl7.fhir.utilities/src/main/resources/Messages.properties +++ b/org.hl7.fhir.utilities/src/main/resources/Messages.properties @@ -1140,4 +1140,6 @@ XHTML_XHTML_ATTRIBUTE_XML_SPACE = The attribute 'xml:space' is legal but has a f VALIDATION_HL7_PUBLISHER_MULTIPLE_WGS = This resource has more than workgroup extension (http://hl7.org/fhir/StructureDefinition/structuredefinition-wg) NO_VALID_DISPLAY_FOUND_NONE_FOR_LANG = Wrong Display Name ''{0}'' for {1}#{2}. There are no valid display names found for language(s) ''{3}''. Default display is ''{4}'' NO_VALID_DISPLAY_AT_ALL = Cannot validate display Name ''{0}'' for {1}#{2}: No displays are known - +SD_BASE_EXPERIMENTAL = The definition builds on ''{0}'' which is experimental, but this definition is not labeled as experimental +SD_ED_EXPERIMENTAL_BINDING = The definition for the element ''{0}'' binds to the value set ''{1}'' which is experimental, but this structure is not labeled as experimental +VALIDATION_NO_EXPERIMENTAL_CONTENT = Experimental content is not allowed in this context diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/ValidationEngine.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/ValidationEngine.java index 9bf88787c..46f5d948b 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/ValidationEngine.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/ValidationEngine.java @@ -227,6 +227,7 @@ public class ValidationEngine implements IValidatorResourceFetcher, IValidationP @Getter @Setter private boolean checkIPSCodes; @Getter @Setter private BestPracticeWarningLevel bestPracticeLevel; @Getter @Setter private boolean unknownCodeSystemsCauseErrors; + @Getter @Setter private boolean noExperimentalContent; @Getter @Setter private Locale locale; @Getter @Setter private List igs = new ArrayList<>(); @Getter @Setter private List extensionDomains = new ArrayList<>(); @@ -909,6 +910,7 @@ public class ValidationEngine implements IValidatorResourceFetcher, IValidationP validator.setPolicyAdvisor(policyAdvisor); } validator.setUnknownCodeSystemsCauseErrors(unknownCodeSystemsCauseErrors); + validator.setNoExperimentalContent(noExperimentalContent); return validator; } 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 79c604c6c..418526071 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 @@ -165,6 +165,9 @@ public class CliContext { @JsonProperty("unknownCodeSystemsCauseErrors") private boolean unknownCodeSystemsCauseErrors; + + @JsonProperty("noExperimentalContent") + private boolean noExperimentalContent; @JsonProperty("baseEngine") public String getBaseEngine() { @@ -836,6 +839,7 @@ public class CliContext { Objects.equals(bestPracticeLevel, that.bestPracticeLevel) && Objects.equals(watchScanDelay, that.watchScanDelay) && Objects.equals(unknownCodeSystemsCauseErrors, that.unknownCodeSystemsCauseErrors) && + Objects.equals(noExperimentalContent, that.noExperimentalContent) && Objects.equals(watchSettleTime, that.watchSettleTime) ; } @@ -844,7 +848,7 @@ public class CliContext { return Objects.hash(baseEngine, doNative, extensions, hintAboutNonMustSupport, recursive, doDebug, assumeValidRestReferences, canDoNative, noInternalCaching, noExtensibleBindingMessages, noInvariants, displayWarnings, wantInvariantsInMessages, map, output, outputSuffix, htmlOutput, txServer, sv, txLog, txCache, mapLog, lang, srcLang, tgtLang, fhirpath, snomedCT, targetVer, igs, questionnaireMode, level, profiles, sources, inputs, mode, locale, locations, crumbTrails, forPublication, showTimes, allowExampleUrls, outputStyle, jurisdiction, noUnicodeBiDiControlChars, - watchMode, watchScanDelay, watchSettleTime, bestPracticeLevel, unknownCodeSystemsCauseErrors, htmlInMarkdownCheck, allowDoubleQuotesInFHIRPath, checkIPSCodes); + watchMode, watchScanDelay, watchSettleTime, bestPracticeLevel, unknownCodeSystemsCauseErrors, noExperimentalContent, htmlInMarkdownCheck, allowDoubleQuotesInFHIRPath, checkIPSCodes); } @Override @@ -904,6 +908,7 @@ public class CliContext { ", watchSettleTime=" + watchSettleTime + ", watchScanDelay=" + watchScanDelay + ", unknownCodeSystemsCauseErrors=" + unknownCodeSystemsCauseErrors + + ", noExperimentalContent=" + noExperimentalContent + '}'; } @@ -973,5 +978,16 @@ public class CliContext { this.unknownCodeSystemsCauseErrors = unknownCodeSystemsCauseErrors; } + @JsonProperty("noExperimentalContent") + public boolean isNoExperimentalContent() { + return noExperimentalContent; + } + + + @JsonProperty("noExperimentalContent") + public void setNoExperimentalContent(boolean noExperimentalContent) { + this.noExperimentalContent = noExperimentalContent; + } + } \ No newline at end of file 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 61d4b7d5f..82abdff63 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 @@ -582,6 +582,7 @@ public class ValidationService { validationEngine.getBundleValidationRules().addAll(cliContext.getBundleValidationRules()); validationEngine.setJurisdiction(CodeSystemUtilities.readCoding(cliContext.getJurisdiction())); validationEngine.setUnknownCodeSystemsCauseErrors(cliContext.isUnknownCodeSystemsCauseErrors()); + validationEngine.setNoExperimentalContent(cliContext.isNoExperimentalContent()); TerminologyCache.setNoCaching(cliContext.isNoInternalCaching()); validationEngine.prepare(); // generate any missing snapshots System.out.println(" go (" + timeTracker.milestone() + ")"); 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 0983d0072..0b220f5f8 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 @@ -94,7 +94,8 @@ public class Params { public static final String DISABLE_DEFAULT_RESOURCE_FETCHER = "-disable-default-resource-fetcher"; public static final String CHECK_IPS_CODES = "-check-ips-codes"; public static final String BEST_PRACTICE = "-best-practice"; - public static final String UNKNOWN_CODESYSTEMS_CAUSE_ERROR = "-unknown-codesystems-cause-errors"; + public static final String UNKNOWN_CODESYSTEMS_CAUSE_ERROR = "-unknown-codesystems-cause-errors"; + public static final String NO_EXPERIMENTAL_CONTENT = "-no-experimental-content"; public static final String RUN_TESTS = "-run-tests"; @@ -321,6 +322,8 @@ public class Params { cliContext.setForPublication(true); } else if (args[i].equals(UNKNOWN_CODESYSTEMS_CAUSE_ERROR)) { cliContext.setUnknownCodeSystemsCauseErrors(true); + } else if (args[i].equals(NO_EXPERIMENTAL_CONTENT)) { + cliContext.setNoExperimentalContent(true); } else if (args[i].equals(VERBOSE)) { cliContext.setCrumbTrails(true); } else if (args[i].equals(ALLOW_EXAMPLE_URLS)) { 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 dbc8eb164..96c72324a 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 @@ -599,6 +599,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat private IDigitalSignatureServices signatureServices; private ContextUtilities cu; private boolean unknownCodeSystemsCauseErrors; + private boolean noExperimentalContent; public InstanceValidator(@Nonnull IWorkerContext theContext, @Nonnull IEvaluationContext hostServices, @Nonnull XVerExtensionManager xverManager) { super(theContext, xverManager, false); @@ -5718,6 +5719,10 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat hint(errors, "2023-08-14", IssueType.BUSINESSRULE, element.line(), element.col(), stack.getLiteralPath(), statusCodesDeeplyConsistent(status, standardsStatus), I18nConstants.VALIDATION_VAL_STATUS_INCONSISTENT_HINT, status, standardsStatus); } } + if (noExperimentalContent) { + String exp = element.getNamedChildValue("experimental"); + ok = rule(errors, "2024-09-17", IssueType.BUSINESSRULE, element.line(), element.col(), stack.getLiteralPath(), !"true".equals(exp), I18nConstants.VALIDATION_NO_EXPERIMENTAL_CONTENT) && ok; + } if (isHL7Core(element) && !isExample()) { ok = checkPublisherConsistency(valContext, errors, element, stack, contained) && ok; @@ -7839,6 +7844,14 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat public void setUnknownCodeSystemsCauseErrors(boolean unknownCodeSystemsCauseErrors) { this.unknownCodeSystemsCauseErrors = unknownCodeSystemsCauseErrors; } + + public boolean isNoExperimentalContent() { + return noExperimentalContent; + } + + public void setNoExperimentalContent(boolean noExperimentalContent) { + this.noExperimentalContent = noExperimentalContent; + } } 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 09f0be183..0df6dd68f 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 @@ -85,6 +85,7 @@ public class StructureDefinitionValidator extends BaseValidator { List snapshot = sd.getSnapshot().getElement(); sd.setSnapshot(null); typeName = sd.getTypeName(); + boolean experimental = "true".equals(src.getNamedChildValue("experimental", false)); StructureDefinition base = context.fetchResource(StructureDefinition.class, sd.getBaseDefinition()); if (warning(errors, NO_RULE_DATE, IssueType.NOTFOUND, stack.getLiteralPath(), base != null, I18nConstants.UNABLE_TO_FIND_BASE__FOR_, sd.getBaseDefinition(), "StructureDefinition, so can't check the differential")) { if (rule(errors, NO_RULE_DATE, IssueType.NOTFOUND, stack.getLiteralPath(), sd.hasDerivation(), I18nConstants.SD_MUST_HAVE_DERIVATION, sd.getUrl())) { @@ -129,6 +130,7 @@ public class StructureDefinitionValidator extends BaseValidator { ok = rule(errors, "2022-11-02", IssueType.NOTFOUND, stack.getLiteralPath(), base.getKindElement().primitiveValue().equals(src.getChildValue("kind")), I18nConstants.SD_DERIVATION_KIND_MISMATCH, base.getKindElement().primitiveValue(), src.getChildValue("kind")) && ok; } + warning(errors, "2024-09-17", IssueType.BUSINESSRULE, stack.getLiteralPath(), !base.getExperimental() || experimental, I18nConstants.SD_BASE_EXPERIMENTAL, sd.getBaseDefinition()); } List differentials = src.getChildrenByName("differential"); @@ -136,10 +138,10 @@ public class StructureDefinitionValidator extends BaseValidator { boolean logical = "logical".equals(src.getNamedChildValue("kind", false)); boolean constraint = "constraint".equals(src.getNamedChildValue("derivation", false)); for (Element differential : differentials) { - ok = validateElementList(errors, differential, stack.push(differential, -1, null, null), false, snapshots.size() > 0, sd, typeName, logical, constraint, src.getNamedChildValue("type", false), src.getNamedChildValue("url", false), src.getNamedChildValue("type", false), base) && ok; + ok = validateElementList(errors, differential, stack.push(differential, -1, null, null), false, snapshots.size() > 0, sd, typeName, logical, constraint, src.getNamedChildValue("type", false), src.getNamedChildValue("url", false), src.getNamedChildValue("type", false), base, experimental) && ok; } for (Element snapshotE : snapshots) { - ok = validateElementList(errors, snapshotE, stack.push(snapshotE, -1, null, null), true, true, sd, typeName, logical, constraint, src.getNamedChildValue("type", false), src.getNamedChildValue("url", false), src.getNamedChildValue("type", false), base) && ok; + ok = validateElementList(errors, snapshotE, stack.push(snapshotE, -1, null, null), true, true, sd, typeName, logical, constraint, src.getNamedChildValue("type", false), src.getNamedChildValue("url", false), src.getNamedChildValue("type", false), base, experimental) && ok; } // obligation profile support @@ -189,6 +191,7 @@ public class StructureDefinitionValidator extends BaseValidator { } } } catch (Exception e) { + e.printStackTrace(); rule(errors, NO_RULE_DATE, IssueType.EXCEPTION, stack.getLiteralPath(), false, I18nConstants.ERROR_GENERATING_SNAPSHOT, e.getMessage()); ok = false; } @@ -409,19 +412,19 @@ public class StructureDefinitionValidator extends BaseValidator { } } - private boolean validateElementList(List errors, Element elementList, NodeStack stack, boolean snapshot, boolean hasSnapshot, StructureDefinition sd, String typeName, boolean logical, boolean constraint, String rootPath, String profileUrl, String profileType, StructureDefinition base) { + private boolean validateElementList(List errors, Element elementList, NodeStack stack, boolean snapshot, boolean hasSnapshot, StructureDefinition sd, String typeName, boolean logical, boolean constraint, String rootPath, String profileUrl, String profileType, StructureDefinition base, boolean experimental) { Map invariantMap = new HashMap<>(); boolean ok = true; List elements = elementList.getChildrenByName("element"); int cc = 0; for (Element element : elements) { - ok = validateElementDefinition(errors, elements, element, stack.push(element, cc, null, null), snapshot, hasSnapshot, sd, typeName, logical, constraint, invariantMap, rootPath, profileUrl, profileType, base) && ok; + ok = validateElementDefinition(errors, elements, element, stack.push(element, cc, null, null), snapshot, hasSnapshot, sd, typeName, logical, constraint, invariantMap, rootPath, profileUrl, profileType, base, experimental) && ok; cc++; } return ok; } - private boolean validateElementDefinition(List errors, List elements, Element element, NodeStack stack, boolean snapshot, boolean hasSnapshot, StructureDefinition sd, String typeName, boolean logical, boolean constraint, Map invariantMap, String rootPath, String profileUrl, String profileType, StructureDefinition base) { + private boolean validateElementDefinition(List errors, List elements, Element element, NodeStack stack, boolean snapshot, boolean hasSnapshot, StructureDefinition sd, String typeName, boolean logical, boolean constraint, Map invariantMap, String rootPath, String profileUrl, String profileType, StructureDefinition base, boolean experimental) { boolean ok = true; boolean typeMustSupport = false; String path = element.getNamedChildValue("path", false); @@ -522,7 +525,7 @@ public class StructureDefinitionValidator extends BaseValidator { ok = rule(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, stack.getLiteralPath(), characteristics.contains("can-bind") , I18nConstants.SD_ILLEGAL_CHARACTERISTICS, "Binding", typeCodes) && ok; } Element binding = element.getNamedChild("binding", false); - ok = validateBinding(errors, binding, stack.push(binding, -1, null, null), typeCodes, snapshot, path) && ok; + ok = validateBinding(errors, binding, stack.push(binding, -1, null, null), typeCodes, snapshot, path, experimental) && ok; } else { // this is a good idea but there's plenty of cases where the rule isn't met; maybe one day it's worth investing the time to exclude these cases and bring this rule back // String bt = boundType(typeCodes); @@ -986,7 +989,7 @@ public class StructureDefinitionValidator extends BaseValidator { return null; } - private boolean validateBinding(List errors, Element binding, NodeStack stack, Set typeCodes, boolean snapshot, String path) { + private boolean validateBinding(List errors, Element binding, NodeStack stack, Set typeCodes, boolean snapshot, String path, boolean experimental) { boolean ok = true; if (bindableType(typeCodes) == null) { ok = rule(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, stack.getLiteralPath(), !snapshot, I18nConstants.SD_ED_BIND_NO_BINDABLE, path, typeCodes.toString()) && ok; @@ -1006,7 +1009,12 @@ public class StructureDefinitionValidator extends BaseValidator { if (warning(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, stack.getLiteralPath(), vs != null || serverSupportsValueSet(ref), I18nConstants.SD_ED_BIND_UNKNOWN_VS, path, ref)) { if (vs != null) { - ok = rule(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, stack.getLiteralPath(), vs instanceof ValueSet, I18nConstants.SD_ED_BIND_NOT_VS, path, ref, vs.fhirType()) && ok; + if (rule(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, stack.getLiteralPath(), vs instanceof ValueSet, I18nConstants.SD_ED_BIND_NOT_VS, path, ref, vs.fhirType())) { + ValueSet vsr = (ValueSet) vs; + warning(errors, "2024-09-17", IssueType.BUSINESSRULE, stack.getLiteralPath(), !vsr.getExperimental() || experimental, I18nConstants.SD_ED_EXPERIMENTAL_BINDING, path, ref); + } else { + ok = false; + } } } } 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 880fb2f9c..c43b88da0 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 @@ -362,6 +362,9 @@ public class ValidationTests implements IEvaluationContext, IValidatorResourceFe if (content.has("security-checks")) { val.setSecurityChecks(content.get("security-checks").getAsBoolean()); } + if (content.has("no-experimental-content")) { + val.setNoExperimentalContent(content.get("no-experimental-content").getAsBoolean()); + } if (content.has("noHtmlInMarkdown")) { val.setHtmlInMarkdownCheck(HtmlInMarkdownCheck.ERROR); } From ded7bc0ffdd59bdc1c5074c68e8965d13463989a Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Tue, 17 Sep 2024 16:20:22 +0800 Subject: [PATCH 41/50] release notes --- RELEASE_NOTES.md | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index f9e202bce..ce6a47dee 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,18 +1,13 @@ ## Validator Changes -* Fix expression for con-3 properly (fix validation problem on some condition resources) -* Fix FHIRPath bug using wrong type on simple elements when checking FHIRPath types -* FHIRPath: Allow _ in constant names (per FHIRPath spec) -* Fix value set rendering creating wrong references -* Fix bug processing value set includes / excludes that are just value sets (no system value) -* Alter processing of unknown code systems per discussion at ,https://chat.fhir.org/#narrow/stream/179252-IG-creation/topic/Don't.20error.20when.20you.20can't.20find.20code.20system and implement unknown-codesystems-cause-errors -* Improve message for when elements are out of order in profile differentials - +* Validate of experimental property on bindings +* Add -no-experimental-content flag +* Allow JSON named extensions to be structure types other than logical +* Process relative URLs properly in base when generating snapshots ## Other code changes -* fix problem where profile rendering had spurious 'slices for' nodes everywhere -* Update SQL-On-FHIR implementation for latest cases, and clone test cases to general test care repository -* Fix problem generating value set spreadsheets -* fix concurrent modification error processing language translations -* Check for null fetcher processing ConceptMaps (#1728) +* Fix rendering path for value set references for kindling +* refactor error handling in ProfileUtilities +* Fix for NPE processing packages + From 9ba7bb447ff1549ddcafc3d10f6dbc290f9772de Mon Sep 17 00:00:00 2001 From: markiantorno Date: Tue, 17 Sep 2024 09:44:27 +0000 Subject: [PATCH 42/50] Updating i18n-coverage csv and png table ***NO_CI*** --- i18n-coverage-table.png | Bin 30997 -> 31259 bytes i18n-coverage.csv | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n-coverage-table.png b/i18n-coverage-table.png index 612370aec15032fa2a6d7e70464b4c1834f5737d..e3f25dc2dce82da4083f7e944f91d22eb0c5c443 100644 GIT binary patch literal 31259 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 X+Kh3o+KE~wN#n;(F+FQyx8Z*PM(9Cy literal 30997 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 XhCDj|VmbbbVrr|tk=}z%`%nKDnu$X! diff --git a/i18n-coverage.csv b/i18n-coverage.csv index 49cf39ece..bf44bb436 100644 --- a/i18n-coverage.csv +++ b/i18n-coverage.csv @@ -1,5 +1,5 @@ Locale,Coverage #,Coverage % -de,831,41% +de,831,40% es,714,35% ja,902,44% nl,1989,98% From e7f5c238d6c7dcbf8b2d3164cbdf93dc00c79bc6 Mon Sep 17 00:00:00 2001 From: Mark Iantorno Date: Tue, 17 Sep 2024 20:31:50 +0000 Subject: [PATCH 43/50] Updating test case dependency to v1.5.22 ***NO_CI*** --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 57abeddaf..cba39c632 100644 --- a/pom.xml +++ b/pom.xml @@ -21,7 +21,7 @@ 1.26.0 32.0.1-jre 6.4.1 - 1.5.22-SNAPSHOT + 1.5.22 2.17.0 5.9.2 1.8.2 From d2ad535b0b764fa52e979096debf4ea505101f18 Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Wed, 18 Sep 2024 04:36:03 +0800 Subject: [PATCH 44/50] update tests dependency --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 57abeddaf..cba39c632 100644 --- a/pom.xml +++ b/pom.xml @@ -21,7 +21,7 @@ 1.26.0 32.0.1-jre 6.4.1 - 1.5.22-SNAPSHOT + 1.5.22 2.17.0 5.9.2 1.8.2 From 46affee48ff1dfb854df91fc0c6dc7c7d66dcdfd Mon Sep 17 00:00:00 2001 From: markiantorno Date: Tue, 17 Sep 2024 21:09:53 +0000 Subject: [PATCH 45/50] Release: v6.3.26 ## Validator Changes * Validate of experimental property on bindings * Add -no-experimental-content flag * Allow JSON named extensions to be structure types other than logical * Process relative URLs properly in base when generating snapshots ## Other code changes * Fix rendering path for value set references for kindling * refactor error handling in ProfileUtilities * Fix for NPE processing packages ***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 497a67ca5..0a6586c96 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.3.26-SNAPSHOT + 6.3.26 ../pom.xml diff --git a/org.hl7.fhir.dstu2/pom.xml b/org.hl7.fhir.dstu2/pom.xml index 1ef5e9c18..fc29044d2 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.3.26-SNAPSHOT + 6.3.26 ../pom.xml diff --git a/org.hl7.fhir.dstu2016may/pom.xml b/org.hl7.fhir.dstu2016may/pom.xml index 10836492e..01bd0a40b 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.3.26-SNAPSHOT + 6.3.26 ../pom.xml diff --git a/org.hl7.fhir.dstu3/pom.xml b/org.hl7.fhir.dstu3/pom.xml index 9b9f1ede2..30d848f3b 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.3.26-SNAPSHOT + 6.3.26 ../pom.xml diff --git a/org.hl7.fhir.r4/pom.xml b/org.hl7.fhir.r4/pom.xml index bc3634f35..f24471b4b 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.3.26-SNAPSHOT + 6.3.26 ../pom.xml diff --git a/org.hl7.fhir.r4b/pom.xml b/org.hl7.fhir.r4b/pom.xml index df709cb6a..ed4dcdda5 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.3.26-SNAPSHOT + 6.3.26 ../pom.xml diff --git a/org.hl7.fhir.r5/pom.xml b/org.hl7.fhir.r5/pom.xml index 8bb7cfbb9..d9e3ffc8c 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.3.26-SNAPSHOT + 6.3.26 ../pom.xml diff --git a/org.hl7.fhir.report/pom.xml b/org.hl7.fhir.report/pom.xml index f0adc1c86..dca6fb2f2 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.3.26-SNAPSHOT + 6.3.26 ../pom.xml diff --git a/org.hl7.fhir.utilities/pom.xml b/org.hl7.fhir.utilities/pom.xml index e4d08a59f..4facadbd1 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.3.26-SNAPSHOT + 6.3.26 ../pom.xml diff --git a/org.hl7.fhir.validation.cli/pom.xml b/org.hl7.fhir.validation.cli/pom.xml index 54e5ebfa8..351f7d192 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.3.26-SNAPSHOT + 6.3.26 ../pom.xml diff --git a/org.hl7.fhir.validation/pom.xml b/org.hl7.fhir.validation/pom.xml index 10e3221ea..122708b8e 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.3.26-SNAPSHOT + 6.3.26 ../pom.xml diff --git a/pom.xml b/pom.xml index cba39c632..2ff0f4ba3 100644 --- a/pom.xml +++ b/pom.xml @@ -14,7 +14,7 @@ HAPI FHIR --> org.hl7.fhir.core - 6.3.26-SNAPSHOT + 6.3.26 pom From f3bd5b9be80ae3717b1121081ca54bd68c298e1f Mon Sep 17 00:00:00 2001 From: markiantorno Date: Tue, 17 Sep 2024 22:00:24 +0000 Subject: [PATCH 46/50] Updating version to: 6.3.27-SNAPSHOT and incrementing test cases dependency. --- RELEASE_NOTES.md | 10 ++-------- 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(+), 20 deletions(-) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index ce6a47dee..7b06c6ab5 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,13 +1,7 @@ ## Validator Changes -* Validate of experimental property on bindings -* Add -no-experimental-content flag -* Allow JSON named extensions to be structure types other than logical -* Process relative URLs properly in base when generating snapshots +* no changes ## Other code changes -* Fix rendering path for value set references for kindling -* refactor error handling in ProfileUtilities -* Fix for NPE processing packages - +* 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 0a6586c96..954879875 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.3.26 + 6.3.27-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.dstu2/pom.xml b/org.hl7.fhir.dstu2/pom.xml index fc29044d2..0f35fa8bd 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.3.26 + 6.3.27-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.dstu2016may/pom.xml b/org.hl7.fhir.dstu2016may/pom.xml index 01bd0a40b..73f375a3b 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.3.26 + 6.3.27-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.dstu3/pom.xml b/org.hl7.fhir.dstu3/pom.xml index 30d848f3b..cf607fb20 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.3.26 + 6.3.27-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.r4/pom.xml b/org.hl7.fhir.r4/pom.xml index f24471b4b..5dcc8666b 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.3.26 + 6.3.27-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.r4b/pom.xml b/org.hl7.fhir.r4b/pom.xml index ed4dcdda5..aec9ce8e4 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.3.26 + 6.3.27-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.r5/pom.xml b/org.hl7.fhir.r5/pom.xml index d9e3ffc8c..b196a2821 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.3.26 + 6.3.27-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.report/pom.xml b/org.hl7.fhir.report/pom.xml index dca6fb2f2..dda6b248f 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.3.26 + 6.3.27-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.utilities/pom.xml b/org.hl7.fhir.utilities/pom.xml index 4facadbd1..a2e86d2a1 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.3.26 + 6.3.27-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.validation.cli/pom.xml b/org.hl7.fhir.validation.cli/pom.xml index 351f7d192..de8286041 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.3.26 + 6.3.27-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.validation/pom.xml b/org.hl7.fhir.validation/pom.xml index 122708b8e..19fe4ae82 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.3.26 + 6.3.27-SNAPSHOT ../pom.xml diff --git a/pom.xml b/pom.xml index 2ff0f4ba3..aac61867c 100644 --- a/pom.xml +++ b/pom.xml @@ -14,7 +14,7 @@ HAPI FHIR --> org.hl7.fhir.core - 6.3.26 + 6.3.27-SNAPSHOT pom From 69525144f3814b0887ab793c4d167bc620de83ff Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Wed, 18 Sep 2024 14:07:09 +1000 Subject: [PATCH 47/50] #1723 fix R3 Quantity.copyValues() --- .../org/hl7/fhir/dstu3/model/Quantity.java | 7 +++- .../MedicationAdministrationCopyTest.java | 40 +++++++++++++++++++ 2 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 org.hl7.fhir.dstu3/src/test/java/org/hl7/fhir/dstu3/model/MedicationAdministrationCopyTest.java diff --git a/org.hl7.fhir.dstu3/src/main/java/org/hl7/fhir/dstu3/model/Quantity.java b/org.hl7.fhir.dstu3/src/main/java/org/hl7/fhir/dstu3/model/Quantity.java index fd3912594..1fe0a11e0 100644 --- a/org.hl7.fhir.dstu3/src/main/java/org/hl7/fhir/dstu3/model/Quantity.java +++ b/org.hl7.fhir.dstu3/src/main/java/org/hl7/fhir/dstu3/model/Quantity.java @@ -1,6 +1,7 @@ package org.hl7.fhir.dstu3.model; import java.math.BigDecimal; +import java.util.ArrayList; /* Copyright (c) 2011+, HL7, Inc. @@ -668,12 +669,16 @@ public class Quantity extends Type implements ICompositeType { public Quantity copy() { Quantity dst = new Quantity(); copyValues(dst); + return dst; + } + + public void copyValues(Quantity dst) { + super.copyValues(dst); dst.value = value == null ? null : value.copy(); dst.comparator = comparator == null ? null : comparator.copy(); dst.unit = unit == null ? null : unit.copy(); dst.system = system == null ? null : system.copy(); dst.code = code == null ? null : code.copy(); - return dst; } protected Quantity typedCopy() { diff --git a/org.hl7.fhir.dstu3/src/test/java/org/hl7/fhir/dstu3/model/MedicationAdministrationCopyTest.java b/org.hl7.fhir.dstu3/src/test/java/org/hl7/fhir/dstu3/model/MedicationAdministrationCopyTest.java new file mode 100644 index 000000000..a1adeb216 --- /dev/null +++ b/org.hl7.fhir.dstu3/src/test/java/org/hl7/fhir/dstu3/model/MedicationAdministrationCopyTest.java @@ -0,0 +1,40 @@ +package org.hl7.fhir.dstu3.model; + +import static org.junit.Assert.assertTrue; + +import java.io.IOException; + +import org.hl7.fhir.dstu3.formats.JsonParser; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +public class MedicationAdministrationCopyTest { + + @DisplayName("Test MedicationAdministration copy") + @Test + public void test() throws IOException { + MedicationAdministration beforeCopy = createMedAdminWithDosageDurationExtension(); + MedicationAdministration afterCopy = beforeCopy.copy(); + + System.out.println("---- BEFORE COPY (BEGIN)"); + System.out.println(new JsonParser().composeString(beforeCopy)); + System.out.println("---- BEFORE COPY (END)"); + System.out.println(); + System.out.println("---- AFTER COPY (BEGIN)"); + System.out.println(new JsonParser().composeString(afterCopy)); + System.out.println("---- AFTER COPY (END)"); + assertTrue(beforeCopy.equalsDeep(afterCopy)); + } + + private static MedicationAdministration createMedAdminWithDosageDurationExtension() { + MedicationAdministration resource = new MedicationAdministration(); + resource.setId("12345"); + var dosage = new MedicationAdministration.MedicationAdministrationDosageComponent(); + dosage.setDose((SimpleQuantity) new SimpleQuantity().setValue(40)) + .addExtension(new Extension() + .setUrl("http://duration") + .setValue(new Duration().setValue(5340000))); + resource.setDosage(dosage); + return resource; + } +} From 948f3411e24bf57ac8deaaa6d92009ab8bafe96b Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Wed, 18 Sep 2024 14:07:29 +1000 Subject: [PATCH 48/50] Fix case typo on Consent.provision in R4 --- .../resources30_40/Consent30_40.java | 12 +- .../resources40_50/Consent40_50.java | 8 +- .../org/hl7/fhir/r4/formats/JsonParser.java | 12 +- .../org/hl7/fhir/r4/formats/RdfParser.java | 2 +- .../org/hl7/fhir/r4/formats/XmlParser.java | 12 +- .../java/org/hl7/fhir/r4/model/Consent.java | 104 +++++++++--------- 6 files changed, 75 insertions(+), 75 deletions(-) diff --git a/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/conv30_40/resources30_40/Consent30_40.java b/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/conv30_40/resources30_40/Consent30_40.java index 1c783f74c..41dec2516 100644 --- a/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/conv30_40/resources30_40/Consent30_40.java +++ b/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/conv30_40/resources30_40/Consent30_40.java @@ -47,7 +47,7 @@ public class Consent30_40 { tgt.setPolicyRule(new CodeableConcept(c)); } if (src.hasSecurityLabel() || src.hasPeriod() || src.hasActor() || src.hasAction() || src.hasPurpose() || src.hasDataPeriod() || src.hasData() || src.hasExcept()) { - org.hl7.fhir.r4.model.Consent.provisionComponent pc = new org.hl7.fhir.r4.model.Consent.provisionComponent(); + org.hl7.fhir.r4.model.Consent.ProvisionComponent pc = new org.hl7.fhir.r4.model.Consent.ProvisionComponent(); if (src.hasPeriod()) pc.setPeriod(Period30_40.convertPeriod(src.getPeriod())); for (org.hl7.fhir.dstu3.model.Consent.ConsentActorComponent t : src.getActor()) @@ -104,7 +104,7 @@ public class Consent30_40 { } } if (src.hasProvision()) { - org.hl7.fhir.r4.model.Consent.provisionComponent p = src.getProvision(); + org.hl7.fhir.r4.model.Consent.ProvisionComponent p = src.getProvision(); if (p.hasPeriod()) tgt.setPeriod(Period30_40.convertPeriod(p.getPeriod())); for (org.hl7.fhir.r4.model.Consent.provisionActorComponent t : p.getActor()) @@ -117,7 +117,7 @@ public class Consent30_40 { tgt.setDataPeriod(Period30_40.convertPeriod(p.getDataPeriod())); for (org.hl7.fhir.r4.model.Consent.provisionDataComponent t : p.getData()) tgt.addData(convertConsentDataComponent(t)); - for (org.hl7.fhir.r4.model.Consent.provisionComponent t : p.getProvision()) + for (org.hl7.fhir.r4.model.Consent.ProvisionComponent t : p.getProvision()) tgt.addExcept(convertExceptComponent(t)); } return tgt; @@ -369,7 +369,7 @@ public class Consent30_40 { return tgt; } - static public org.hl7.fhir.dstu3.model.Consent.ExceptComponent convertExceptComponent(org.hl7.fhir.r4.model.Consent.provisionComponent src) throws FHIRException { + static public org.hl7.fhir.dstu3.model.Consent.ExceptComponent convertExceptComponent(org.hl7.fhir.r4.model.Consent.ProvisionComponent src) throws FHIRException { if (src == null) return null; org.hl7.fhir.dstu3.model.Consent.ExceptComponent tgt = new org.hl7.fhir.dstu3.model.Consent.ExceptComponent(); @@ -393,10 +393,10 @@ public class Consent30_40 { return tgt; } - static public org.hl7.fhir.r4.model.Consent.provisionComponent convertExceptComponent(org.hl7.fhir.dstu3.model.Consent.ExceptComponent src) throws FHIRException { + static public org.hl7.fhir.r4.model.Consent.ProvisionComponent convertExceptComponent(org.hl7.fhir.dstu3.model.Consent.ExceptComponent src) throws FHIRException { if (src == null) return null; - org.hl7.fhir.r4.model.Consent.provisionComponent tgt = new org.hl7.fhir.r4.model.Consent.provisionComponent(); + org.hl7.fhir.r4.model.Consent.ProvisionComponent tgt = new org.hl7.fhir.r4.model.Consent.ProvisionComponent(); ConversionContext30_40.INSTANCE.getVersionConvertor_30_40().copyBackboneElement(src,tgt); if (src.hasType()) tgt.setTypeElement(convertConsentExceptType(src.getTypeElement())); diff --git a/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/conv40_50/resources40_50/Consent40_50.java b/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/conv40_50/resources40_50/Consent40_50.java index 0fe389de5..727efa673 100644 --- a/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/conv40_50/resources40_50/Consent40_50.java +++ b/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/conv40_50/resources40_50/Consent40_50.java @@ -220,7 +220,7 @@ public class Consent40_50 { return tgt; } - public static org.hl7.fhir.r5.model.Consent.ProvisionComponent convertprovisionComponent(org.hl7.fhir.r4.model.Consent.provisionComponent src) throws FHIRException { + public static org.hl7.fhir.r5.model.Consent.ProvisionComponent convertprovisionComponent(org.hl7.fhir.r4.model.Consent.ProvisionComponent src) throws FHIRException { if (src == null) return null; org.hl7.fhir.r5.model.Consent.ProvisionComponent tgt = new org.hl7.fhir.r5.model.Consent.ProvisionComponent(); @@ -242,15 +242,15 @@ public class Consent40_50 { tgt.setDataPeriod(Period40_50.convertPeriod(src.getDataPeriod())); for (org.hl7.fhir.r4.model.Consent.provisionDataComponent t : src.getData()) tgt.addData(convertprovisionDataComponent(t)); - for (org.hl7.fhir.r4.model.Consent.provisionComponent t : src.getProvision()) + for (org.hl7.fhir.r4.model.Consent.ProvisionComponent t : src.getProvision()) tgt.addProvision(convertprovisionComponent(t)); return tgt; } - public static org.hl7.fhir.r4.model.Consent.provisionComponent convertprovisionComponent(org.hl7.fhir.r5.model.Consent.ProvisionComponent src) throws FHIRException { + public static org.hl7.fhir.r4.model.Consent.ProvisionComponent convertprovisionComponent(org.hl7.fhir.r5.model.Consent.ProvisionComponent src) throws FHIRException { if (src == null) return null; - org.hl7.fhir.r4.model.Consent.provisionComponent tgt = new org.hl7.fhir.r4.model.Consent.provisionComponent(); + org.hl7.fhir.r4.model.Consent.ProvisionComponent tgt = new org.hl7.fhir.r4.model.Consent.ProvisionComponent(); ConversionContext40_50.INSTANCE.getVersionConvertor_40_50().copyBackboneElement(src, tgt); // if (src.hasType()) // tgt.setTypeElement(convertConsentProvisionType(src.getTypeElement())); diff --git a/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/formats/JsonParser.java b/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/formats/JsonParser.java index 06ee27a94..49eff1638 100644 --- a/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/formats/JsonParser.java +++ b/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/formats/JsonParser.java @@ -8400,15 +8400,15 @@ public class JsonParser extends JsonParserBase { parseElementProperties(getJObject(json, "_verificationDate"), res.getVerificationDateElement()); } - protected Consent.provisionComponent parseConsentprovisionComponent(JsonObject json, Consent owner) + protected Consent.ProvisionComponent parseConsentprovisionComponent(JsonObject json, Consent owner) throws IOException, FHIRFormatError { - Consent.provisionComponent res = new Consent.provisionComponent(); + Consent.ProvisionComponent res = new Consent.ProvisionComponent(); parseConsentprovisionComponentProperties(json, owner, res); return res; } protected void parseConsentprovisionComponentProperties(JsonObject json, Consent owner, - Consent.provisionComponent res) throws IOException, FHIRFormatError { + Consent.ProvisionComponent res) throws IOException, FHIRFormatError { parseBackboneElementProperties(json, res); if (json.has("type")) res.setTypeElement(parseEnumeration(json.get("type").getAsString(), Consent.ConsentProvisionType.NULL, @@ -41383,7 +41383,7 @@ public class JsonParser extends JsonParserBase { } } - protected void composeConsentprovisionComponent(String name, Consent.provisionComponent element) throws IOException { + protected void composeConsentprovisionComponent(String name, Consent.ProvisionComponent element) throws IOException { if (element != null) { open(name); composeConsentprovisionComponentInner(element); @@ -41391,7 +41391,7 @@ public class JsonParser extends JsonParserBase { } } - protected void composeConsentprovisionComponentInner(Consent.provisionComponent element) throws IOException { + protected void composeConsentprovisionComponentInner(Consent.ProvisionComponent element) throws IOException { composeBackbone(element); if (element.hasTypeElement()) { composeEnumerationCore("type", element.getTypeElement(), new Consent.ConsentProvisionTypeEnumFactory(), false); @@ -41454,7 +41454,7 @@ public class JsonParser extends JsonParserBase { ; if (element.hasProvision()) { openArray("provision"); - for (Consent.provisionComponent e : element.getProvision()) + for (Consent.ProvisionComponent e : element.getProvision()) composeConsentprovisionComponent(null, e); closeArray(); } diff --git a/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/formats/RdfParser.java b/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/formats/RdfParser.java index e09127adc..76ffee7e9 100644 --- a/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/formats/RdfParser.java +++ b/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/formats/RdfParser.java @@ -4917,7 +4917,7 @@ public class RdfParser extends RdfParserBase { } protected void composeConsentprovisionComponent(Complex parent, String parentType, String name, - Consent.provisionComponent element, int index) { + Consent.ProvisionComponent element, int index) { if (element == null) return; Complex t; diff --git a/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/formats/XmlParser.java b/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/formats/XmlParser.java index 7ccf6fdd6..6c46487ea 100644 --- a/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/formats/XmlParser.java +++ b/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/formats/XmlParser.java @@ -6924,9 +6924,9 @@ public class XmlParser extends XmlParserBase { return true; } - protected Consent.provisionComponent parseConsentprovisionComponent(XmlPullParser xpp, Consent owner) + protected Consent.ProvisionComponent parseConsentprovisionComponent(XmlPullParser xpp, Consent owner) throws XmlPullParserException, IOException, FHIRFormatError { - Consent.provisionComponent res = new Consent.provisionComponent(); + Consent.ProvisionComponent res = new Consent.ProvisionComponent(); parseBackboneAttributes(xpp, res); next(xpp); int eventType = nextNoWhitespace(xpp); @@ -6941,7 +6941,7 @@ public class XmlParser extends XmlParserBase { } protected boolean parseConsentprovisionComponentContent(int eventType, XmlPullParser xpp, Consent owner, - Consent.provisionComponent res) throws XmlPullParserException, IOException, FHIRFormatError { + Consent.ProvisionComponent res) throws XmlPullParserException, IOException, FHIRFormatError { if (eventType == XmlPullParser.START_TAG && xpp.getName().equals("type")) { res.setTypeElement( parseEnumeration(xpp, Consent.ConsentProvisionType.NULL, new Consent.ConsentProvisionTypeEnumFactory())); @@ -34008,7 +34008,7 @@ public class XmlParser extends XmlParserBase { } } - protected void composeConsentprovisionComponent(String name, Consent.provisionComponent element) throws IOException { + protected void composeConsentprovisionComponent(String name, Consent.ProvisionComponent element) throws IOException { if (element != null) { composeElementAttributes(element); xml.enter(FHIR_NS, name); @@ -34018,7 +34018,7 @@ public class XmlParser extends XmlParserBase { } } - protected void composeConsentprovisionComponentElements(Consent.provisionComponent element) throws IOException { + protected void composeConsentprovisionComponentElements(Consent.ProvisionComponent element) throws IOException { composeBackboneElementElements(element); if (element.hasTypeElement()) composeEnumeration("type", element.getTypeElement(), new Consent.ConsentProvisionTypeEnumFactory()); @@ -34057,7 +34057,7 @@ public class XmlParser extends XmlParserBase { composeConsentprovisionDataComponent("data", e); } if (element.hasProvision()) { - for (Consent.provisionComponent e : element.getProvision()) + for (Consent.ProvisionComponent e : element.getProvision()) composeConsentprovisionComponent("provision", e); } } diff --git a/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/model/Consent.java b/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/model/Consent.java index 1560c3f27..eb2e25345 100644 --- a/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/model/Consent.java +++ b/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/model/Consent.java @@ -1221,7 +1221,7 @@ public class Consent extends DomainResource { } @Block() - public static class provisionComponent extends BackboneElement implements IBaseBackboneElement { + public static class ProvisionComponent extends BackboneElement implements IBaseBackboneElement { /** * Action to take - permit or deny - when the rule conditions are met. Not * permitted in root rule, required in all nested rules. @@ -1314,16 +1314,16 @@ public class Consent extends DomainResource { * Rules which provide exceptions to the base rule or subrules. */ @Child(name = "provision", type = { - provisionComponent.class }, order = 11, min = 0, max = Child.MAX_UNLIMITED, modifier = false, summary = false) + ProvisionComponent.class }, order = 11, min = 0, max = Child.MAX_UNLIMITED, modifier = false, summary = false) @Description(shortDefinition = "Nested Exception Rules", formalDefinition = "Rules which provide exceptions to the base rule or subrules.") - protected List provision; + protected List provision; private static final long serialVersionUID = -1280172451L; /** * Constructor */ - public provisionComponent() { + public ProvisionComponent() { super(); } @@ -1357,7 +1357,7 @@ public class Consent extends DomainResource { * extensions. The accessor "getType" gives direct access to the * value */ - public provisionComponent setTypeElement(Enumeration value) { + public ProvisionComponent setTypeElement(Enumeration value) { this.type = value; return this; } @@ -1374,7 +1374,7 @@ public class Consent extends DomainResource { * @param value Action to take - permit or deny - when the rule conditions are * met. Not permitted in root rule, required in all nested rules. */ - public provisionComponent setType(ConsentProvisionType value) { + public ProvisionComponent setType(ConsentProvisionType value) { if (value == null) this.type = null; else { @@ -1404,7 +1404,7 @@ public class Consent extends DomainResource { /** * @param value {@link #period} (The timeframe in this rule is valid.) */ - public provisionComponent setPeriod(Period value) { + public ProvisionComponent setPeriod(Period value) { this.period = value; return this; } @@ -1423,7 +1423,7 @@ public class Consent extends DomainResource { /** * @return Returns a reference to this for easy method chaining */ - public provisionComponent setActor(List theActor) { + public ProvisionComponent setActor(List theActor) { this.actor = theActor; return this; } @@ -1445,7 +1445,7 @@ public class Consent extends DomainResource { return t; } - public provisionComponent addActor(provisionActorComponent t) { // 3 + public ProvisionComponent addActor(provisionActorComponent t) { // 3 if (t == null) return this; if (this.actor == null) @@ -1477,7 +1477,7 @@ public class Consent extends DomainResource { /** * @return Returns a reference to this for easy method chaining */ - public provisionComponent setAction(List theAction) { + public ProvisionComponent setAction(List theAction) { this.action = theAction; return this; } @@ -1499,7 +1499,7 @@ public class Consent extends DomainResource { return t; } - public provisionComponent addAction(CodeableConcept t) { // 3 + public ProvisionComponent addAction(CodeableConcept t) { // 3 if (t == null) return this; if (this.action == null) @@ -1533,7 +1533,7 @@ public class Consent extends DomainResource { /** * @return Returns a reference to this for easy method chaining */ - public provisionComponent setSecurityLabel(List theSecurityLabel) { + public ProvisionComponent setSecurityLabel(List theSecurityLabel) { this.securityLabel = theSecurityLabel; return this; } @@ -1555,7 +1555,7 @@ public class Consent extends DomainResource { return t; } - public provisionComponent addSecurityLabel(Coding t) { // 3 + public ProvisionComponent addSecurityLabel(Coding t) { // 3 if (t == null) return this; if (this.securityLabel == null) @@ -1589,7 +1589,7 @@ public class Consent extends DomainResource { /** * @return Returns a reference to this for easy method chaining */ - public provisionComponent setPurpose(List thePurpose) { + public ProvisionComponent setPurpose(List thePurpose) { this.purpose = thePurpose; return this; } @@ -1611,7 +1611,7 @@ public class Consent extends DomainResource { return t; } - public provisionComponent addPurpose(Coding t) { // 3 + public ProvisionComponent addPurpose(Coding t) { // 3 if (t == null) return this; if (this.purpose == null) @@ -1646,7 +1646,7 @@ public class Consent extends DomainResource { /** * @return Returns a reference to this for easy method chaining */ - public provisionComponent setClass_(List theClass_) { + public ProvisionComponent setClass_(List theClass_) { this.class_ = theClass_; return this; } @@ -1668,7 +1668,7 @@ public class Consent extends DomainResource { return t; } - public provisionComponent addClass_(Coding t) { // 3 + public ProvisionComponent addClass_(Coding t) { // 3 if (t == null) return this; if (this.class_ == null) @@ -1701,7 +1701,7 @@ public class Consent extends DomainResource { /** * @return Returns a reference to this for easy method chaining */ - public provisionComponent setCode(List theCode) { + public ProvisionComponent setCode(List theCode) { this.code = theCode; return this; } @@ -1723,7 +1723,7 @@ public class Consent extends DomainResource { return t; } - public provisionComponent addCode(CodeableConcept t) { // 3 + public ProvisionComponent addCode(CodeableConcept t) { // 3 if (t == null) return this; if (this.code == null) @@ -1764,7 +1764,7 @@ public class Consent extends DomainResource { * @param value {@link #dataPeriod} (Clinical or Operational Relevant period of * time that bounds the data controlled by this rule.) */ - public provisionComponent setDataPeriod(Period value) { + public ProvisionComponent setDataPeriod(Period value) { this.dataPeriod = value; return this; } @@ -1782,7 +1782,7 @@ public class Consent extends DomainResource { /** * @return Returns a reference to this for easy method chaining */ - public provisionComponent setData(List theData) { + public ProvisionComponent setData(List theData) { this.data = theData; return this; } @@ -1804,7 +1804,7 @@ public class Consent extends DomainResource { return t; } - public provisionComponent addData(provisionDataComponent t) { // 3 + public ProvisionComponent addData(provisionDataComponent t) { // 3 if (t == null) return this; if (this.data == null) @@ -1828,16 +1828,16 @@ public class Consent extends DomainResource { * @return {@link #provision} (Rules which provide exceptions to the base rule * or subrules.) */ - public List getProvision() { + public List getProvision() { if (this.provision == null) - this.provision = new ArrayList(); + this.provision = new ArrayList(); return this.provision; } /** * @return Returns a reference to this for easy method chaining */ - public provisionComponent setProvision(List theProvision) { + public ProvisionComponent setProvision(List theProvision) { this.provision = theProvision; return this; } @@ -1845,25 +1845,25 @@ public class Consent extends DomainResource { public boolean hasProvision() { if (this.provision == null) return false; - for (provisionComponent item : this.provision) + for (ProvisionComponent item : this.provision) if (!item.isEmpty()) return true; return false; } - public provisionComponent addProvision() { // 3 - provisionComponent t = new provisionComponent(); + public ProvisionComponent addProvision() { // 3 + ProvisionComponent t = new ProvisionComponent(); if (this.provision == null) - this.provision = new ArrayList(); + this.provision = new ArrayList(); this.provision.add(t); return t; } - public provisionComponent addProvision(provisionComponent t) { // 3 + public ProvisionComponent addProvision(ProvisionComponent t) { // 3 if (t == null) return this; if (this.provision == null) - this.provision = new ArrayList(); + this.provision = new ArrayList(); this.provision.add(t); return this; } @@ -1872,7 +1872,7 @@ public class Consent extends DomainResource { * @return The first repetition of repeating field {@link #provision}, creating * it if it does not already exist */ - public provisionComponent getProvisionFirstRep() { + public ProvisionComponent getProvisionFirstRep() { if (getProvision().isEmpty()) { addProvision(); } @@ -2027,7 +2027,7 @@ public class Consent extends DomainResource { this.getData().add((provisionDataComponent) value); // provisionDataComponent return value; case -547120939: // provision - this.getProvision().add((provisionComponent) value); // provisionComponent + this.getProvision().add((ProvisionComponent) value); // provisionComponent return value; default: return super.setProperty(hash, name, value); @@ -2059,7 +2059,7 @@ public class Consent extends DomainResource { } else if (name.equals("data")) { this.getData().add((provisionDataComponent) value); } else if (name.equals("provision")) { - this.getProvision().add((provisionComponent) value); + this.getProvision().add((ProvisionComponent) value); } else return super.setProperty(name, value); return value; @@ -2088,7 +2088,7 @@ public class Consent extends DomainResource { } else if (name.equals("data")) { this.getData().remove((provisionDataComponent) value); } else if (name.equals("provision")) { - this.getProvision().remove((provisionComponent) value); + this.getProvision().remove((ProvisionComponent) value); } else super.removeChild(name, value); @@ -2186,13 +2186,13 @@ public class Consent extends DomainResource { return super.addChild(name); } - public provisionComponent copy() { - provisionComponent dst = new provisionComponent(); + public ProvisionComponent copy() { + ProvisionComponent dst = new ProvisionComponent(); copyValues(dst); return dst; } - public void copyValues(provisionComponent dst) { + public void copyValues(ProvisionComponent dst) { super.copyValues(dst); dst.type = type == null ? null : type.copy(); dst.period = period == null ? null : period.copy(); @@ -2240,8 +2240,8 @@ public class Consent extends DomainResource { } ; if (provision != null) { - dst.provision = new ArrayList(); - for (provisionComponent i : provision) + dst.provision = new ArrayList(); + for (ProvisionComponent i : provision) dst.provision.add(i.copy()); } ; @@ -2251,9 +2251,9 @@ public class Consent extends DomainResource { public boolean equalsDeep(Base other_) { if (!super.equalsDeep(other_)) return false; - if (!(other_ instanceof provisionComponent)) + if (!(other_ instanceof ProvisionComponent)) return false; - provisionComponent o = (provisionComponent) other_; + ProvisionComponent o = (ProvisionComponent) other_; return compareDeep(type, o.type, true) && compareDeep(period, o.period, true) && compareDeep(actor, o.actor, true) && compareDeep(action, o.action, true) && compareDeep(securityLabel, o.securityLabel, true) && compareDeep(purpose, o.purpose, true) && compareDeep(class_, o.class_, true) @@ -2265,9 +2265,9 @@ public class Consent extends DomainResource { public boolean equalsShallow(Base other_) { if (!super.equalsShallow(other_)) return false; - if (!(other_ instanceof provisionComponent)) + if (!(other_ instanceof ProvisionComponent)) return false; - provisionComponent o = (provisionComponent) other_; + ProvisionComponent o = (ProvisionComponent) other_; return compareValues(type, o.type, true); } @@ -3002,7 +3002,7 @@ public class Consent extends DomainResource { */ @Child(name = "provision", type = {}, order = 12, min = 0, max = 1, modifier = false, summary = true) @Description(shortDefinition = "Constraints to the base Consent.policyRule", formalDefinition = "An exception to the base policy of this consent. An exception can be an addition or removal of access permissions.") - protected provisionComponent provision; + protected ProvisionComponent provision; private static final long serialVersionUID = 206528051L; @@ -3669,12 +3669,12 @@ public class Consent extends DomainResource { * @return {@link #provision} (An exception to the base policy of this consent. * An exception can be an addition or removal of access permissions.) */ - public provisionComponent getProvision() { + public ProvisionComponent getProvision() { if (this.provision == null) if (Configuration.errorOnAutoCreate()) throw new Error("Attempt to auto-create Consent.provision"); else if (Configuration.doAutoCreate()) - this.provision = new provisionComponent(); // cc + this.provision = new ProvisionComponent(); // cc return this.provision; } @@ -3687,7 +3687,7 @@ public class Consent extends DomainResource { * consent. An exception can be an addition or removal of access * permissions.) */ - public Consent setProvision(provisionComponent value) { + public Consent setProvision(ProvisionComponent value) { this.provision = value; return this; } @@ -3883,7 +3883,7 @@ public class Consent extends DomainResource { this.getVerification().add((ConsentVerificationComponent) value); // ConsentVerificationComponent return value; case -547120939: // provision - this.provision = (provisionComponent) value; // provisionComponent + this.provision = (ProvisionComponent) value; // provisionComponent return value; default: return super.setProperty(hash, name, value); @@ -3919,7 +3919,7 @@ public class Consent extends DomainResource { } else if (name.equals("verification")) { this.getVerification().add((ConsentVerificationComponent) value); } else if (name.equals("provision")) { - this.provision = (provisionComponent) value; // provisionComponent + this.provision = (ProvisionComponent) value; // provisionComponent } else return super.setProperty(name, value); return value; @@ -3952,7 +3952,7 @@ public class Consent extends DomainResource { } else if (name.equals("verification")) { this.getVerification().remove((ConsentVerificationComponent) value); } else if (name.equals("provision")) { - this.provision = (provisionComponent) value; // provisionComponent + this.provision = (ProvisionComponent) value; // provisionComponent } else super.removeChild(name, value); @@ -4064,7 +4064,7 @@ public class Consent extends DomainResource { } else if (name.equals("verification")) { return addVerification(); } else if (name.equals("provision")) { - this.provision = new provisionComponent(); + this.provision = new ProvisionComponent(); return this.provision; } else return super.addChild(name); From eab82767534374b1b0994a35815b0c0c649e299f Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Wed, 18 Sep 2024 14:51:15 +1000 Subject: [PATCH 49/50] update test case dependency --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index aac61867c..883b784e5 100644 --- a/pom.xml +++ b/pom.xml @@ -21,7 +21,7 @@ 1.26.0 32.0.1-jre 6.4.1 - 1.5.22 + 1.5.23-SNAPSHOT 2.17.0 5.9.2 1.8.2 From 9a7a843a207b34e72f27a5ed27eb752bb2305b61 Mon Sep 17 00:00:00 2001 From: dotasek Date: Wed, 18 Sep 2024 10:15:38 -0400 Subject: [PATCH 50/50] Fix argument confusion in format (#1746) * Fix argument confusion in format * Bump test cases --- .../src/main/java/org/hl7/fhir/utilities/i18n/I18nBase.java | 2 +- pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/i18n/I18nBase.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/i18n/I18nBase.java index 09b7782f3..6470514c6 100644 --- a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/i18n/I18nBase.java +++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/i18n/I18nBase.java @@ -125,7 +125,7 @@ public abstract class I18nBase { if (Objects.nonNull(theMessageArguments) && theMessageArguments.length > 0) { message = MessageFormat.format(messages.getString(theMessage).trim(), theMessageArguments); } else { - message = MessageFormat.format(messages.getString(theMessage).trim(), null); + message = MessageFormat.format(messages.getString(theMessage).trim(), (Object) null); } } return message; diff --git a/pom.xml b/pom.xml index aac61867c..883b784e5 100644 --- a/pom.xml +++ b/pom.xml @@ -21,7 +21,7 @@ 1.26.0 32.0.1-jre 6.4.1 - 1.5.22 + 1.5.23-SNAPSHOT 2.17.0 5.9.2 1.8.2