aboutsummaryrefslogtreecommitdiffstats
path: root/cps-service/src/main/java/org/onap
diff options
context:
space:
mode:
authorarpitsingh <as00745003@techmahindra.com>2022-10-14 02:42:43 +0530
committerarpitsingh <as00745003@techmahindra.com>2022-12-15 18:19:48 +0530
commit0c8068aadbb34f30ca58efb9a860b2d88016627a (patch)
tree856cf2390886d5c12a3a952b3a7c1f051fb6c04f /cps-service/src/main/java/org/onap
parent3ded83809e65eec2ac673f157b03212472a29833 (diff)
CPS-341 Support for multiple data tree instances under 1 anchor
- Updated the parseJsonData method so it can parse JSON with multiple data trees, now it returns a ContainerNode - ContainerNode holds a collection of NormalizedNodes - Updated DataNodeBuilder and FragmentRepository as well to support collection of NormalizedNodes - Added new methods in CpsDataPersistenceService to store multiple Data Nodes - Added new test cases - Updated existing test cases and fixed code coverage - Addressed comments from previous patch Issue-ID: CPS-341 Change-Id: Ie893e91c0fbfb139a1a406e962721b0f52412ced Signed-off-by: arpitsingh <as00745003@techmahindra.com>
Diffstat (limited to 'cps-service/src/main/java/org/onap')
-rwxr-xr-xcps-service/src/main/java/org/onap/cps/api/impl/CpsDataServiceImpl.java48
-rw-r--r--cps-service/src/main/java/org/onap/cps/spi/CpsDataPersistenceService.java23
-rw-r--r--cps-service/src/main/java/org/onap/cps/spi/model/DataNodeBuilder.java39
-rw-r--r--cps-service/src/main/java/org/onap/cps/utils/YangUtils.java26
4 files changed, 90 insertions, 46 deletions
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 b08d8c1eba..732b494994 100755
--- 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
@@ -3,6 +3,7 @@
* Copyright (C) 2021-2022 Nordix Foundation
* Modifications Copyright (C) 2020-2022 Bell Canada.
* Modifications Copyright (C) 2021 Pantheon.tech
+ * Modifications Copyright (C) 2022 TechMahindra Ltd.
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -27,6 +28,7 @@ import static org.onap.cps.notification.Operation.DELETE;
import static org.onap.cps.notification.Operation.UPDATE;
import java.time.OffsetDateTime;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
@@ -45,7 +47,7 @@ import org.onap.cps.spi.model.DataNode;
import org.onap.cps.spi.model.DataNodeBuilder;
import org.onap.cps.spi.utils.CpsValidator;
import org.onap.cps.utils.YangUtils;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
import org.springframework.stereotype.Service;
@@ -67,8 +69,9 @@ public class CpsDataServiceImpl implements CpsDataService {
public void saveData(final String dataspaceName, final String anchorName, final String jsonData,
final OffsetDateTime observedTimestamp) {
cpsValidator.validateNameCharacters(dataspaceName, anchorName);
- final DataNode dataNode = buildDataNode(dataspaceName, anchorName, ROOT_NODE_XPATH, jsonData);
- cpsDataPersistenceService.storeDataNode(dataspaceName, anchorName, dataNode);
+ final Collection<DataNode> dataNodes =
+ buildDataNodes(dataspaceName, anchorName, ROOT_NODE_XPATH, jsonData);
+ cpsDataPersistenceService.storeDataNodes(dataspaceName, anchorName, dataNodes);
processDataUpdatedEventAsync(dataspaceName, anchorName, ROOT_NODE_XPATH, CREATE, observedTimestamp);
}
@@ -76,8 +79,9 @@ public class CpsDataServiceImpl implements CpsDataService {
public void saveData(final String dataspaceName, final String anchorName, final String parentNodeXpath,
final String jsonData, final OffsetDateTime observedTimestamp) {
cpsValidator.validateNameCharacters(dataspaceName, anchorName);
- final DataNode dataNode = buildDataNode(dataspaceName, anchorName, parentNodeXpath, jsonData);
- cpsDataPersistenceService.addChildDataNode(dataspaceName, anchorName, parentNodeXpath, dataNode);
+ final Collection<DataNode> dataNodes =
+ buildDataNodes(dataspaceName, anchorName, parentNodeXpath, jsonData);
+ cpsDataPersistenceService.addChildDataNodes(dataspaceName, anchorName, parentNodeXpath, dataNodes);
processDataUpdatedEventAsync(dataspaceName, anchorName, parentNodeXpath, CREATE, observedTimestamp);
}
@@ -161,8 +165,10 @@ public class CpsDataServiceImpl implements CpsDataService {
final String parentNodeXpath, final String jsonData,
final OffsetDateTime observedTimestamp) {
cpsValidator.validateNameCharacters(dataspaceName, anchorName);
- final DataNode dataNode = buildDataNode(dataspaceName, anchorName, parentNodeXpath, jsonData);
- cpsDataPersistenceService.updateDataNodeAndDescendants(dataspaceName, anchorName, dataNode);
+ final Collection<DataNode> dataNodes =
+ buildDataNodes(dataspaceName, anchorName, parentNodeXpath, jsonData);
+ final ArrayList<DataNode> nodes = new ArrayList<>(dataNodes);
+ cpsDataPersistenceService.updateDataNodesAndDescendants(dataspaceName, anchorName, nodes);
processDataUpdatedEventAsync(dataspaceName, anchorName, parentNodeXpath, UPDATE, observedTimestamp);
}
@@ -226,15 +232,16 @@ public class CpsDataServiceImpl implements CpsDataService {
final SchemaContext schemaContext = getSchemaContext(dataspaceName, anchor.getSchemaSetName());
if (ROOT_NODE_XPATH.equals(parentNodeXpath)) {
- final NormalizedNode normalizedNode = YangUtils.parseJsonData(jsonData, schemaContext);
- return new DataNodeBuilder().withNormalizedNodeTree(normalizedNode).build();
+ final ContainerNode containerNode = YangUtils.parseJsonData(jsonData, schemaContext);
+ return new DataNodeBuilder().withContainerNode(containerNode).build();
}
- final NormalizedNode normalizedNode = YangUtils.parseJsonData(jsonData, schemaContext, parentNodeXpath);
+ final ContainerNode containerNode = YangUtils
+ .parseJsonData(jsonData, schemaContext, parentNodeXpath);
return new DataNodeBuilder()
- .withParentNodeXpath(parentNodeXpath)
- .withNormalizedNodeTree(normalizedNode)
- .build();
+ .withParentNodeXpath(parentNodeXpath)
+ .withContainerNode(containerNode)
+ .build();
}
private List<DataNode> buildDataNodes(final String dataspaceName, final String anchorName,
@@ -251,11 +258,20 @@ public class CpsDataServiceImpl implements CpsDataService {
final Anchor anchor = cpsAdminService.getAnchor(dataspaceName, anchorName);
final SchemaContext schemaContext = getSchemaContext(dataspaceName, anchor.getSchemaSetName());
-
- final NormalizedNode normalizedNode = YangUtils.parseJsonData(jsonData, schemaContext, parentNodeXpath);
+ if (ROOT_NODE_XPATH.equals(parentNodeXpath)) {
+ final ContainerNode containerNode = YangUtils.parseJsonData(jsonData, schemaContext);
+ final Collection<DataNode> dataNodes = new DataNodeBuilder()
+ .withContainerNode(containerNode)
+ .buildCollection();
+ if (dataNodes.isEmpty()) {
+ throw new DataValidationException("Invalid data.", "No data nodes provided");
+ }
+ return dataNodes;
+ }
+ final ContainerNode containerNode = YangUtils.parseJsonData(jsonData, schemaContext, parentNodeXpath);
final Collection<DataNode> dataNodes = new DataNodeBuilder()
.withParentNodeXpath(parentNodeXpath)
- .withNormalizedNodeTree(normalizedNode)
+ .withContainerNode(containerNode)
.buildCollection();
if (dataNodes.isEmpty()) {
throw new DataValidationException("Invalid data.", "No data nodes provided");
diff --git a/cps-service/src/main/java/org/onap/cps/spi/CpsDataPersistenceService.java b/cps-service/src/main/java/org/onap/cps/spi/CpsDataPersistenceService.java
index 28b18b3b5c..b9da4af025 100644
--- a/cps-service/src/main/java/org/onap/cps/spi/CpsDataPersistenceService.java
+++ b/cps-service/src/main/java/org/onap/cps/spi/CpsDataPersistenceService.java
@@ -3,6 +3,7 @@
* Copyright (C) 2020-2022 Nordix Foundation.
* Modifications Copyright (C) 2021 Pantheon.tech
* Modifications Copyright (C) 2022 Bell Canada
+ * Modifications Copyright (C) 2022 TechMahindra Ltd.
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -35,16 +36,27 @@ import org.onap.cps.spi.model.DataNode;
*/
public interface CpsDataPersistenceService {
+
/**
* Store a datanode.
*
* @param dataspaceName dataspace name
* @param anchorName anchor name
* @param dataNode data node
+ * @deprecated Please use {@link #storeDataNodes(String, String, Collection)} as it supports multiple data nodes.
*/
+ @Deprecated
void storeDataNode(String dataspaceName, String anchorName, DataNode dataNode);
/**
+ * Store multiple datanodes at once.
+ * @param dataspaceName dataspace name
+ * @param anchorName anchor name
+ * @param dataNodes data nodes
+ */
+ void storeDataNodes(String dataspaceName, String anchorName, Collection<DataNode> dataNodes);
+
+ /**
* Add a child to a Fragment.
*
* @param dataspaceName dataspace name
@@ -55,6 +67,16 @@ public interface CpsDataPersistenceService {
void addChildDataNode(String dataspaceName, String anchorName, String parentXpath, DataNode dataNode);
/**
+ * Add multiple children to a Fragment.
+ *
+ * @param dataspaceName dataspace name
+ * @param anchorName anchor name
+ * @param parentXpath parent xpath
+ * @param dataNodes collection of dataNodes
+ */
+ void addChildDataNodes(String dataspaceName, String anchorName, String parentXpath, Collection<DataNode> dataNodes);
+
+ /**
* Adds list child elements to a Fragment.
*
* @param dataspaceName dataspace name
@@ -62,7 +84,6 @@ public interface CpsDataPersistenceService {
* @param parentNodeXpath parent node xpath
* @param listElementsCollection collection of data nodes representing list elements
*/
-
void addListElements(String dataspaceName, String anchorName, String parentNodeXpath,
Collection<DataNode> listElementsCollection);
diff --git a/cps-service/src/main/java/org/onap/cps/spi/model/DataNodeBuilder.java b/cps-service/src/main/java/org/onap/cps/spi/model/DataNodeBuilder.java
index 1d8bac0dde..b23cdfc8d1 100644
--- a/cps-service/src/main/java/org/onap/cps/spi/model/DataNodeBuilder.java
+++ b/cps-service/src/main/java/org/onap/cps/spi/model/DataNodeBuilder.java
@@ -3,6 +3,7 @@
* Copyright (C) 2021 Bell Canada. All rights reserved.
* Modifications Copyright (C) 2021 Pantheon.tech
* Modifications Copyright (C) 2022 Nordix Foundation.
+ * Modifications Copyright (C) 2022 TechMahindra Ltd.
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -35,6 +36,7 @@ import org.onap.cps.spi.exceptions.DataValidationException;
import org.onap.cps.utils.YangUtils;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
import org.opendaylight.yangtools.yang.data.api.schema.DataContainerNode;
import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode;
@@ -46,7 +48,7 @@ import org.opendaylight.yangtools.yang.data.api.schema.ValueNode;
@Slf4j
public class DataNodeBuilder {
- private NormalizedNode normalizedNodeTree;
+ private ContainerNode containerNode;
private String xpath;
private String moduleNamePrefix;
private String parentNodeXpath = "";
@@ -64,15 +66,14 @@ public class DataNodeBuilder {
return this;
}
-
/**
- * To use {@link NormalizedNode} for creating {@link DataNode}.
+ * To use {@link Collection} of Normalized Nodes for creating {@link DataNode}.
*
- * @param normalizedNodeTree used for creating the Data Node
+ * @param containerNode used for creating the Data Node
* @return this {@link DataNodeBuilder} object
*/
- public DataNodeBuilder withNormalizedNodeTree(final NormalizedNode normalizedNodeTree) {
- this.normalizedNodeTree = normalizedNodeTree;
+ public DataNodeBuilder withContainerNode(final ContainerNode containerNode) {
+ this.containerNode = containerNode;
return this;
}
@@ -128,11 +129,10 @@ public class DataNodeBuilder {
* @return {@link DataNode}
*/
public DataNode build() {
- if (normalizedNodeTree != null) {
- return buildFromNormalizedNodeTree();
- } else {
- return buildFromAttributes();
+ if (containerNode != null) {
+ return buildFromContainerNode();
}
+ return buildFromAttributes();
}
/**
@@ -141,11 +141,10 @@ public class DataNodeBuilder {
* @return {@link DataNode} {@link Collection}
*/
public Collection<DataNode> buildCollection() {
- if (normalizedNodeTree != null) {
- return buildCollectionFromNormalizedNodeTree();
- } else {
- return Set.of(buildFromAttributes());
+ if (containerNode != null) {
+ return buildCollectionFromContainerNode();
}
+ return Collections.emptySet();
}
private DataNode buildFromAttributes() {
@@ -157,8 +156,8 @@ public class DataNodeBuilder {
return dataNode;
}
- private DataNode buildFromNormalizedNodeTree() {
- final Collection<DataNode> dataNodeCollection = buildCollectionFromNormalizedNodeTree();
+ private DataNode buildFromContainerNode() {
+ final Collection<DataNode> dataNodeCollection = buildCollectionFromContainerNode();
if (!dataNodeCollection.iterator().hasNext()) {
throw new DataValidationException(
"Unsupported xpath: ", "Unsupported xpath as it is referring to one element");
@@ -166,9 +165,13 @@ public class DataNodeBuilder {
return dataNodeCollection.iterator().next();
}
- private Collection<DataNode> buildCollectionFromNormalizedNodeTree() {
+ private Collection<DataNode> buildCollectionFromContainerNode() {
final var parentDataNode = new DataNodeBuilder().withXpath(parentNodeXpath).build();
- addDataNodeFromNormalizedNode(parentDataNode, normalizedNodeTree);
+ if (containerNode.body() != null) {
+ for (final NormalizedNode normalizedNode: containerNode.body()) {
+ addDataNodeFromNormalizedNode(parentDataNode, normalizedNode);
+ }
+ }
return parentDataNode.getChildDataNodes();
}
diff --git a/cps-service/src/main/java/org/onap/cps/utils/YangUtils.java b/cps-service/src/main/java/org/onap/cps/utils/YangUtils.java
index 48241ed392..9a61579b12 100644
--- a/cps-service/src/main/java/org/onap/cps/utils/YangUtils.java
+++ b/cps-service/src/main/java/org/onap/cps/utils/YangUtils.java
@@ -3,6 +3,7 @@
* Copyright (C) 2020-2022 Nordix Foundation
* Modifications Copyright (C) 2021 Bell Canada.
* Modifications Copyright (C) 2021 Pantheon.tech
+ * Modifications Copyright (C) 2022 TechMahindra Ltd.
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -39,13 +40,14 @@ import lombok.extern.slf4j.Slf4j;
import org.onap.cps.spi.exceptions.DataValidationException;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
+import org.opendaylight.yangtools.yang.data.api.schema.builder.DataContainerNodeBuilder;
import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
import org.opendaylight.yangtools.yang.data.codec.gson.JSONCodecFactory;
import org.opendaylight.yangtools.yang.data.codec.gson.JSONCodecFactorySupplier;
import org.opendaylight.yangtools.yang.data.codec.gson.JsonParserStream;
+import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNormalizedNodeStreamWriter;
-import org.opendaylight.yangtools.yang.data.impl.schema.NormalizedNodeResult;
import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
@@ -62,38 +64,40 @@ public class YangUtils {
private static final String XPATH_NODE_KEY_ATTRIBUTES_REGEX = "\\[.*?\\]";
/**
- * Parses jsonData into NormalizedNode according to given schema context.
+ * Parses jsonData into Collection of NormalizedNode according to given schema context.
*
* @param jsonData json data as string
* @param schemaContext schema context describing associated data model
- * @return the NormalizedNode object
+ * @return the Collection of NormalizedNode object
*/
- public static NormalizedNode parseJsonData(final String jsonData, final SchemaContext schemaContext) {
+ public static ContainerNode parseJsonData(final String jsonData, final SchemaContext schemaContext) {
return parseJsonData(jsonData, schemaContext, Optional.empty());
}
/**
- * Parses jsonData into NormalizedNode according to given schema context.
+ * Parses jsonData into Collection of NormalizedNode according to given schema context.
*
* @param jsonData json data fragment as string
* @param schemaContext schema context describing associated data model
* @param parentNodeXpath the xpath referencing the parent node current data fragment belong to
* @return the NormalizedNode object
*/
- public static NormalizedNode parseJsonData(final String jsonData, final SchemaContext schemaContext,
+ public static ContainerNode parseJsonData(final String jsonData, final SchemaContext schemaContext,
final String parentNodeXpath) {
final Collection<QName> dataSchemaNodeIdentifiers =
getDataSchemaNodeIdentifiersByXpath(parentNodeXpath, schemaContext);
return parseJsonData(jsonData, schemaContext, Optional.of(dataSchemaNodeIdentifiers));
}
- private static NormalizedNode parseJsonData(final String jsonData, final SchemaContext schemaContext,
+ private static ContainerNode parseJsonData(final String jsonData, final SchemaContext schemaContext,
final Optional<Collection<QName>> dataSchemaNodeIdentifiers) {
final JSONCodecFactory jsonCodecFactory = JSONCodecFactorySupplier.DRAFT_LHOTKA_NETMOD_YANG_JSON_02
.getShared((EffectiveModelContext) schemaContext);
- final NormalizedNodeResult normalizedNodeResult = new NormalizedNodeResult();
+ final DataContainerNodeBuilder<YangInstanceIdentifier.NodeIdentifier, ContainerNode> dataContainerNodeBuilder =
+ Builders.containerBuilder()
+ .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(schemaContext.getQName()));
final NormalizedNodeStreamWriter normalizedNodeStreamWriter = ImmutableNormalizedNodeStreamWriter
- .from(normalizedNodeResult);
+ .from(dataContainerNodeBuilder);
final JsonReader jsonReader = new JsonReader(new StringReader(jsonData));
final JsonParserStream jsonParserStream;
@@ -119,7 +123,7 @@ public class YangUtils {
"Failed to parse json data. Unsupported xpath or json data:" + jsonData, illegalStateException
.getMessage(), illegalStateException);
}
- return normalizedNodeResult.getResult();
+ return dataContainerNodeBuilder.build();
}
/**