diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/5_1_0/2005-snapshot-parents-first.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/5_1_0/2005-snapshot-parents-first.yaml new file mode 100644 index 00000000000..226de7bb843 --- /dev/null +++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/5_1_0/2005-snapshot-parents-first.yaml @@ -0,0 +1,5 @@ +--- +type: fix +issue: 2005 +title: When generating a snapshot for a StructureDefinition that extends another non-base StructureDefinition, if the parent + SD did not have a snapshot itself, the child snapshot would be empty. This has been corrected. diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4StructureDefinitionTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4StructureDefinitionTest.java index d2fb98206a0..4fbec4009ee 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4StructureDefinitionTest.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4StructureDefinitionTest.java @@ -13,6 +13,7 @@ import org.junit.jupiter.api.Test; import java.io.IOException; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; @SuppressWarnings({"unchecked", "deprecation"}) public class FhirResourceDaoR4StructureDefinitionTest extends BaseJpaR4Test { @@ -47,5 +48,24 @@ public class FhirResourceDaoR4StructureDefinitionTest extends BaseJpaR4Test { } + /** + * Make sure that if one SD extends another SD, and the parent SD hasn't been snapshotted itself, the child can + * be snapshotted. + */ + @Test + public void testGenerateSnapshotChained() throws IOException { + StructureDefinition sd = loadResourceFromClasspath(StructureDefinition.class, "/r4/StructureDefinition-kfdrc-patient.json"); + myStructureDefinitionDao.update(sd); + + StructureDefinition sd2 = loadResourceFromClasspath(StructureDefinition.class, "/r4/StructureDefinition-kfdrc-patient-no-phi.json"); + myStructureDefinitionDao.update(sd2); + + StructureDefinition snapshotted = myStructureDefinitionDao.generateSnapshot(sd2, null, null, null); + ourLog.info(myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(snapshotted)); + + assertTrue(snapshotted.getSnapshot().getElement().size() > 0); + } + + } diff --git a/hapi-fhir-jpaserver-base/src/test/resources/r4/StructureDefinition-kfdrc-patient-no-phi.json b/hapi-fhir-jpaserver-base/src/test/resources/r4/StructureDefinition-kfdrc-patient-no-phi.json new file mode 100644 index 00000000000..b951fd455b3 --- /dev/null +++ b/hapi-fhir-jpaserver-base/src/test/resources/r4/StructureDefinition-kfdrc-patient-no-phi.json @@ -0,0 +1,62 @@ +{ + "resourceType": "StructureDefinition", + "id": "kfdrc-patient-no-phi", + "url": "http://fhir.kids-first.io/StructureDefinition/kfdrc-patient-no-phi", + "version": "0.1.0", + "name": "kfdrc-patient-no-phi", + "title": "Kids First DRC Patient without Protected Health Information", + "status": "draft", + "fhirVersion": "4.0.0", + "kind": "resource", + "abstract": false, + "type": "Patient", + "baseDefinition": "http://fhir.kids-first.io/StructureDefinition/kfdrc-patient", + "derivation": "constraint", + "differential": { + "element": [ + { + "id": "Patient", + "path": "Patient" + }, + { + "id": "Patient.name", + "path": "Patient.name", + "max": "0" + }, + { + "id": "Patient.telecom", + "path": "Patient.telecom", + "max": "0" + }, + { + "id": "Patient.birthDate", + "path": "Patient.birthDate", + "max": "0" + }, + { + "id": "Patient.deceased[x]", + "path": "Patient.deceased[x]", + "type" : [ + { + "code" : "boolean" + } + ] + }, + { + "id": "Patient.address", + "path": "Patient.address", + "max": "0" + }, + { + "id": "Patient.photo", + "path": "Patient.photo", + "max": "0" + }, + { + "id": "Patient.contact", + "path": "Patient.contact", + "max": "0" + } + ] + } +} diff --git a/hapi-fhir-jpaserver-base/src/test/resources/r4/StructureDefinition-kfdrc-patient.json b/hapi-fhir-jpaserver-base/src/test/resources/r4/StructureDefinition-kfdrc-patient.json new file mode 100644 index 00000000000..ac82b8fe74d --- /dev/null +++ b/hapi-fhir-jpaserver-base/src/test/resources/r4/StructureDefinition-kfdrc-patient.json @@ -0,0 +1,100 @@ +{ + "resourceType": "StructureDefinition", + "id": "kfdrc-patient", + "url": "http://fhir.kids-first.io/StructureDefinition/kfdrc-patient", + "version": "0.1.0", + "name": "kfdrc-patient", + "title": "Kids First DRC Patient", + "status": "draft", + "fhirVersion": "4.0.0", + "kind": "resource", + "abstract": false, + "type": "Patient", + "baseDefinition": "http://hl7.org/fhir/StructureDefinition/Patient", + "derivation": "constraint", + "differential": { + "element": [ + { + "id": "Patient", + "path": "Patient" + }, + { + "id": "Patient.extension", + "path": "Patient.extension", + "slicing": { + "discriminator": [ + { + "type": "value", + "path": "url" + } + ], + "ordered": false, + "rules": "open" + } + }, + { + "id": "Patient.extension:us-core-ethnicity", + "path": "Patient.extension", + "sliceName": "us-core-ethnicity", + "sliceIsConstraining": false, + "short": "US Core Ethnicity Extension", + "definition": "Concepts classifying the person into a named category of humans sharing common history, traits, geographical origin or nationality. The ethnicity codes used to represent these concepts are based upon the [CDC ethnicity and Ethnicity Code Set Version 1.0](http://www.cdc.gov/phin/resources/vocabulary/index.html) which includes over 900 concepts for representing race and ethnicity of which 43 reference ethnicity. The ethnicity concepts are grouped by and pre-mapped to the 2 OMB ethnicity categories: - Hispanic or Latino - Not Hispanic or Latino.", + "min": 0, + "max": "1", + "type": [ + { + "code": "Extension", + "profile": [ + "http://hl7.org/fhir/us/core/StructureDefinition/us-core-ethnicity" + ] + } + ], + "mustSupport": true, + "isModifier": false + }, + { + "id": "Patient.extension:us-core-race", + "path": "Patient.extension", + "sliceName": "us-core-race", + "short": "US Core Race Extension", + "definition": "Concepts classifying the person into a named category of humans sharing common history, traits, geographical origin or nationality. The race codes used to represent these concepts are based upon the [CDC Race and Ethnicity Code Set Version 1.0](http://www.cdc.gov/phin/resources/vocabulary/index.html) which includes over 900 concepts for representing race and ethnicity of which 921 reference race. The race concepts are grouped by and pre-mapped to the 5 OMB race categories:\n\n - American Indian or Alaska Native\n - Asian\n - Black or African American\n - Native Hawaiian or Other Pacific Islander\n - White.", + "min": 0, + "max": "1", + "type": [ + { + "code": "Extension", + "profile": [ + "http://hl7.org/fhir/us/core/StructureDefinition/us-core-race" + ] + } + ], + "mustSupport": true, + "isModifier": false + }, + { + "id": "Patient.extension:species", + "path": "Patient.extension", + "sliceName": "species", + "short": "Species", + "definition": "Species of the KF DRC Patient.", + "min": 0, + "max": "1", + "type": [ + { + "code": "Extension", + "profile": [ + "http://fhir.kids-first.io/StructureDefinition/species" + ] + } + ], + "mustSupport": true, + "isModifier": false, + "binding": { + "strength": "required", + "description": "Species of the Participant.", + "valueSet": "http://fhir.kids-first.io/ValueSet/species" + } + } + ] + } +} diff --git a/hapi-fhir-validation/src/main/java/org/hl7/fhir/common/hapi/validation/support/SnapshotGeneratingValidationSupport.java b/hapi-fhir-validation/src/main/java/org/hl7/fhir/common/hapi/validation/support/SnapshotGeneratingValidationSupport.java index 094a2402bad..d2ba590bbd4 100644 --- a/hapi-fhir-validation/src/main/java/org/hl7/fhir/common/hapi/validation/support/SnapshotGeneratingValidationSupport.java +++ b/hapi-fhir-validation/src/main/java/org/hl7/fhir/common/hapi/validation/support/SnapshotGeneratingValidationSupport.java @@ -12,6 +12,7 @@ import org.hl7.fhir.common.hapi.validation.validator.VersionSpecificWorkerContex import org.hl7.fhir.common.hapi.validation.validator.VersionTypeConverterDstu3; import org.hl7.fhir.common.hapi.validation.validator.VersionTypeConverterR4; import org.hl7.fhir.instance.model.api.IBaseResource; +import org.hl7.fhir.r5.conformance.ProfileUtilities; import org.hl7.fhir.r5.context.IWorkerContext; import org.hl7.fhir.utilities.validation.ValidationMessage; import org.slf4j.Logger; @@ -90,10 +91,17 @@ public class SnapshotGeneratingValidationSupport implements IValidationSupport { org.hl7.fhir.r5.model.StructureDefinition baseCanonical = (org.hl7.fhir.r5.model.StructureDefinition) converter.toCanonical(base); + if (baseCanonical.getSnapshot().getElement().isEmpty()) { + // If the base definition also doesn't have a snapshot, generate that first + theValidationSupportContext.getRootValidationSupport().generateSnapshot(theValidationSupportContext, base, null, null, null); + baseCanonical = (org.hl7.fhir.r5.model.StructureDefinition) converter.toCanonical(base); + } + ArrayList messages = new ArrayList<>(); org.hl7.fhir.r5.conformance.ProfileUtilities.ProfileKnowledgeProvider profileKnowledgeProvider = new ProfileKnowledgeWorkerR5(myCtx); IWorkerContext context = new VersionSpecificWorkerContextWrapper(theValidationSupportContext, converter); - new org.hl7.fhir.r5.conformance.ProfileUtilities(context, messages, profileKnowledgeProvider).generateSnapshot(baseCanonical, inputCanonical, theUrl, theWebUrl, theProfileName); + ProfileUtilities profileUtilities = new ProfileUtilities(context, messages, profileKnowledgeProvider); + profileUtilities.generateSnapshot(baseCanonical, inputCanonical, theUrl, theWebUrl, theProfileName); switch (theInput.getStructureFhirVersionEnum()) { case DSTU3: