diff options
author | lukegleeson <luke.gleeson@est.tech> | 2023-01-09 16:14:36 +0000 |
---|---|---|
committer | lukegleeson <luke.gleeson@est.tech> | 2023-01-11 09:58:22 +0000 |
commit | ec769e3d938d2a5b626ddd2be11a44ac4471c74a (patch) | |
tree | eb50027355bebe22902fa12300edd17d8f3b603a | |
parent | 86cda427e084b45c0f76d67f0eeebe74ee419ff2 (diff) |
CPS PATCH operation does not merge existing data
Altered code to add attributes and not overwrite attributes + tests
Issue-ID: CPS-1442
Signed-off-by: lukegleeson <luke.gleeson@est.tech>
Change-Id: I23c5f6a65b98ea1b05af62a38a874c228cc82067
-rw-r--r-- | cps-ri/src/main/java/org/onap/cps/spi/impl/CpsDataPersistenceServiceImpl.java | 16 | ||||
-rw-r--r-- | cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsDataPersistenceServiceSpec.groovy | 19 |
2 files changed, 33 insertions, 2 deletions
diff --git a/cps-ri/src/main/java/org/onap/cps/spi/impl/CpsDataPersistenceServiceImpl.java b/cps-ri/src/main/java/org/onap/cps/spi/impl/CpsDataPersistenceServiceImpl.java index 3bd2994305..06068e391b 100644 --- a/cps-ri/src/main/java/org/onap/cps/spi/impl/CpsDataPersistenceServiceImpl.java +++ b/cps-ri/src/main/java/org/onap/cps/spi/impl/CpsDataPersistenceServiceImpl.java @@ -447,9 +447,11 @@ public class CpsDataPersistenceServiceImpl implements CpsDataPersistenceService @Override public void updateDataLeaves(final String dataspaceName, final String anchorName, final String xpath, - final Map<String, Serializable> leaves) { + final Map<String, Serializable> updateLeaves) { final FragmentEntity fragmentEntity = getFragmentWithoutDescendantsByXpath(dataspaceName, anchorName, xpath); - fragmentEntity.setAttributes(jsonObjectMapper.asJsonString(leaves)); + final String currentLeavesAsString = fragmentEntity.getAttributes(); + final String mergedLeaves = mergeLeaves(updateLeaves, currentLeavesAsString); + fragmentEntity.setAttributes(mergedLeaves); fragmentRepository.save(fragmentEntity); } @@ -694,4 +696,14 @@ public class CpsDataPersistenceServiceImpl implements CpsDataPersistenceService private static boolean isRootXpath(final String xpath) { return "/".equals(xpath) || "".equals(xpath); } + + private String mergeLeaves(final Map<String, Serializable> updateLeaves, final String currentLeavesAsString) { + final Map<String, Serializable> currentLeavesAsMap = currentLeavesAsString.isEmpty() + ? new HashMap<>() : jsonObjectMapper.convertJsonString(currentLeavesAsString, Map.class); + currentLeavesAsMap.putAll(updateLeaves); + if (currentLeavesAsMap.isEmpty()) { + return ""; + } + return jsonObjectMapper.asJsonString(currentLeavesAsMap); + } } diff --git a/cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsDataPersistenceServiceSpec.groovy b/cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsDataPersistenceServiceSpec.groovy index 255e8e52f4..8234d32a8e 100644 --- a/cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsDataPersistenceServiceSpec.groovy +++ b/cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsDataPersistenceServiceSpec.groovy @@ -165,6 +165,25 @@ class CpsDataPersistenceServiceSpec extends Specification { 1 * mockSessionManager.lockAnchor('mySessionId', 'myDataspaceName', 'myAnchorName', 123L) } + def 'update data node leaves: #scenario'(){ + given: 'A node exists for the given xpath' + mockFragmentRepository.getByDataspaceAndAnchorAndXpath(_, _, '/some/xpath') >> new FragmentEntity(xpath: '/some/xpath', attributes: existingAttributes) + when: 'the node leaves are updated' + objectUnderTest.updateDataLeaves('some-dataspace', 'some-anchor', '/some/xpath', newAttributes as Map<String, Serializable>) + then: 'the fragment entity saved has the original and new attributes' + 1 * mockFragmentRepository.save({fragmentEntity -> { + assert fragmentEntity.getXpath() == '/some/xpath' + assert fragmentEntity.getAttributes() == mergedAttributes + }}) + where: 'the following attributes combinations are used' + scenario | existingAttributes | newAttributes | mergedAttributes + 'add new leaf' | '{"existing":"value"}' | ["new":"value"] | '{"existing":"value","new":"value"}' + 'update existing leaf' | '{"existing":"value"}' | ["existing":"value2"] | '{"existing":"value2"}' + 'update nothing with nothing' | '' | [] | '' + 'update with nothing' | '{"existing":"value"}' | [] | '{"existing":"value"}' + 'update with same value' | '{"existing":"value"}' | ["existing":"value"] | '{"existing":"value"}' + } + def 'update data node and descendants: #scenario'(){ given: 'mocked responses' mockFragmentRepository.getByDataspaceAndAnchorAndXpath(_, _, '/test/xpath') >> new FragmentEntity(xpath: '/test/xpath', childFragments: []) |