/*
* ============LICENSE_START=======================================================
* Copyright (C) 2021 Bell Canada. All rights reserved.
+ * Modifications Copyright (C) 2021 Pantheon.tech
+ * Modifications Copyright (C) 2022-2023 Nordix Foundation.
+ * Modifications Copyright (C) 2022-2023 TechMahindra Ltd.
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
+import java.io.Serializable;
import java.util.Collection;
import java.util.Collections;
-import java.util.LinkedList;
import java.util.List;
import java.util.Map;
-import java.util.Optional;
import java.util.Set;
+import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
+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;
import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
@Slf4j
public class DataNodeBuilder {
- private NormalizedNode normalizedNodeTree;
+ private ContainerNode containerNode;
private String xpath;
+ private String moduleNamePrefix;
+ private String parentNodeXpath = "";
+ private Map<String, Serializable> leaves = Collections.emptyMap();
private Collection<DataNode> childDataNodes = Collections.emptySet();
+ private String dataspaceName;
+ private String anchorName;
-
- /** To use {@link NormalizedNode} for creating {@link DataNode}.
+ /**
+ * To use parent node xpath for creating {@link DataNode}.
*
- * @param normalizedNodeTree used for creating the Data Node
+ * @param parentNodeXpath xpath of a parent node
+ * @return this {@link DataNodeBuilder} object
+ */
+ public DataNodeBuilder withParentNodeXpath(final String parentNodeXpath) {
+ this.parentNodeXpath = parentNodeXpath;
+ return this;
+ }
+
+ /**
+ * To use {@link Collection} of Normalized Nodes for creating {@link DataNode}.
*
+ * @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;
}
/**
* To use xpath for creating {@link DataNode}.
+ *
* @param xpath for the data node
* @return DataNodeBuilder
*/
return this;
}
+ /**
+ * To use dataspace name for creating {@link DataNode}.
+ *
+ * @param dataspaceName dataspace name for the data node
+ * @return DataNodeBuilder
+ */
+ public DataNodeBuilder withDataspace(final String dataspaceName) {
+ this.dataspaceName = dataspaceName;
+ return this;
+ }
+
+ /**
+ * To use anchor name for creating {@link DataNode}.
+ *
+ * @param anchorName anchor name for the data node
+ * @return DataNodeBuilder
+ */
+ public DataNodeBuilder withAnchor(final String anchorName) {
+ this.anchorName = anchorName;
+ return this;
+ }
+
+ /**
+ * To use module name for prefix for creating {@link DataNode}.
+ *
+ * @param moduleNamePrefix module name as prefix
+ * @return DataNodeBuilder
+ */
+ public DataNodeBuilder withModuleNamePrefix(final String moduleNamePrefix) {
+ this.moduleNamePrefix = moduleNamePrefix;
+ return this;
+ }
+
+ /**
+ * To use attributes for creating {@link DataNode}.
+ *
+ * @param leaves for the data node
+ * @return DataNodeBuilder
+ */
+ public DataNodeBuilder withLeaves(final Map<String, Serializable> leaves) {
+ this.leaves = leaves;
+ return this;
+ }
+
/**
* To specify child nodes needs to be used while creating {@link DataNode}.
+ *
* @param childDataNodes to be added to the dataNode
* @return DataNodeBuilder
*/
* @return {@link DataNode}
*/
public DataNode build() {
- if (normalizedNodeTree != null) {
- return buildFromNormalizedNodeTree();
- } else {
- return buildFromAttributes();
+ if (containerNode != null) {
+ return buildFromContainerNode();
}
+ return buildFromAttributes();
+ }
+
+ /**
+ * To build a {@link Collection} of {@link DataNode} objects.
+ *
+ * @return {@link DataNode} {@link Collection}
+ */
+ public Collection<DataNode> buildCollection() {
+ if (containerNode != null) {
+ return buildCollectionFromContainerNode();
+ }
+ return Collections.emptySet();
}
private DataNode buildFromAttributes() {
- final DataNode dataNode = new DataNode();
+ final var dataNode = new DataNode();
dataNode.setXpath(xpath);
+ dataNode.setModuleNamePrefix(moduleNamePrefix);
+ dataNode.setLeaves(leaves);
dataNode.setChildDataNodes(childDataNodes);
+ dataNode.setDataspace(dataspaceName);
+ dataNode.setAnchorName(anchorName);
return dataNode;
}
- private DataNode buildFromNormalizedNodeTree() {
- xpath = YangUtils.buildXpath(normalizedNodeTree.getIdentifier());
- final DataNode dataNode = new DataNodeBuilder().withXpath(xpath).build();
- addDataNodeFromNormalizedNode(dataNode, normalizedNodeTree);
- return dataNode;
+ private DataNode buildFromContainerNode() {
+ final Collection<DataNode> dataNodeCollection = buildCollectionFromContainerNode();
+ if (dataNodeCollection.isEmpty()) {
+ throw new DataValidationException("Unsupported Normalized Node", "No valid node found");
+ }
+ return dataNodeCollection.iterator().next();
+ }
+
+ private Collection<DataNode> buildCollectionFromContainerNode() {
+ final var parentDataNode = new DataNodeBuilder().withXpath(parentNodeXpath).build();
+ if (containerNode.body() != null) {
+ for (final NormalizedNode normalizedNode: containerNode.body()) {
+ addDataNodeFromNormalizedNode(parentDataNode, normalizedNode);
+ }
+ }
+ return parentDataNode.getChildDataNodes();
}
- private void addDataNodeFromNormalizedNode(final DataNode currentDataNode,
+ private static void addDataNodeFromNormalizedNode(final DataNode currentDataNode,
final NormalizedNode normalizedNode) {
- if (normalizedNode instanceof DataContainerNode) {
+
+ if (normalizedNode instanceof ChoiceNode) {
+ addChoiceNode(currentDataNode, (ChoiceNode) normalizedNode);
+ } else if (normalizedNode instanceof DataContainerNode) {
addYangContainer(currentDataNode, (DataContainerNode) normalizedNode);
} else if (normalizedNode instanceof MapNode) {
addDataNodeForEachListElement(currentDataNode, (MapNode) normalizedNode);
} else if (normalizedNode instanceof ValueNode) {
- final ValueNode valuesNode = (ValueNode) normalizedNode;
- addYangLeaf(currentDataNode, valuesNode.getNodeType().getLocalName(), valuesNode.getValue());
+ final ValueNode<NormalizedNode> valuesNode = (ValueNode) normalizedNode;
+ addYangLeaf(currentDataNode, valuesNode.getIdentifier().getNodeType().getLocalName(),
+ (Serializable) valuesNode.body());
} else if (normalizedNode instanceof LeafSetNode) {
- addYangLeafList(currentDataNode, (LeafSetNode) normalizedNode);
+ addYangLeafList(currentDataNode, (LeafSetNode<?>) normalizedNode);
} else {
- log.warn("Cannot normalize {}", normalizedNode.getClass());
+ log.warn("Unsupported NormalizedNode type detected: {}", normalizedNode.getClass());
}
}
- private void addYangContainer(final DataNode currentDataNode, final DataContainerNode dataContainerNode) {
- final Collection<NormalizedNode> normalizedChildNodes = dataContainerNode.getValue();
+ private static void addYangContainer(final DataNode currentDataNode, final DataContainerNode dataContainerNode) {
+ final DataNode dataContainerDataNode =
+ (dataContainerNode.getIdentifier() instanceof YangInstanceIdentifier.AugmentationIdentifier)
+ ? currentDataNode
+ : createAndAddChildDataNode(currentDataNode, YangUtils.buildXpath(dataContainerNode.getIdentifier()));
+ final Collection<DataContainerChild> normalizedChildNodes = dataContainerNode.body();
for (final NormalizedNode normalizedNode : normalizedChildNodes) {
- addDataNodeFromNormalizedNode(currentDataNode, normalizedNode);
+ addDataNodeFromNormalizedNode(dataContainerDataNode, normalizedNode);
}
}
- private void addYangLeaf(final DataNode currentDataNode, final String leafName, final Object leafValue) {
- final Map leaves = new ImmutableMap.Builder<String, Object>()
+ private static void addYangLeaf(final DataNode currentDataNode, final String leafName,
+ final Serializable leafValue) {
+ final Map<String, Serializable> leaves = new ImmutableMap.Builder<String, Serializable>()
.putAll(currentDataNode.getLeaves())
.put(leafName, leafValue)
.build();
currentDataNode.setLeaves(leaves);
}
- private void addYangLeafList(final DataNode currentDataNode, final LeafSetNode leafSetNode) {
- final ImmutableSet.Builder builder = new ImmutableSet.Builder<String>();
- final String leafListName = leafSetNode.getNodeType().getLocalName();
- final Optional<Set<String>> optionalLeafListNames = currentDataNode.getOptionalLeafListNames();
- if (optionalLeafListNames.isPresent()) {
- builder.addAll(optionalLeafListNames.get());
- }
- builder.add(leafListName);
- final ImmutableSet leafListNames = builder.build();
- currentDataNode.setOptionalLeafListNames(Optional.of(leafListNames));
- final List leafListValues = new LinkedList();
- for (final NormalizedNode normalizedNode : (Collection<NormalizedNode>) leafSetNode.getValue()) {
- leafListValues.add(((ValueNode) normalizedNode).getValue());
- }
- addYangLeaf(currentDataNode, leafListName, leafListValues);
+ private static void addYangLeafList(final DataNode currentDataNode, final LeafSetNode<?> leafSetNode) {
+ final String leafListName = leafSetNode.getIdentifier().getNodeType().getLocalName();
+ final List<?> leafListValues = ((Collection<? extends NormalizedNode>) leafSetNode.body())
+ .stream()
+ .map(normalizedNode -> (normalizedNode).body())
+ .collect(Collectors.toUnmodifiableList());
+ addYangLeaf(currentDataNode, leafListName, (Serializable) leafListValues);
}
- private void addDataNodeForEachListElement(final DataNode currentDataNode, final MapNode mapNode) {
- final Collection<MapEntryNode> mapEntryNodes = mapNode.getValue();
+ private static void addDataNodeForEachListElement(final DataNode currentDataNode, final MapNode mapNode) {
+ final Collection<MapEntryNode> mapEntryNodes = mapNode.body();
for (final MapEntryNode mapEntryNode : mapEntryNodes) {
- final String xpathChild = YangUtils.buildXpath(mapEntryNode.getIdentifier());
- final DataNode childDataNode = createAndAddChildDataNode(currentDataNode, xpathChild);
- addDataNodeFromNormalizedNode(childDataNode, mapEntryNode);
+ addDataNodeFromNormalizedNode(currentDataNode, mapEntryNode);
}
}
- private DataNode createAndAddChildDataNode(final DataNode parentDataNode, final String childXpath) {
- final DataNode newChildDataNode = new DataNodeBuilder().withXpath(xpath + childXpath)
+ private static DataNode createAndAddChildDataNode(final DataNode parentDataNode, final String childXpath) {
+
+ final var newChildDataNode = new DataNodeBuilder()
+ .withXpath(parentDataNode.getXpath() + childXpath)
.build();
final Set<DataNode> allChildDataNodes = new ImmutableSet.Builder<DataNode>()
.addAll(parentDataNode.getChildDataNodes())
return newChildDataNode;
}
+ private static void addChoiceNode(final DataNode currentDataNode, final ChoiceNode choiceNode) {
+
+ final Collection<DataContainerChild> normalizedChildNodes = choiceNode.body();
+ for (final NormalizedNode normalizedNode : normalizedChildNodes) {
+ addDataNodeFromNormalizedNode(currentDataNode, normalizedNode);
+ }
+ }
+
}