summaryrefslogtreecommitdiffstats
path: root/cps-service
diff options
context:
space:
mode:
authorRudrangi Anupriya <ra00745022@techmahindra.com>2024-07-11 21:56:24 +0530
committerRudrangi Anupriya <ra00745022@techmahindra.com>2024-07-16 11:00:11 +0000
commit760dd950e6f6fcb6f49c6f9d92a33f538adffd24 (patch)
treecccab533a2837a60e527ff1e75d6dbcd01197d6a /cps-service
parentac58e919008c4449b389d3681a6f8aa216cb5f8f (diff)
XML content support on replace a node with descendants
Issue-ID: CPS-2282 Change-Id: Ibb7ffb65ccbb03703266712c6d5c2eade0e7ab4b Signed-off-by: Rudrangi Anupriya <ra00745022@techmahindra.com>
Diffstat (limited to 'cps-service')
-rw-r--r--cps-service/src/main/java/org/onap/cps/api/CpsDataService.java20
-rw-r--r--cps-service/src/main/java/org/onap/cps/api/impl/CpsDataServiceImpl.java19
-rw-r--r--cps-service/src/test/groovy/org/onap/cps/api/impl/CpsDataServiceImplSpec.groovy45
3 files changed, 60 insertions, 24 deletions
diff --git a/cps-service/src/main/java/org/onap/cps/api/CpsDataService.java b/cps-service/src/main/java/org/onap/cps/api/CpsDataService.java
index f396b49e6b..cfa5f2de20 100644
--- a/cps-service/src/main/java/org/onap/cps/api/CpsDataService.java
+++ b/cps-service/src/main/java/org/onap/cps/api/CpsDataService.java
@@ -55,7 +55,7 @@ public interface CpsDataService {
* @param anchorName anchor name
* @param nodeData node data
* @param observedTimestamp observedTimestamp
- * @param contentType node data content type
+ * @param contentType JSON/XML content type
*/
void saveData(String dataspaceName, String anchorName, String nodeData, OffsetDateTime observedTimestamp,
ContentType contentType);
@@ -80,7 +80,7 @@ public interface CpsDataService {
* @param parentNodeXpath parent node xpath
* @param nodeData node data
* @param observedTimestamp observedTimestamp
- * @param contentType node data content type
+ * @param contentType JSON/XML content type
*
*/
void saveData(String dataspaceName, String anchorName, String parentNodeXpath, String nodeData,
@@ -134,7 +134,7 @@ public interface CpsDataService {
* @param parentNodeXpath xpath to parent node
* @param nodeData node data
* @param observedTimestamp observedTimestamp
- * @param contentType node data content type
+ * @param contentType JSON/XML content type
*/
void updateNodeLeaves(String dataspaceName, String anchorName, String parentNodeXpath, String nodeData,
OffsetDateTime observedTimestamp, ContentType contentType);
@@ -145,22 +145,24 @@ public interface CpsDataService {
* @param dataspaceName dataspace name
* @param anchorName anchor name
* @param parentNodeXpath xpath to parent node
- * @param jsonData json data
+ * @param nodeData node data
* @param observedTimestamp observedTimestamp
+ * @param contentType JSON/XML content type
*/
- void updateDataNodeAndDescendants(String dataspaceName, String anchorName, String parentNodeXpath, String jsonData,
- OffsetDateTime observedTimestamp);
+ void updateDataNodeAndDescendants(String dataspaceName, String anchorName, String parentNodeXpath, String nodeData,
+ OffsetDateTime observedTimestamp, ContentType contentType);
/**
* Replaces multiple existing data nodes' content including descendants in a batch operation.
*
* @param dataspaceName dataspace name
* @param anchorName anchor name
- * @param nodesJsonData map of xpath and node JSON data
+ * @param nodeDataPerXPath map of xpath and node JSON/XML data
* @param observedTimestamp observedTimestamp
+ * @param contentType JSON/XML content type
*/
- void updateDataNodesAndDescendants(String dataspaceName, String anchorName, Map<String, String> nodesJsonData,
- OffsetDateTime observedTimestamp);
+ void updateDataNodesAndDescendants(String dataspaceName, String anchorName, Map<String, String> nodeDataPerXPath,
+ OffsetDateTime observedTimestamp, ContentType contentType);
/**
* Replaces list content by removing all existing elements and inserting the given new elements as json
diff --git a/cps-service/src/main/java/org/onap/cps/api/impl/CpsDataServiceImpl.java b/cps-service/src/main/java/org/onap/cps/api/impl/CpsDataServiceImpl.java
index 5a48428772..c65bc5e0e9 100644
--- a/cps-service/src/main/java/org/onap/cps/api/impl/CpsDataServiceImpl.java
+++ b/cps-service/src/main/java/org/onap/cps/api/impl/CpsDataServiceImpl.java
@@ -251,12 +251,12 @@ public class CpsDataServiceImpl implements CpsDataService {
@Timed(value = "cps.data.service.datanode.descendants.update",
description = "Time taken to update a data node and descendants")
public void updateDataNodeAndDescendants(final String dataspaceName, final String anchorName,
- final String parentNodeXpath, final String jsonData,
- final OffsetDateTime observedTimestamp) {
+ final String parentNodeXpath, final String nodeData,
+ final OffsetDateTime observedTimestamp, final ContentType contentType) {
cpsValidator.validateNameCharacters(dataspaceName, anchorName);
final Anchor anchor = cpsAnchorService.getAnchor(dataspaceName, anchorName);
final Collection<DataNode> dataNodes =
- buildDataNodesWithParentNodeXpath(anchor, parentNodeXpath, jsonData, ContentType.JSON);
+ buildDataNodesWithParentNodeXpath(anchor, parentNodeXpath, nodeData, contentType);
cpsDataPersistenceService.updateDataNodesAndDescendants(dataspaceName, anchorName, dataNodes);
sendDataUpdatedEvent(anchor, parentNodeXpath, Operation.UPDATE, observedTimestamp);
}
@@ -265,13 +265,13 @@ public class CpsDataServiceImpl implements CpsDataService {
@Timed(value = "cps.data.service.datanode.descendants.batch.update",
description = "Time taken to update a batch of data nodes and descendants")
public void updateDataNodesAndDescendants(final String dataspaceName, final String anchorName,
- final Map<String, String> nodesJsonData,
- final OffsetDateTime observedTimestamp) {
+ final Map<String, String> nodeDataPerXPath,
+ final OffsetDateTime observedTimestamp, final ContentType contentType) {
cpsValidator.validateNameCharacters(dataspaceName, anchorName);
final Anchor anchor = cpsAnchorService.getAnchor(dataspaceName, anchorName);
- final Collection<DataNode> dataNodes = buildDataNodesWithParentNodeXpath(anchor, nodesJsonData);
+ final Collection<DataNode> dataNodes = buildDataNodesWithParentNodeXpath(anchor, nodeDataPerXPath, contentType);
cpsDataPersistenceService.updateDataNodesAndDescendants(dataspaceName, anchorName, dataNodes);
- nodesJsonData.keySet().forEach(nodeXpath ->
+ nodeDataPerXPath.keySet().forEach(nodeXpath ->
sendDataUpdatedEvent(anchor, nodeXpath, Operation.UPDATE, observedTimestamp));
}
@@ -408,11 +408,12 @@ public class CpsDataServiceImpl implements CpsDataService {
}
private Collection<DataNode> buildDataNodesWithParentNodeXpath(final Anchor anchor,
- final Map<String, String> nodesJsonData) {
+ final Map<String, String> nodesJsonData,
+ final ContentType contentType) {
final Collection<DataNode> dataNodes = new ArrayList<>();
for (final Map.Entry<String, String> nodeJsonData : nodesJsonData.entrySet()) {
dataNodes.addAll(buildDataNodesWithParentNodeXpath(anchor, nodeJsonData.getKey(),
- nodeJsonData.getValue(), ContentType.JSON));
+ nodeJsonData.getValue(), contentType));
}
return dataNodes;
}
diff --git a/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsDataServiceImplSpec.groovy b/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsDataServiceImplSpec.groovy
index 4e5807ec84..2e38d797d9 100644
--- a/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsDataServiceImplSpec.groovy
+++ b/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsDataServiceImplSpec.groovy
@@ -362,11 +362,11 @@ class CpsDataServiceImplSpec extends Specification {
1 * mockCpsValidator.validateNameCharacters(dataspaceName, anchorName)
}
- def 'Replace data node using singular data node: #scenario.'() {
+ def 'Replace data node using singular JSON data node: #scenario.'() {
given: 'schema set for given anchor and dataspace references test-tree model'
setupSchemaSetMocks('test-tree.yang')
when: 'replace data method is invoked with json data #jsonData and parent node xpath #parentNodeXpath'
- objectUnderTest.updateDataNodeAndDescendants(dataspaceName, anchorName, parentNodeXpath, jsonData, observedTimestamp)
+ objectUnderTest.updateDataNodeAndDescendants(dataspaceName, anchorName, parentNodeXpath, jsonData, observedTimestamp, ContentType.JSON)
then: 'the persistence service method is invoked with correct parameters'
1 * mockCpsDataPersistenceService.updateDataNodesAndDescendants(dataspaceName, anchorName,
{ dataNode -> dataNode.xpath == expectedNodeXpath})
@@ -379,30 +379,63 @@ class CpsDataServiceImplSpec extends Specification {
'json list' | '/test-tree' | '{"branch": [{"name":"Name1"}, {"name":"Name2"}]}' || ["/test-tree/branch[@name='Name1']", "/test-tree/branch[@name='Name2']"]
}
- def 'Replace data node using multiple data nodes: #scenario.'() {
+ def 'Replace data node using singular XML data node: #scenario.'() {
+ given: 'schema set for given anchor and dataspace references test-tree model'
+ setupSchemaSetMocks('test-tree.yang')
+ when: 'replace data method is invoked with XML data #xmlData and parent node xpath #parentNodeXpath'
+ objectUnderTest.updateDataNodeAndDescendants(dataspaceName, anchorName, parentNodeXpath, xmlData, observedTimestamp, ContentType.XML)
+ then: 'the persistence service method is invoked with correct parameters'
+ 1 * mockCpsDataPersistenceService.updateDataNodesAndDescendants(dataspaceName, anchorName,
+ { dataNode -> dataNode.xpath == expectedNodeXpath })
+ and: 'the CpsValidator is called on the dataspaceName and AnchorName'
+ 1 * mockCpsValidator.validateNameCharacters(dataspaceName, anchorName)
+ where: 'following parameters were used'
+ scenario | parentNodeXpath | xmlData || expectedNodeXpath
+ 'level 2 node' | '/test-tree' | '<branch><name>Name</name></branch>' || ['/test-tree/branch[@name=\'Name\']']
+ 'xml list' | '/test-tree' | '<test-tree xmlns="org:onap:cps:test:test-tree"><branch><name>Name1</name></branch>' + '<branch><name>Name2</name></branch></test-tree>' || ["/test-tree/branch[@name='Name1']", "/test-tree/branch[@name='Name2']"]
+ }
+
+ def 'Replace data node using multiple JSON data nodes: #scenario.'() {
given: 'schema set for given anchor and dataspace references test-tree model'
setupSchemaSetMocks('test-tree.yang')
when: 'replace data method is invoked with a map of xpaths and json data'
- objectUnderTest.updateDataNodesAndDescendants(dataspaceName, anchorName, nodesJsonData, observedTimestamp)
+ objectUnderTest.updateDataNodesAndDescendants(dataspaceName, anchorName, nodeDataPerXPath, observedTimestamp, ContentType.JSON)
then: 'the persistence service method is invoked with correct parameters'
1 * mockCpsDataPersistenceService.updateDataNodesAndDescendants(dataspaceName, anchorName,
{ dataNode -> dataNode.xpath == expectedNodeXpath})
and: 'the CpsValidator is called on the dataspaceName and AnchorName'
1 * mockCpsValidator.validateNameCharacters(dataspaceName, anchorName)
where: 'following parameters were used'
- scenario | nodesJsonData || expectedNodeXpath
+ scenario | nodeDataPerXPath || expectedNodeXpath
'top level node' | ['/' : '{"test-tree": {"branch": []}}', '/test-tree' : '{"branch": [{"name":"Name"}]}'] || ["/test-tree", "/test-tree/branch[@name='Name']"]
'level 2 node' | ['/test-tree' : '{"branch": [{"name":"Name"}]}', '/test-tree/branch[@name=\'Name\']':'{"nest":{"name":"nestName"}}'] || ["/test-tree/branch[@name='Name']", "/test-tree/branch[@name='Name']/nest"]
'json list' | ['/test-tree' : '{"branch": [{"name":"Name1"}, {"name":"Name2"}]}'] || ["/test-tree/branch[@name='Name1']", "/test-tree/branch[@name='Name2']"]
}
+ def 'Replace data node using multiple XML data nodes: #scenario.'() {
+ given: 'schema set for given anchor and dataspace references test-tree model'
+ setupSchemaSetMocks('test-tree.yang')
+ when: 'replace data method is invoked with a map of xpaths and XML data'
+ objectUnderTest.updateDataNodesAndDescendants(dataspaceName, anchorName, nodeXmlDataPerXPath, observedTimestamp, ContentType.XML)
+ then: 'the persistence service method is invoked with correct parameters'
+ 1 * mockCpsDataPersistenceService.updateDataNodesAndDescendants(dataspaceName, anchorName,
+ { dataNode -> dataNode.xpath == expectedNodeXpath })
+ and: 'the CpsValidator is called on the dataspaceName and AnchorName'
+ 1 * mockCpsValidator.validateNameCharacters(dataspaceName, anchorName)
+ where: 'following parameters were used'
+ scenario | nodeXmlDataPerXPath || expectedNodeXpath
+ 'top level node' | ['/test-tree': '<branch><name>Name</name></branch>'] || ["/test-tree/branch[@name='Name']"]
+ 'level 2 node' | ['/test-tree': '<branch><name>Name</name></branch>', '/test-tree/branch[@name=\'Name\']': '<nest><name>nestName</name></nest>'] || ["/test-tree/branch[@name='Name']", "/test-tree/branch[@name='Name']/nest"]
+ 'xml list' | ['/test-tree': '<test-tree xmlns="org:onap:cps:test:test-tree"><branch><name>Name1</name></branch>' + '<branch><name>Name2</name></branch></test-tree>'] || ["/test-tree/branch[@name='Name1']", "/test-tree/branch[@name='Name2']"]
+ }
+
def 'Replace data node with concurrency exception in persistence layer.'() {
given: 'the persistence layer throws an concurrency exception'
def originalException = new ConcurrencyException('message', 'details')
mockCpsDataPersistenceService.updateDataNodesAndDescendants(*_) >> { throw originalException }
setupSchemaSetMocks('test-tree.yang')
when: 'attempt to replace data node'
- objectUnderTest.updateDataNodesAndDescendants(dataspaceName, anchorName, ['/' : '{"test-tree": {}}'] , observedTimestamp)
+ objectUnderTest.updateDataNodesAndDescendants(dataspaceName, anchorName, ['/' : '{"test-tree": {}}'] , observedTimestamp, ContentType.JSON)
then: 'the same exception is thrown up'
def thrownUp = thrown(ConcurrencyException)
assert thrownUp == originalException