Fixes to diff operation (#1866)
This commit is contained in:
parent
3807640347
commit
535bf88efe
|
@ -369,14 +369,7 @@ public class FhirPatch {
|
||||||
// Find newly inserted items
|
// Find newly inserted items
|
||||||
while (targetIndex < targetValues.size()) {
|
while (targetIndex < targetValues.size()) {
|
||||||
String path = theTargetPath + "." + elementName;
|
String path = theTargetPath + "." + elementName;
|
||||||
|
addInsertItems(theDiff, targetValues, targetIndex, path, theChildDef);
|
||||||
|
|
||||||
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));
|
|
||||||
|
|
||||||
targetIndex++;
|
targetIndex++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -393,6 +386,36 @@ public class FhirPatch {
|
||||||
theSourceEncodePath.popPath();
|
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) {
|
private void addValueToDiff(IBase theOperationPart, IBase theOldValue, IBase theNewValue) {
|
||||||
|
|
||||||
if (myIncludePreviousValueInDiff) {
|
if (myIncludePreviousValueInDiff) {
|
||||||
|
|
|
@ -12,6 +12,7 @@ import org.hl7.fhir.r4.model.Patient;
|
||||||
import org.hl7.fhir.r4.model.StringType;
|
import org.hl7.fhir.r4.model.StringType;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
@ -170,9 +171,13 @@ public class FhirPatchApplyR4Test {
|
||||||
return ((IPrimitiveType) part.getValue()).getValueAsString();
|
return ((IPrimitiveType) part.getValue()).getValueAsString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
public static <T extends IBase> T extractPartValue(Parameters theDiff, int theIndex, String theParameterName, String thePartName, Class<T> theExpectedType) {
|
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 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)) {
|
if (IBaseResource.class.isAssignableFrom(theExpectedType)) {
|
||||||
return (T) part.getResource();
|
return (T) part.getResource();
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
package ca.uhn.fhir.jpa.patch;
|
package ca.uhn.fhir.jpa.patch;
|
||||||
|
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
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.BooleanType;
|
||||||
import org.hl7.fhir.r4.model.DateTimeType;
|
import org.hl7.fhir.r4.model.DateTimeType;
|
||||||
import org.hl7.fhir.r4.model.Extension;
|
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.Identifier;
|
||||||
import org.hl7.fhir.r4.model.Parameters;
|
import org.hl7.fhir.r4.model.Parameters;
|
||||||
import org.hl7.fhir.r4.model.Patient;
|
import org.hl7.fhir.r4.model.Patient;
|
||||||
|
@ -319,6 +321,30 @@ public class FhirPatchDiffR4Test {
|
||||||
validateDiffProducesSameResults(oldValue, newValue, svc, diff);
|
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
|
@Test
|
||||||
public void testIgnoreElementComposite_Resource() {
|
public void testIgnoreElementComposite_Resource() {
|
||||||
Patient oldValue = new Patient();
|
Patient oldValue = new Patient();
|
||||||
|
|
Loading…
Reference in New Issue