diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/DraftCaseJsonMerger.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/DraftCaseJsonMerger.java index c494c5797a..17f7fb4b7e 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/DraftCaseJsonMerger.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/DraftCaseJsonMerger.java @@ -3,12 +3,20 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Component; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; + @Component public class DraftCaseJsonMerger { + private static final Set REPLACE_FIELDS = Set.of("address"); + + private final ObjectMapper objectMapper; public DraftCaseJsonMerger(@Qualifier("draftCaseDataObjectMapper") ObjectMapper objectMapper) { @@ -25,6 +33,9 @@ public DraftCaseJsonMerger(@Qualifier("draftCaseDataObjectMapper") ObjectMapper */ public String mergeJson(String baseJson, String patchJson) throws JsonProcessingException { JsonNode base = objectMapper.readValue(baseJson, JsonNode.class); + JsonNode patch = objectMapper.readValue(patchJson, JsonNode.class); + + applyReplaceRulesRecursively(base, patch); JsonNode merged = objectMapper.readerForUpdating(base) .readValue(patchJson); @@ -32,4 +43,35 @@ public String mergeJson(String baseJson, String patchJson) throws JsonProcessing return objectMapper.writeValueAsString(merged); } + /** + * Clears fields in the base JSON where the patch contains an address object. + * Fully replaces the old fields rather than merging individual fields. + */ + private void applyReplaceRulesRecursively(JsonNode base, JsonNode patch) { + if (!patch.isObject() || !base.isObject()) { + return; + } + + Iterator> fields = patch.properties().iterator(); + while (fields.hasNext()) { + Map.Entry field = fields.next(); + String fieldName = field.getKey(); + JsonNode patchChild = field.getValue(); + + if (base.has(fieldName)) { + JsonNode baseChild = base.get(fieldName); + + if (REPLACE_FIELDS.contains(fieldName.toLowerCase()) + && patchChild.isObject() + && base instanceof ObjectNode) { + + ((ObjectNode) base).set(fieldName, objectMapper.createObjectNode()); + + } else { + applyReplaceRulesRecursively(baseChild, patchChild); + } + } + } + } + } diff --git a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/DraftCaseJsonMergerTest.java b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/DraftCaseJsonMergerTest.java index be649c4cec..9305999c83 100644 --- a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/DraftCaseJsonMergerTest.java +++ b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/DraftCaseJsonMergerTest.java @@ -14,10 +14,13 @@ import uk.gov.hmcts.reform.pcs.ccd.type.DynamicStringListElement; import uk.gov.hmcts.reform.pcs.config.JacksonConfiguration; +import com.fasterxml.jackson.databind.JsonNode; + import java.util.List; import static org.assertj.core.api.Assertions.assertThat; + class DraftCaseJsonMergerTest { private ObjectMapper objectMapper; @@ -114,4 +117,82 @@ private DynamicStringListElement createListElement(ClaimantType value) { return DynamicStringListElement.builder().code(value.name()).label(value.getLabel()).build(); } + @Test + void shouldClearAddressFieldsWhenPatchContainsAddress() throws Exception { + //Given + String baseJson = """ + { + "party": { + "address": { + "AddressLine1": "Old Line 1", + "AddressLine2": "Old Line 2", + "AddressLine3": "Old Line 3", + "PostTown": "Old Town", + "County": "Old County", + "PostCode": "OLD123", + "Country": "Old Country" + } + } + } + """; + + String patchJson = """ + { + "party": { + "address": { + "AddressLine1": "New Line 1" + } + } + } + """; + + // When + String mergedJson = underTest.mergeJson(baseJson, patchJson); + JsonNode merged = objectMapper.readTree(mergedJson); + JsonNode address = merged.at("/party/address"); + + // Then: new field present + assertThat(address.get("AddressLine1").asText()).isEqualTo("New Line 1"); + + // All old fields removed + assertThat(address.has("AddressLine2")).isFalse(); + assertThat(address.has("AddressLine3")).isFalse(); + assertThat(address.has("PostTown")).isFalse(); + assertThat(address.has("County")).isFalse(); + assertThat(address.has("PostCode")).isFalse(); + assertThat(address.has("Country")).isFalse(); + } + + @Test + void shouldNotClearAddressIfPatchDoesNotContainAddress() throws Exception { + //Given + String baseJson = """ + { + "party": { + "address": { + "AddressLine1": "Line 1", + "PostCode": "ABC123" + } + } + } + """; + + String patchJson = """ + { + "party": { + "name": "John" + } + } + """; + + // When + String mergedJson = underTest.mergeJson(baseJson, patchJson); + JsonNode merged = objectMapper.readTree(mergedJson); + JsonNode address = merged.at("/party/address"); + + // Then: address untouched + assertThat(address.get("AddressLine1").asText()).isEqualTo("Line 1"); + assertThat(address.get("PostCode").asText()).isEqualTo("ABC123"); + } + }