Merge pull request #2668 from hapifhir/2667_terserutil_merge_empty_fields
Fixed primitive field merging
This commit is contained in:
commit
cc734613a8
|
@ -28,9 +28,12 @@ import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
|||
import org.apache.commons.lang3.Validate;
|
||||
import org.apache.commons.lang3.tuple.Triple;
|
||||
import org.hl7.fhir.instance.model.api.IBase;
|
||||
import org.hl7.fhir.instance.model.api.IBaseEnumeration;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
|
@ -283,9 +286,10 @@ public final class TerserUtil {
|
|||
*/
|
||||
public static void replaceFieldsByPredicate(FhirContext theFhirContext, IBaseResource theFrom, IBaseResource theTo, Predicate<Triple<BaseRuntimeChildDefinition, IBase, IBase>> thePredicate) {
|
||||
RuntimeResourceDefinition definition = theFhirContext.getResourceDefinition(theFrom);
|
||||
FhirTerser terser = theFhirContext.newTerser();
|
||||
for (BaseRuntimeChildDefinition childDefinition : definition.getChildrenAndExtension()) {
|
||||
if (thePredicate.test(Triple.of(childDefinition, theFrom, theTo))) {
|
||||
replaceField(theFrom, theTo, childDefinition);
|
||||
replaceField(terser, theFrom, theTo, childDefinition);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -313,7 +317,7 @@ public final class TerserUtil {
|
|||
public static void replaceField(FhirContext theFhirContext, String theFieldName, IBaseResource theFrom, IBaseResource theTo) {
|
||||
RuntimeResourceDefinition definition = theFhirContext.getResourceDefinition(theFrom);
|
||||
Validate.notNull(definition);
|
||||
replaceField(theFrom, theTo, theFhirContext.getResourceDefinition(theFrom).getChildByName(theFieldName));
|
||||
replaceField(theFhirContext.newTerser(), theFrom, theTo, theFhirContext.getResourceDefinition(theFrom).getChildByName(theFieldName));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -325,7 +329,7 @@ public final class TerserUtil {
|
|||
*/
|
||||
public static void clearField(FhirContext theFhirContext, String theFieldName, IBaseResource theResource) {
|
||||
BaseRuntimeChildDefinition childDefinition = getBaseRuntimeChildDefinition(theFhirContext, theFieldName, theResource);
|
||||
childDefinition.getAccessor().getValues(theResource).clear();
|
||||
clear(childDefinition.getAccessor().getValues(theResource));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -339,7 +343,7 @@ public final class TerserUtil {
|
|||
BaseRuntimeElementDefinition definition = theFhirContext.getElementDefinition(theBase.getClass());
|
||||
BaseRuntimeChildDefinition childDefinition = definition.getChildByName(theFieldName);
|
||||
Validate.notNull(childDefinition);
|
||||
childDefinition.getAccessor().getValues(theBase).clear();
|
||||
clear(childDefinition.getAccessor().getValues(theBase));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -441,11 +445,12 @@ public final class TerserUtil {
|
|||
return values.get(0);
|
||||
}
|
||||
|
||||
private static void replaceField(IBaseResource theFrom, IBaseResource theTo, BaseRuntimeChildDefinition childDefinition) {
|
||||
childDefinition.getAccessor().getFirstValueOrNull(theFrom).ifPresent(v -> {
|
||||
childDefinition.getMutator().setValue(theTo, v);
|
||||
}
|
||||
);
|
||||
private static void replaceField(FhirTerser theTerser, IBaseResource theFrom, IBaseResource theTo, BaseRuntimeChildDefinition childDefinition) {
|
||||
List<IBase> fromValues = childDefinition.getAccessor().getValues(theFrom);
|
||||
List<IBase> toValues = childDefinition.getAccessor().getValues(theTo);
|
||||
clear(toValues);
|
||||
|
||||
mergeFields(theTerser, theTo, childDefinition, fromValues, toValues);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -532,13 +537,24 @@ public final class TerserUtil {
|
|||
}
|
||||
|
||||
IBase newFieldValue = childDefinition.getChildByName(childDefinition.getElementName()).newInstance();
|
||||
theTerser.cloneInto(theFromFieldValue, newFieldValue, true);
|
||||
if (theFromFieldValue instanceof IPrimitiveType) {
|
||||
try {
|
||||
Method copyMethod = getMethod(theFromFieldValue, "copy");
|
||||
if (copyMethod != null) {
|
||||
newFieldValue = (IBase) copyMethod.invoke(theFromFieldValue, new Object[]{});
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
((IPrimitiveType) newFieldValue).setValueAsString(((IPrimitiveType) theFromFieldValue).getValueAsString());
|
||||
}
|
||||
} else {
|
||||
theTerser.cloneInto(theFromFieldValue, newFieldValue, true);
|
||||
}
|
||||
|
||||
try {
|
||||
theToFieldValues.add(newFieldValue);
|
||||
} catch (UnsupportedOperationException e) {
|
||||
childDefinition.getMutator().setValue(theTo, newFieldValue);
|
||||
break;
|
||||
theToFieldValues = childDefinition.getAccessor().getValues(theTo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -615,4 +631,16 @@ public final class TerserUtil {
|
|||
return (T) def.newInstance(theConstructorParam);
|
||||
}
|
||||
|
||||
private static void clear(List<IBase> values) {
|
||||
if (values == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
values.clear();
|
||||
} catch (Throwable t) {
|
||||
ourLog.debug("Unable to clear values " + String.valueOf(values), t);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -103,6 +103,38 @@ class TerserUtilTest {
|
|||
assertEquals(p1.getName().get(0).getNameAsSingleString(), p2.getName().get(0).getNameAsSingleString());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCloneIdentifiers() {
|
||||
Patient p1 = new Patient();
|
||||
p1.addIdentifier(new Identifier().setSystem("uri:mi").setValue("123456"));
|
||||
p1.addIdentifier(new Identifier().setSystem("uri:mdi").setValue("287351247K"));
|
||||
p1.addIdentifier(new Identifier().setSystem("uri:cdns").setValue("654841918"));
|
||||
p1.addIdentifier(new Identifier().setSystem("uri:ssn").setValue("855191882"));
|
||||
p1.addName().setFamily("Sat").addGiven("Joe");
|
||||
|
||||
Patient p2 = new Patient();
|
||||
TerserUtil.mergeField(ourFhirContext, ourFhirContext.newTerser(), "identifier", p1, p2);
|
||||
|
||||
assertEquals(4, p2.getIdentifier().size());
|
||||
assertTrue(p2.getName().isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testReplaceIdentifiers() {
|
||||
Patient p1 = new Patient();
|
||||
p1.addIdentifier(new Identifier().setSystem("uri:mi").setValue("123456"));
|
||||
p1.addIdentifier(new Identifier().setSystem("uri:mdi").setValue("287351247K"));
|
||||
p1.addIdentifier(new Identifier().setSystem("uri:cdns").setValue("654841918"));
|
||||
p1.addIdentifier(new Identifier().setSystem("uri:ssn").setValue("855191882"));
|
||||
p1.addName().setFamily("Sat").addGiven("Joe");
|
||||
|
||||
Patient p2 = new Patient();
|
||||
TerserUtil.replaceField(ourFhirContext, "identifier", p1, p2);
|
||||
|
||||
assertEquals(4, p2.getIdentifier().size());
|
||||
assertTrue(p2.getName().isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCloneWithNonPrimitves() {
|
||||
Patient p1 = new Patient();
|
||||
|
@ -314,6 +346,7 @@ class TerserUtilTest {
|
|||
// expect p2 to have "Doe" and MALE after replace
|
||||
assertEquals(1, p2.getName().size());
|
||||
assertEquals("Doe", p2.getName().get(0).getFamily());
|
||||
|
||||
assertEquals(Enumerations.AdministrativeGender.MALE, p2.getGender());
|
||||
assertEquals(dob, p2.getBirthDate());
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue