Ensure that parent structuredefinitions are snapshotted before (#2005)

* Ensure that parent structuredefinitions are snapshotted before
snapshotting child

* Add changelog
This commit is contained in:
James Agnew 2020-07-28 11:46:58 -04:00 committed by GitHub
parent 20d1ab2fac
commit 6a8e09addf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 196 additions and 1 deletions

View File

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

View File

@ -13,6 +13,7 @@ import org.junit.jupiter.api.Test;
import java.io.IOException; import java.io.IOException;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
@SuppressWarnings({"unchecked", "deprecation"}) @SuppressWarnings({"unchecked", "deprecation"})
public class FhirResourceDaoR4StructureDefinitionTest extends BaseJpaR4Test { 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);
}
} }

View File

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

View File

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

View File

@ -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.VersionTypeConverterDstu3;
import org.hl7.fhir.common.hapi.validation.validator.VersionTypeConverterR4; import org.hl7.fhir.common.hapi.validation.validator.VersionTypeConverterR4;
import org.hl7.fhir.instance.model.api.IBaseResource; 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.r5.context.IWorkerContext;
import org.hl7.fhir.utilities.validation.ValidationMessage; import org.hl7.fhir.utilities.validation.ValidationMessage;
import org.slf4j.Logger; 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); 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<ValidationMessage> messages = new ArrayList<>(); ArrayList<ValidationMessage> messages = new ArrayList<>();
org.hl7.fhir.r5.conformance.ProfileUtilities.ProfileKnowledgeProvider profileKnowledgeProvider = new ProfileKnowledgeWorkerR5(myCtx); org.hl7.fhir.r5.conformance.ProfileUtilities.ProfileKnowledgeProvider profileKnowledgeProvider = new ProfileKnowledgeWorkerR5(myCtx);
IWorkerContext context = new VersionSpecificWorkerContextWrapper(theValidationSupportContext, converter); 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()) { switch (theInput.getStructureFhirVersionEnum()) {
case DSTU3: case DSTU3: