This commit is contained in:
Lloyd McKenzie 2024-09-19 13:25:14 -06:00
commit 8b90d6fee4
71 changed files with 1103 additions and 527 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 30 KiB

View File

@ -1,5 +1,5 @@
Locale,Coverage #,Coverage %
de,831,41%
de,831,40%
es,714,35%
ja,902,44%
nl,1989,98%

1 Locale Coverage # Coverage %
2 de 831 41% 40%
3 es 714 35%
4 ja 902 44%
5 nl 1989 98%

View File

@ -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 '

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>org.hl7.fhir.core</artifactId>
<version>6.3.24-SNAPSHOT</version>
<version>6.3.27-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -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()));

View File

@ -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()));

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>org.hl7.fhir.core</artifactId>
<version>6.3.24-SNAPSHOT</version>
<version>6.3.27-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>org.hl7.fhir.core</artifactId>
<version>6.3.24-SNAPSHOT</version>
<version>6.3.27-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>org.hl7.fhir.core</artifactId>
<version>6.3.24-SNAPSHOT</version>
<version>6.3.27-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -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() {

View File

@ -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;
}
}

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>org.hl7.fhir.core</artifactId>
<version>6.3.24-SNAPSHOT</version>
<version>6.3.27-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -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();
}

View File

@ -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;

View File

@ -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);
}
}

View File

@ -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<provisionComponent> provision;
protected List<ProvisionComponent> 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<ConsentProvisionType> value) {
public ProvisionComponent setTypeElement(Enumeration<ConsentProvisionType> 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 <code>this</code> for easy method chaining
*/
public provisionComponent setActor(List<provisionActorComponent> theActor) {
public ProvisionComponent setActor(List<provisionActorComponent> 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 <code>this</code> for easy method chaining
*/
public provisionComponent setAction(List<CodeableConcept> theAction) {
public ProvisionComponent setAction(List<CodeableConcept> 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 <code>this</code> for easy method chaining
*/
public provisionComponent setSecurityLabel(List<Coding> theSecurityLabel) {
public ProvisionComponent setSecurityLabel(List<Coding> 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 <code>this</code> for easy method chaining
*/
public provisionComponent setPurpose(List<Coding> thePurpose) {
public ProvisionComponent setPurpose(List<Coding> 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 <code>this</code> for easy method chaining
*/
public provisionComponent setClass_(List<Coding> theClass_) {
public ProvisionComponent setClass_(List<Coding> 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 <code>this</code> for easy method chaining
*/
public provisionComponent setCode(List<CodeableConcept> theCode) {
public ProvisionComponent setCode(List<CodeableConcept> 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 <code>this</code> for easy method chaining
*/
public provisionComponent setData(List<provisionDataComponent> theData) {
public ProvisionComponent setData(List<provisionDataComponent> 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<provisionComponent> getProvision() {
public List<ProvisionComponent> getProvision() {
if (this.provision == null)
this.provision = new ArrayList<provisionComponent>();
this.provision = new ArrayList<ProvisionComponent>();
return this.provision;
}
/**
* @return Returns a reference to <code>this</code> for easy method chaining
*/
public provisionComponent setProvision(List<provisionComponent> theProvision) {
public ProvisionComponent setProvision(List<ProvisionComponent> 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<provisionComponent>();
this.provision = new ArrayList<ProvisionComponent>();
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<provisionComponent>();
this.provision = new ArrayList<ProvisionComponent>();
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<provisionComponent>();
for (provisionComponent i : provision)
dst.provision = new ArrayList<ProvisionComponent>();
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);

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>org.hl7.fhir.core</artifactId>
<version>6.3.24-SNAPSHOT</version>
<version>6.3.27-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>org.hl7.fhir.core</artifactId>
<version>6.3.24-SNAPSHOT</version>
<version>6.3.27-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -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<ElementDefinition> 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<ElementDefinition> 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<ElementDefinition> 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));

View File

@ -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<ValidationMessage> messages;
private List<ValidationMessage> messages = new ArrayList<ValidationMessage>();
private List<String> snapshotStack = new ArrayList<String>();
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<StructureDefinition> obligationProfiles = new ArrayList<>();
private boolean wantThrowExceptions;
public ProfileUtilities(IWorkerContext context, List<ValidationMessage> 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<ValidationMessage> 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);
@ -739,7 +747,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)) {
@ -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) {
@ -1042,7 +1050,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 +1556,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 +1918,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 +1936,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));
}
}
}
@ -2250,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));
@ -2371,7 +2378,6 @@ public class ProfileUtilities {
if (elist.size() == 2) {
dest.getExtension().remove(elist.get(1));
}
updateExtensionsFromDefinition(dest, source);
for (ElementDefinition ed : obligationProfileElements) {
@ -2423,6 +2429,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 +2475,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);
@ -2528,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);
@ -2539,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);
@ -2641,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)
@ -2653,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)
@ -2720,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()) {
@ -2749,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();
@ -2964,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 {
@ -2988,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)) {
@ -3021,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));
}
}
@ -3463,6 +3466,11 @@ public class ProfileUtilities {
public void sortDifferential(StructureDefinition base, StructureDefinition diff, String name, List<String> errors, boolean errorIfChanges) throws FHIRException {
int index = 0;
for (ElementDefinition ed : diff.getDifferential().getElement()) {
ed.setUserData("ed.index", Integer.toString(index));
index++;
}
List<ElementDefinition> original = new ArrayList<>();
original.addAll(diff.getDifferential().getElement());
final List<ElementDefinition> diffList = diff.getDifferential().getElement();
@ -3520,7 +3528,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;
}
}
@ -3930,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("#")) {
@ -4309,12 +4314,12 @@ public class ProfileUtilities {
public boolean isThrowException() {
return exception;
return wantThrowExceptions;
}
public void setThrowException(boolean exception) {
this.exception = exception;
this.wantThrowExceptions = exception;
}
@ -4572,7 +4577,9 @@ public class ProfileUtilities {
}
public void setMessages(List<ValidationMessage> messages) {
this.messages = messages;
if (messages != null) {
this.messages = messages;
}
}
private Map<String, List<Property>> propertyCache = new HashMap<>();

View File

@ -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);

View File

@ -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;
}

View File

@ -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()) {
// Create a copy of the children collection before iterating
List<Element> childrenCopy = List.copyOf(element.getChildren());
for (Element c : childrenCopy) {
if (!c.getName().equals("designation")) {
t = t + importFromTranslations(element, c, translations, usedUnits);
}

View File

@ -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 == '/') {

View File

@ -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<Base> evaluate(Object appContext, Base base, ExpressionNode ExpressionNode) throws FHIRException {
List<Base> list = new ArrayList<Base>();
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()) {

View File

@ -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);
@ -3421,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);
}
}

View File

@ -750,20 +750,11 @@ 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");
}
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<String> langs, Map<String, String> 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);

View File

@ -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 {

View File

@ -1,25 +1,17 @@
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.i18n.I18nConstants;
public class ValueSetSpreadsheetGenerator extends CanonicalSpreadsheetGenerator {
@ -36,11 +28,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 +75,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 +100,14 @@ 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) {
Sheet sheet = makeSheet(mode+" #"+count);
if (inc.hasValueSet()) {
addValueSets(sheet, inc.getValueSet());
}

View File

@ -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;
}

View File

@ -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<WorkingContext> 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<WorkingContext> 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);

View File

@ -124,11 +124,9 @@ public class ValueSetValidator extends ValueSetProcessBase {
}
public String getMessage() {
return message;
}
}
}
private ValueSet valueset;
private Map<String, ValueSetValidator> inner = new HashMap<>();
private ValidationOptions options;

View File

@ -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<Cell>());
for (JsonObject select : vd.getJsonObjects("select")) {
executeSelect(select, b, rows);
executeSelect(vd, select, b, rows);
}
for (List<Cell> 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<List<Cell>> rows) {
private void executeSelect(JsonObject vd, JsonObject select, Base b, List<List<Cell>> rows) {
List<Base> 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<Column> columns = (List<Column>) select.getUserData("columns");
for (List<Cell> row : rows) {
@ -159,20 +159,20 @@ public class Runner implements IEvaluationContext {
List<List<Cell>> 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<JsonObject> unionList, Base b, List<List<Cell>> rows) {
private void executeUnionAll(JsonObject vd, List<JsonObject> unionList, Base b, List<List<Cell>> rows) {
if (unionList.isEmpty()) {
return;
}
@ -183,7 +183,7 @@ public class Runner implements IEvaluationContext {
for (JsonObject union : unionList) {
List<List<Cell>> 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<Base> executeForEach(JsonObject focus, Base b) {
private List<Base> executeForEach(JsonObject vd, JsonObject focus, Base b) {
ExpressionNode n = (ExpressionNode) focus.getUserData("forEach");
List<Base> result = new ArrayList<>();
result.addAll(fpe.evaluate(b, n));
result.addAll(fpe.evaluate(vd, b, n));
return result;
}
private List<Base> executeForEachOrNull(JsonObject focus, Base b) {
private List<Base> executeForEachOrNull(JsonObject vd, JsonObject focus, Base b) {
ExpressionNode n = (ExpressionNode) focus.getUserData("forEachOrNull");
List<Base> 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<List<Cell>> rows) {
private void executeColumn(JsonObject vd, JsonObject column, Base b, List<List<Cell>> rows) {
ExpressionNode n = (ExpressionNode) column.getUserData("path");
List<Base> 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<Base> resolveConstant(FHIRPathEngine engine, Object appContext, String name, boolean beforeContext, boolean explicitConstant) throws PathEngineException {
throw new Error("Not implemented yet: resolveConstant");
List<Base> list = new ArrayList<Base>();
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<Base> focus) {
throw new Error("Not implemented yet: log");

View File

@ -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

View File

@ -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<Column> checkSelect(String path, JsonObject select, TypeDetails t) {
private List<Column> checkSelect(JsonObject vd, String path, JsonObject select, TypeDetails t) {
List<Column> 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<Column> checkUnion(String path, JsonObject focus, JsonElement expression, TypeDetails t) {
private List<Column> 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<String> 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);
}

View File

@ -0,0 +1,55 @@
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.*;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
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<LanguageFileProducer.TranslationUnit> res = new ArrayList<>();
res.addAll(lp.loadSource(getResourceAsInputStream("languageUtils", "CodeSystem-answer.po")));
List<ValidationMessage> lvm = new ArrayList<>();
lvm.add(new ValidationMessage());
LanguageUtils languageUtils = new LanguageUtils(context);
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);
}
}

View File

@ -83,23 +83,21 @@ public class SQLOnFhirTests {
this.resources = resources;
this.testCase = testCase;
}
}
public static Stream<Arguments> data() throws ParserConfigurationException, SAXException, IOException {
List<Arguments> 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<JsonObject> 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<JsonObject> 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);

View File

@ -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

View File

@ -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"
} ]
} ]
}

View File

@ -0,0 +1,30 @@
{
"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"
},
{
"code": "yes",
"display": "Yes"
},
{
"code": "no",
"display": "No"
}
],
"language": "en",
"version": "0.1.0",
"date": "2024-04-07",
"publisher": "Sample",
"caseSensitive": false,
"count": 3
}

View File

@ -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"

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>org.hl7.fhir.core</artifactId>
<version>6.3.24-SNAPSHOT</version>
<version>6.3.27-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
@ -89,7 +89,7 @@
<groupId>org.sonatype.plugins</groupId>
<artifactId>nexus-staging-maven-plugin</artifactId>
<configuration>
<skipStaging>true</skipStaging>
<skipNexusStagingDeployMojo>true</skipNexusStagingDeployMojo>
</configuration>
</plugin>
<plugin>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>org.hl7.fhir.core</artifactId>
<version>6.3.24-SNAPSHOT</version>
<version>6.3.27-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -1491,7 +1491,7 @@ public class Utilities {
}
public static boolean startsWithInList(String s, Collection<String> list) {
if (s == null) {
if (s == null || list == null) {
return false;
}
for (String l : list) {
@ -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;
}
@ -2304,4 +2309,16 @@ public class Utilities {
}
}
public static boolean listValueStartsWith(String s, Set<String> list) {
if (s == null || list == null) {
return false;
}
for (String l : list) {
if (l.startsWith(s)) {
return true;
}
}
return false;
}
}

View File

@ -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;

View File

@ -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";
}

View File

@ -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 {

View File

@ -237,9 +237,11 @@ public class NpmPackage {
public List<String> listFiles() {
List<String> 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 {
@ -648,7 +650,17 @@ public class NpmPackage {
}
/**
* Create a package .index.json file for a package folder.
* <p>
* See <a href="https://hl7.org/fhir/packages.html#2.1.10.4">the FHIR specification</a> 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<String> remove = new ArrayList<>();
NpmPackageIndexBuilder indexer = new NpmPackageIndexBuilder();

View File

@ -30,61 +30,74 @@ 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("/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/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 {
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 {
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());
System.out.println("Loading Package "+f.getAbsolutePath());
NpmPackage pck = null;
FileInputStream fs = ManagedFileAccess.inStream(f);
try {
@ -95,7 +108,7 @@ public class PackageHacker {
System.out.println("Altering Package "+f.getAbsolutePath());
System.out.println(nice(pck.getNpm()));
change(pck.getNpm());
if (change(pck.getNpm(), path)) {
System.out.println("Revised Package");
System.out.println("=======================");
@ -111,7 +124,8 @@ public class PackageHacker {
} finally {
fso.close();
}
}
}
}
}
private void fixExampleContent(Map<String, byte[]> content) {
@ -129,10 +143,15 @@ public class PackageHacker {
return JsonParser.compose(json, true);
}
private void change(JsonObject npm) throws FileNotFoundException, IOException {
// fixVersions(npm, ver);
npm.remove("notForPublication");
npm.set("name", "hl7.fhir.us.vitals");
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<String, byte[]> content) {

View File

@ -560,7 +560,6 @@ public class HierarchicalTableGenerator {
}
return b.toString();
}
}
public class TableModel {

View File

@ -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

View File

@ -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 {

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>org.hl7.fhir.core</artifactId>
<version>6.3.24-SNAPSHOT</version>
<version>6.3.27-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
@ -405,7 +405,7 @@
<groupId>org.sonatype.plugins</groupId>
<artifactId>nexus-staging-maven-plugin</artifactId>
<configuration>
<skipStaging>true</skipStaging>
<skipNexusStagingDeployMojo>true</skipNexusStagingDeployMojo>
</configuration>
</plugin>
<plugin>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>org.hl7.fhir.core</artifactId>
<version>6.3.24-SNAPSHOT</version>
<version>6.3.27-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
@ -119,37 +119,6 @@
<optional>true</optional>
</dependency>
<!-- CQL-to-ELM -->
<dependency>
<groupId>info.cqframework</groupId>
<artifactId>cql</artifactId>
<version>${info_cqframework_version}</version>
</dependency>
<dependency>
<groupId>info.cqframework</groupId>
<artifactId>model</artifactId>
<version>${info_cqframework_version}</version>
</dependency>
<dependency>
<groupId>info.cqframework</groupId>
<artifactId>elm</artifactId>
<version>${info_cqframework_version}</version>
</dependency>
<dependency>
<groupId>info.cqframework</groupId>
<artifactId>cql-to-elm</artifactId>
<version>${info_cqframework_version}</version>
</dependency>
<dependency>
<groupId>info.cqframework</groupId>
<artifactId>quick</artifactId>
<version>${info_cqframework_version}</version>
</dependency>
<dependency>
<groupId>info.cqframework</groupId>
<artifactId>qdm</artifactId>
<version>${info_cqframework_version}</version>
</dependency>
<!-- OkHttpDependency -->
<dependency>
<groupId>com.squareup.okhttp3</groupId>

View File

@ -226,6 +226,8 @@ 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 boolean noExperimentalContent;
@Getter @Setter private Locale locale;
@Getter @Setter private List<ImplementationGuide> igs = new ArrayList<>();
@Getter @Setter private List<String> extensionDomains = new ArrayList<>();
@ -289,6 +291,7 @@ public class ValidationEngine implements IValidatorResourceFetcher, IValidationP
fhirPathEngine = other.fhirPathEngine;
igLoader = other.igLoader;
jurisdiction = other.jurisdiction;
unknownCodeSystemsCauseErrors = other.unknownCodeSystemsCauseErrors;
}
/**
@ -906,6 +909,8 @@ public class ValidationEngine implements IValidatorResourceFetcher, IValidationP
if (policyAdvisor != null) {
validator.setPolicyAdvisor(policyAdvisor);
}
validator.setUnknownCodeSystemsCauseErrors(unknownCodeSystemsCauseErrors);
validator.setNoExperimentalContent(noExperimentalContent);
return validator;
}

View File

@ -163,6 +163,12 @@ public class CliContext {
@JsonProperty("bestPracticeLevel")
private BestPracticeWarningLevel bestPracticeLevel = BestPracticeWarningLevel.Warning;
@JsonProperty("unknownCodeSystemsCauseErrors")
private boolean unknownCodeSystemsCauseErrors;
@JsonProperty("noExperimentalContent")
private boolean noExperimentalContent;
@JsonProperty("baseEngine")
public String getBaseEngine() {
return baseEngine;
@ -832,6 +838,8 @@ 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(noExperimentalContent, that.noExperimentalContent) &&
Objects.equals(watchSettleTime, that.watchSettleTime) ;
}
@ -839,8 +847,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, noExperimentalContent, htmlInMarkdownCheck, allowDoubleQuotesInFHIRPath, checkIPSCodes);
}
@Override
@ -899,6 +907,8 @@ public class CliContext {
", bestPracticeLevel=" + bestPracticeLevel +
", watchSettleTime=" + watchSettleTime +
", watchScanDelay=" + watchScanDelay +
", unknownCodeSystemsCauseErrors=" + unknownCodeSystemsCauseErrors +
", noExperimentalContent=" + noExperimentalContent +
'}';
}
@ -956,4 +966,28 @@ public class CliContext {
return this;
}
@JsonProperty("unknownCodeSystemsCauseErrors")
public boolean isUnknownCodeSystemsCauseErrors() {
return unknownCodeSystemsCauseErrors;
}
@JsonProperty("unknownCodeSystemsCauseErrors")
public void setUnknownCodeSystemsCauseErrors(boolean unknownCodeSystemsCauseErrors) {
this.unknownCodeSystemsCauseErrors = unknownCodeSystemsCauseErrors;
}
@JsonProperty("noExperimentalContent")
public boolean isNoExperimentalContent() {
return noExperimentalContent;
}
@JsonProperty("noExperimentalContent")
public void setNoExperimentalContent(boolean noExperimentalContent) {
this.noExperimentalContent = noExperimentalContent;
}
}

View File

@ -581,6 +581,8 @@ 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() + ")");

View File

@ -94,8 +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 NO_EXPERIMENTAL_CONTENT = "-no-experimental-content";
public static final String RUN_TESTS = "-run-tests";
@ -320,6 +320,10 @@ 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(NO_EXPERIMENTAL_CONTENT)) {
cliContext.setNoExperimentalContent(true);
} else if (args[i].equals(VERBOSE)) {
cliContext.setCrumbTrails(true);
} else if (args[i].equals(ALLOW_EXAMPLE_URLS)) {

View File

@ -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;
@ -598,6 +598,8 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
private boolean example ;
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);
@ -1125,7 +1127,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 +1383,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 +1467,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 +1535,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<String> 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<ValidationMessage> 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<ValidationMessage> 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 +1570,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 +1618,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 +1747,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 +1792,21 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
return ok;
}
private Set<String> getUnknownSystems(ValidationResult vr) {
if (vr == null) {
return null;
}
if (vr.getUnknownSystems() != null && !vr.getUnknownSystems().isEmpty()) {
return vr.getUnknownSystems();
}
if (vr.getSystem() != null) {
Set<String> set = new HashSet<String>();
set.add(vr.getSystem());
return set;
}
return null;
}
private boolean convertCDACodeToCodeableConcept(List<ValidationMessage> errors, String path, Element element, StructureDefinition logical, CodeableConcept cc) {
boolean ok = true;
cc.setText(element.getNamedChildValue("originalText", false));
@ -1851,7 +1892,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 +1931,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 +1962,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 +2086,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 +3551,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) {
@ -5678,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;
@ -7791,4 +7836,22 @@ 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;
}
public boolean isNoExperimentalContent() {
return noExperimentalContent;
}
public void setNoExperimentalContent(boolean noExperimentalContent) {
this.noExperimentalContent = noExperimentalContent;
}
}

View File

@ -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<CMCodingValidationRequest> batch = new ArrayList<>();
private final List<CMCodingValidationRequest> 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<String> 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)));

View File

@ -85,6 +85,7 @@ public class StructureDefinitionValidator extends BaseValidator {
List<ElementDefinition> 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<Element> 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<ValidationMessage> 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<ValidationMessage> 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<String, String> invariantMap = new HashMap<>();
boolean ok = true;
List<Element> 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<ValidationMessage> errors, List<Element> elements, Element element, NodeStack stack, boolean snapshot, boolean hasSnapshot, StructureDefinition sd, String typeName, boolean logical, boolean constraint, Map<String, String> invariantMap, String rootPath, String profileUrl, String profileType, StructureDefinition base) {
private boolean validateElementDefinition(List<ValidationMessage> errors, List<Element> elements, Element element, NodeStack stack, boolean snapshot, boolean hasSnapshot, StructureDefinition sd, String typeName, boolean logical, boolean constraint, Map<String, String> 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<ValidationMessage> errors, Element binding, NodeStack stack, Set<String> typeCodes, boolean snapshot, String path) {
private boolean validateBinding(List<ValidationMessage> errors, Element binding, NodeStack stack, Set<String> 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;
}
}
}
}

View File

@ -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

View File

@ -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;

View File

@ -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);
}

View File

@ -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);
}

10
pom.xml
View File

@ -14,14 +14,14 @@
HAPI FHIR
-->
<artifactId>org.hl7.fhir.core</artifactId>
<version>6.3.24-SNAPSHOT</version>
<version>6.3.27-SNAPSHOT</version>
<packaging>pom</packaging>
<properties>
<commons_compress_version>1.26.0</commons_compress_version>
<guava_version>32.0.1-jre</guava_version>
<hapi_fhir_version>6.4.1</hapi_fhir_version>
<validator_test_case_version>1.5.20</validator_test_case_version>
<validator_test_case_version>1.5.23-SNAPSHOT</validator_test_case_version>
<jackson_version>2.17.0</jackson_version>
<junit_jupiter_version>5.9.2</junit_jupiter_version>
<junit_platform_launcher_version>1.8.2</junit_platform_launcher_version>
@ -418,7 +418,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.10.1</version>
<version>3.13.0</version>
<configuration>
<release>11</release>
@ -428,7 +428,7 @@
while if true it will use an executable. -->
<fork>true</fork>
<meminitial>512m</meminitial>
<maxmem>4000m</maxmem>
<maxmem>5632m</maxmem>
<debug>true</debug>
</configuration>
<executions>
@ -717,7 +717,7 @@
<plugin>
<groupId>org.sonatype.plugins</groupId>
<artifactId>nexus-staging-maven-plugin</artifactId>
<version>1.6.13</version>
<version>1.7.0</version>
<extensions>true</extensions>
<configuration>
<serverId>ossrh</serverId>

View File

@ -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'

View File

@ -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'

View File

@ -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) }}:

View File

@ -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'

View File

@ -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'