Fixes to diff operation (#1866)

This commit is contained in:
James Agnew 2020-05-25 13:16:58 -04:00 committed by GitHub
parent 3807640347
commit 535bf88efe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 63 additions and 9 deletions

View File

@ -369,14 +369,7 @@ public class FhirPatch {
// Find newly inserted items
while (targetIndex < targetValues.size()) {
String path = theTargetPath + "." + elementName;
IBase operation = ParametersUtil.addParameterToParameters(myContext, theDiff, "operation");
ParametersUtil.addPartCode(myContext, operation, "type", "insert");
ParametersUtil.addPartString(myContext, operation, "path", path);
ParametersUtil.addPartInteger(myContext, operation, "index", targetIndex);
ParametersUtil.addPart(myContext, operation, "value", targetValues.get(targetIndex));
addInsertItems(theDiff, targetValues, targetIndex, path, theChildDef);
targetIndex++;
}
@ -393,6 +386,36 @@ public class FhirPatch {
theSourceEncodePath.popPath();
}
private void addInsertItems(IBaseParameters theDiff, List<? extends IBase> theTargetValues, int theTargetIndex, String thePath, BaseRuntimeChildDefinition theChildDefinition) {
IBase operation = ParametersUtil.addParameterToParameters(myContext, theDiff, "operation");
ParametersUtil.addPartCode(myContext, operation, "type", "insert");
ParametersUtil.addPartString(myContext, operation, "path", thePath);
ParametersUtil.addPartInteger(myContext, operation, "index", theTargetIndex);
IBase value = theTargetValues.get(theTargetIndex);
BaseRuntimeElementDefinition<?> valueDef = myContext.getElementDefinition(value.getClass());
/*
* If the value is a Resource or a datatype, we can put it into the part.value and that will cover
* all of its children. If it's an infrastructure element though, such as Patient.contact we can't
* just put it into part.value because it isn't an actual type. So we have to put all of its
* childen in instead.
*/
if (valueDef.isStandardType()) {
ParametersUtil.addPart(myContext, operation, "value", value);
} else {
for (BaseRuntimeChildDefinition nextChild : valueDef.getChildren()) {
List<IBase> childValues = nextChild.getAccessor().getValues(value);
for (int index = 0; index < childValues.size(); index++) {
boolean childRepeatable = theChildDefinition.getMax() != 1;
String elementName = nextChild.getChildNameByDatatype(childValues.get(index).getClass());
String targetPath = thePath + (childRepeatable ? "[" + index + "]" : "") + "." + elementName;
addInsertItems(theDiff, childValues, index, targetPath, nextChild);
}
}
}
}
private void addValueToDiff(IBase theOperationPart, IBase theOldValue, IBase theNewValue) {
if (myIncludePreviousValueInDiff) {

View File

@ -12,6 +12,7 @@ import org.hl7.fhir.r4.model.Patient;
import org.hl7.fhir.r4.model.StringType;
import org.junit.Test;
import javax.annotation.Nullable;
import java.util.stream.Collectors;
import static org.junit.Assert.assertEquals;
@ -170,9 +171,13 @@ public class FhirPatchApplyR4Test {
return ((IPrimitiveType) part.getValue()).getValueAsString();
}
@Nullable
public static <T extends IBase> T extractPartValue(Parameters theDiff, int theIndex, String theParameterName, String thePartName, Class<T> theExpectedType) {
Parameters.ParametersParameterComponent component = theDiff.getParameter().stream().filter(t -> t.getName().equals(theParameterName)).collect(Collectors.toList()).get(theIndex);
Parameters.ParametersParameterComponent part = component.getPart().stream().filter(t -> t.getName().equals(thePartName)).findFirst().orElseThrow(() -> new IllegalArgumentException());
Parameters.ParametersParameterComponent part = component.getPart().stream().filter(t -> t.getName().equals(thePartName)).findFirst().orElse(null);
if (part == null) {
return null;
}
if (IBaseResource.class.isAssignableFrom(theExpectedType)) {
return (T) part.getResource();

View File

@ -1,9 +1,11 @@
package ca.uhn.fhir.jpa.patch;
import ca.uhn.fhir.context.FhirContext;
import org.hl7.fhir.instance.model.api.IBase;
import org.hl7.fhir.r4.model.BooleanType;
import org.hl7.fhir.r4.model.DateTimeType;
import org.hl7.fhir.r4.model.Extension;
import org.hl7.fhir.r4.model.HumanName;
import org.hl7.fhir.r4.model.Identifier;
import org.hl7.fhir.r4.model.Parameters;
import org.hl7.fhir.r4.model.Patient;
@ -319,6 +321,30 @@ public class FhirPatchDiffR4Test {
validateDiffProducesSameResults(oldValue, newValue, svc, diff);
}
@Test
public void testInsertContact() {
Patient oldValue = new Patient();
Patient newValue = new Patient();
newValue.addContact().getName().setFamily("My Family");
FhirPatch svc = new FhirPatch(ourCtx);
Parameters diff = (Parameters) svc.diff(oldValue, newValue);
ourLog.info(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(diff));
assertEquals(2, diff.getParameter().size());
assertEquals("insert", extractPartValuePrimitive(diff, 0, "operation", "type"));
assertEquals("Patient.contact", extractPartValuePrimitive(diff, 0, "operation", "path"));
assertEquals(null, extractPartValue(diff, 0, "operation", "value", IBase.class));
assertEquals("insert", extractPartValuePrimitive(diff, 1, "operation", "type"));
assertEquals("Patient.contact[0].name", extractPartValuePrimitive(diff, 1, "operation", "path"));
assertEquals("My Family", extractPartValue(diff, 1, "operation", "value", HumanName.class).getFamily());
validateDiffProducesSameResults(oldValue, newValue, svc, diff);
}
@Test
public void testIgnoreElementComposite_Resource() {
Patient oldValue = new Patient();