Fixed bug with choice children (#2714)

This commit is contained in:
Nick Goupinets 2021-06-08 08:24:13 -04:00 committed by GitHub
parent dc627dc019
commit 3863e82a59
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 113 additions and 3 deletions

View File

@ -24,6 +24,7 @@ import ca.uhn.fhir.context.BaseRuntimeChildDefinition;
import ca.uhn.fhir.context.BaseRuntimeElementCompositeDefinition;
import ca.uhn.fhir.context.BaseRuntimeElementDefinition;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.RuntimeChildChoiceDefinition;
import ca.uhn.fhir.context.RuntimeResourceDefinition;
import org.apache.commons.lang3.Validate;
import org.apache.commons.lang3.tuple.Triple;
@ -178,7 +179,7 @@ public final class TerserUtil {
continue;
}
IBase newFieldValue = childDefinition.getChildByName(theField).newInstance();
IBase newFieldValue = newElement(childDefinition, theFromFieldValue, null);
terser.cloneInto(theFromFieldValue, newFieldValue, true);
try {
@ -524,13 +525,32 @@ public final class TerserUtil {
return childDefinition;
}
/**
* Creates a new element taking into consideration elements with choice that are not directly retrievable by element
* name
*
* @param theChildDefinition Child to create a new instance for
* @param theFromFieldValue The base parent field
* @param theConstructorParam Optional constructor param
* @return Returns the new element with the given value if configured
*/
private static IBase newElement(BaseRuntimeChildDefinition theChildDefinition, IBase theFromFieldValue, Object theConstructorParam) {
BaseRuntimeElementDefinition runtimeElementDefinition;
if (theChildDefinition instanceof RuntimeChildChoiceDefinition) {
runtimeElementDefinition = theChildDefinition.getChildElementDefinitionByDatatype(theFromFieldValue.getClass());
} else {
runtimeElementDefinition = theChildDefinition.getChildByName(theChildDefinition.getElementName());
}
return (theConstructorParam == null) ? runtimeElementDefinition.newInstance() : runtimeElementDefinition.newInstance(theConstructorParam);
}
private static void mergeFields(FhirTerser theTerser, IBaseResource theTo, BaseRuntimeChildDefinition childDefinition, List<IBase> theFromFieldValues, List<IBase> theToFieldValues) {
for (IBase theFromFieldValue : theFromFieldValues) {
if (contains(theFromFieldValue, theToFieldValues)) {
continue;
}
IBase newFieldValue = childDefinition.getChildByName(childDefinition.getElementName()).newInstance();
IBase newFieldValue = newElement(childDefinition, theFromFieldValue, null);
if (theFromFieldValue instanceof IPrimitiveType) {
try {
Method copyMethod = getMethod(theFromFieldValue, "copy");

View File

@ -2,7 +2,6 @@ package ca.uhn.fhir.util;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.RuntimeResourceDefinition;
import org.checkerframework.checker.units.qual.A;
import org.hl7.fhir.r4.model.Address;
import org.hl7.fhir.r4.model.DateTimeType;
import org.hl7.fhir.r4.model.DateType;
@ -23,6 +22,73 @@ import static org.junit.jupiter.api.Assertions.*;
class TerserUtilTest {
private FhirContext ourFhirContext = FhirContext.forR4();
private static final String SAMPLE_PERSON = "{\n" +
" \"resourceType\": \"Patient\",\n" +
" \"extension\": [\n" +
" {\n" +
" \"url\": \"http://hl7.org/fhir/us/core/StructureDefinition/us-core-race\",\n" +
" \"valueCoding\": {\n" +
" \"system\": \"MyInternalRace\",\n" +
" \"code\": \"X\",\n" +
" \"display\": \"Eks\"\n" +
" }\n" +
" },\n" +
" {\n" +
" \"url\": \"http://hl7.org/fhir/us/core/StructureDefinition/us-core-ethnicity'\",\n" +
" \"valueCoding\": {\n" +
" \"system\": \"MyInternalEthnicity\",\n" +
" \"display\": \"NNN\"\n" +
" }\n" +
" }\n" +
" ],\n" +
" \"identifier\": [\n" +
" {\n" +
" \"system\": \"http://example.org/member_id\",\n" +
" \"value\": \"123123\"\n" +
" },\n" +
" {\n" +
" \"system\": \"http://example.org/medicaid_id\",\n" +
" \"value\": \"12312323123Z\"\n" +
" },\n" +
" {\n" +
" \"system\": \"http://example.org/CDNS_id\",\n" +
" \"value\": \"123123123E\"\n" +
" },\n" +
" {\n" +
" \"system\": \"http://example.org/SSN\"\n" +
" }\n" +
" ],\n" +
" \"active\": true,\n" +
" \"name\": [\n" +
" {\n" +
" \"family\": \"TestFamily\",\n" +
" \"given\": [\n" +
" \"Given\"\n" +
" ]\n" +
" }\n" +
" ],\n" +
" \"telecom\": [\n" +
" {\n" +
" \"system\": \"email\",\n" +
" \"value\": \"email@email.io\"\n" +
" },\n" +
" {\n" +
" \"system\": \"phone\",\n" +
" \"value\": \"123123231\"\n" +
" },\n" +
" {\n" +
" \"system\": \"phone\",\n" +
" \"value\": \"1231232312\"\n" +
" },\n" +
" {\n" +
" \"system\": \"phone\",\n" +
" \"value\": \"1231232314\"\n" +
" }\n" +
" ],\n" +
" \"gender\": \"male\",\n" +
" \"birthDate\": \"1900-01-01\",\n" +
" \"deceasedBoolean\": true\n" +
" }";
@Test
void testCloneEidIntoResource() {
@ -40,6 +106,30 @@ class TerserUtilTest {
assertEquals(p1.getIdentifier().get(0).getValue(), p2.getIdentifier().get(0).getValue());
}
@Test
void testReplaceBooleanField() {
Patient p1 = ourFhirContext.newJsonParser().parseResource(Patient.class, SAMPLE_PERSON);
Patient p2 = new Patient();
TerserUtil.replaceFields(ourFhirContext, p1, p2, TerserUtil.EXCLUDE_IDS_AND_META);
assertTrue(p2.hasDeceased());
assertTrue("true".equals(p2.getDeceased().primitiveValue()));
assertEquals(2, p2.getExtension().size());
}
@Test
void testMergeBooleanField() {
Patient p1 = ourFhirContext.newJsonParser().parseResource(Patient.class, SAMPLE_PERSON);
Patient p2 = new Patient();
TerserUtil.mergeAllFields(ourFhirContext, p1, p2);
assertTrue(p2.hasDeceased());
assertTrue("true".equals(p2.getDeceased().primitiveValue()));
assertEquals(2, p2.getExtension().size());
}
@Test
void testCloneEidIntoResourceViaHelper() {
TerserUtilHelper p1Helper = TerserUtilHelper.newHelper(ourFhirContext, "Patient");