Skip to content

Commit

Permalink
fix fhir patch replace in a list
Browse files Browse the repository at this point in the history
  • Loading branch information
mrdnctrk committed Jan 23, 2025
1 parent 3793d81 commit 81b88f8
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -456,6 +456,32 @@ public void testAddToHighCardinalityFieldSetsValueIfEmpty() {
assertEquals("third-system", patient.getIdentifier().get(0).getSystem());
assertEquals("third-value", patient.getIdentifier().get(0).getValue());
}


@Test
public void testReplaceAnElementInHighCardinalityField() {
FhirPatch svc = new FhirPatch(ourCtx);
Patient patient = new Patient();
patient.addIdentifier().setSystem("first-system").setValue("first-value");
patient.addIdentifier().setSystem("second-system").setValue("second-value");

//Given: We create a patch to replace the second identifier
Identifier theValue = new Identifier().setSystem("third-system").setValue("third-value");
Parameters patch = new Parameters();
patch.addParameter(createPatchReplaceOperation("Patient.identifier[1]", theValue));

//When: We apply the patch
svc.apply(patient, patch);
ourLog.debug("Outcome:\n{}", ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(patient));

//Then: it replaces the new identifier correctly.
assertThat(patient.getIdentifier()).hasSize(2);
assertThat(patient.getIdentifier().get(0).getSystem()).isEqualTo("first-system");
assertThat(patient.getIdentifier().get(0).getValue()).isEqualTo("first-value");
assertThat(patient.getIdentifier().get(1).getSystem()).isEqualTo("third-system");
assertThat(patient.getIdentifier().get(1).getValue()).isEqualTo("third-value");
}

@Test
public void testReplaceToHighCardinalityFieldRemovesAllAndSetsValue() {
FhirPatch svc = new FhirPatch(ourCtx);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
import java.util.Set;

import static org.apache.commons.lang3.StringUtils.defaultString;
import static org.apache.commons.lang3.StringUtils.isAllLowerCase;

public class FhirPatch {

Expand Down Expand Up @@ -231,14 +232,68 @@ private void handleReplaceOperation(IBaseResource theResource, IBase theParamete
String containingPath = path.substring(0, lastDot);
String elementName = path.substring(lastDot + 1);

boolean isList = false;
if (path.endsWith(")")) {
// This is probably a filter, so we're probably dealing with a list
int filterArgsIndex = path.lastIndexOf('('); // Let's hope there aren't nested parentheses
int lastDotIndex = path.lastIndexOf(
'.', filterArgsIndex); // There might be a dot inside the parentheses, so look to the left of that
int secondLastDotIndex = path.lastIndexOf('.', lastDotIndex - 1);
containingPath = path.substring(0, secondLastDotIndex);
elementName = path.substring(secondLastDotIndex + 1, lastDotIndex);
isList = true;
} else if (path.endsWith("]")) {
// This is almost definitely a list
int openBracketIndex = path.lastIndexOf('[');
int lastDotIndex = path.lastIndexOf('.', openBracketIndex);
containingPath = path.substring(0, lastDotIndex);
elementName = path.substring(lastDotIndex + 1, openBracketIndex);
isList = true;
} else {
containingPath = path.substring(0, lastDot);
elementName = path.substring(lastDot + 1);
// containingPath = path;
// elementName = null;
}

List<IBase> containingElements = myContext.newFhirPath().evaluate(theResource, containingPath, IBase.class);
for (IBase nextElement : containingElements) {

ChildDefinition childDefinition = findChildDefinition(nextElement, elementName);
if (isList) {
replaceInList(theParameters, theResource, nextElement, elementName, path);
}
else {
ChildDefinition childDefinition = findChildDefinition(nextElement, elementName);

IBase newValue = getNewValue(theParameters, nextElement, childDefinition);
IBase newValue = getNewValue(theParameters, nextElement, childDefinition);

childDefinition.getChildDef().getMutator().setValue(nextElement, newValue);
}
}
}

private void replaceInList(
IBase theParameters,
IBaseResource theResource,
IBase theContainingElement,
String theListElementName,
String theElementToReplacePath) {

ChildDefinition childDefinition = findChildDefinition(theContainingElement, theListElementName);
List<IBase> existingValues =
new ArrayList<>(childDefinition.getChildDef().getAccessor().getValues(theContainingElement));
IBase newValue = getNewValue(theParameters, theContainingElement, childDefinition);
List<IBase> elementsToReplace =
myContext.newFhirPath().evaluate(theResource, theElementToReplacePath, IBase.class);

childDefinition.getChildDef().getMutator().setValue(nextElement, newValue);
childDefinition.getChildDef().getMutator().setValue(theContainingElement, null);
for (IBase existingValue : existingValues) {
if (elementsToReplace.contains(existingValue)) {
childDefinition.getChildDef().getMutator().addValue(theContainingElement, newValue);
}
else {
childDefinition.getChildDef().getMutator().addValue(theContainingElement, existingValue);
}
}
}

Expand Down

0 comments on commit 81b88f8

Please sign in to comment.