summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorlukegleeson <luke.gleeson@est.tech>2023-01-09 16:14:36 +0000
committerlukegleeson <luke.gleeson@est.tech>2023-01-11 09:58:22 +0000
commitec769e3d938d2a5b626ddd2be11a44ac4471c74a (patch)
treeeb50027355bebe22902fa12300edd17d8f3b603a
parent86cda427e084b45c0f76d67f0eeebe74ee419ff2 (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.java16
-rw-r--r--cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsDataPersistenceServiceSpec.groovy19
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: [])