2 * ============LICENSE_START=======================================================
3 * Copyright (C) 2021 Bell Canada. All rights reserved.
4 * ================================================================================
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 * SPDX-License-Identifier: Apache-2.0
17 * ============LICENSE_END=========================================================
20 package org.onap.cps.spi.model;
22 import com.google.common.collect.ImmutableMap;
23 import com.google.common.collect.ImmutableSet;
24 import java.util.Collection;
25 import java.util.Collections;
26 import java.util.List;
29 import java.util.stream.Collectors;
30 import lombok.extern.slf4j.Slf4j;
31 import org.onap.cps.utils.YangUtils;
32 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
33 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerNode;
34 import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode;
35 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
36 import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
37 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
38 import org.opendaylight.yangtools.yang.data.api.schema.ValueNode;
41 public class DataNodeBuilder {
43 private NormalizedNode<?, ?> normalizedNodeTree;
45 private Collection<DataNode> childDataNodes = Collections.emptySet();
49 * To use {@link NormalizedNode} for creating {@link DataNode}.
51 * @param normalizedNodeTree used for creating the Data Node
52 * @return this {@link DataNodeBuilder} object
54 public DataNodeBuilder withNormalizedNodeTree(final NormalizedNode<?, ?> normalizedNodeTree) {
55 this.normalizedNodeTree = normalizedNodeTree;
60 * To use xpath for creating {@link DataNode}.
62 * @param xpath for the data node
63 * @return DataNodeBuilder
65 public DataNodeBuilder withXpath(final String xpath) {
71 * To specify child nodes needs to be used while creating {@link DataNode}.
73 * @param childDataNodes to be added to the dataNode
74 * @return DataNodeBuilder
76 public DataNodeBuilder withChildDataNodes(final Collection<DataNode> childDataNodes) {
77 // Added as this is being set from test cases .
78 // Open for suggestions
79 this.childDataNodes = childDataNodes;
84 * To create the {@link DataNode}.
86 * @return {@link DataNode}
88 public DataNode build() {
89 if (normalizedNodeTree != null) {
90 return buildFromNormalizedNodeTree();
92 return buildFromAttributes();
96 private DataNode buildFromAttributes() {
97 final DataNode dataNode = new DataNode();
98 dataNode.setXpath(xpath);
99 dataNode.setChildDataNodes(childDataNodes);
103 private DataNode buildFromNormalizedNodeTree() {
104 final DataNode formalRootDataNode = new DataNodeBuilder().withXpath("").build();
105 addDataNodeFromNormalizedNode(formalRootDataNode, normalizedNodeTree);
106 return formalRootDataNode.getChildDataNodes().iterator().next();
109 private static void addDataNodeFromNormalizedNode(final DataNode currentDataNode,
110 final NormalizedNode<?, ?> normalizedNode) {
112 if (normalizedNode instanceof DataContainerNode) {
113 addYangContainer(currentDataNode, (DataContainerNode<?>) normalizedNode);
114 } else if (normalizedNode instanceof MapNode) {
115 addDataNodeForEachListElement(currentDataNode, (MapNode) normalizedNode);
116 } else if (normalizedNode instanceof ValueNode) {
117 final ValueNode<?, ?> valuesNode = (ValueNode<?, ?>) normalizedNode;
118 addYangLeaf(currentDataNode, valuesNode.getNodeType().getLocalName(), valuesNode.getValue());
119 } else if (normalizedNode instanceof LeafSetNode) {
120 addYangLeafList(currentDataNode, (LeafSetNode<?>) normalizedNode);
122 log.warn("Unsupported NormalizedNode type detected: {}", normalizedNode.getClass());
126 private static void addYangContainer(final DataNode currentDataNode, final DataContainerNode<?> dataContainerNode) {
127 final DataNode dataContainerDataNode = createAndAddChildDataNode(currentDataNode,
128 YangUtils.buildXpath(dataContainerNode.getIdentifier()));
129 final Collection<DataContainerChild<?, ?>> normalizedChildNodes = dataContainerNode.getValue();
130 for (final NormalizedNode<?, ?> normalizedNode : normalizedChildNodes) {
131 addDataNodeFromNormalizedNode(dataContainerDataNode, normalizedNode);
135 private static void addYangLeaf(final DataNode currentDataNode, final String leafName, final Object leafValue) {
136 final Map<String, Object> leaves = new ImmutableMap.Builder<String, Object>()
137 .putAll(currentDataNode.getLeaves())
138 .put(leafName, leafValue)
140 currentDataNode.setLeaves(leaves);
143 private static void addYangLeafList(final DataNode currentDataNode, final LeafSetNode<?> leafSetNode) {
144 final String leafListName = leafSetNode.getNodeType().getLocalName();
145 final List<?> leafListValues = ((Collection<? extends NormalizedNode<?, ?>>) leafSetNode.getValue())
147 .map(normalizedNode -> ((ValueNode<?, ?>) normalizedNode).getValue())
148 .collect(Collectors.toUnmodifiableList());
149 addYangLeaf(currentDataNode, leafListName, leafListValues);
152 private static void addDataNodeForEachListElement(final DataNode currentDataNode, final MapNode mapNode) {
153 final Collection<MapEntryNode> mapEntryNodes = mapNode.getValue();
154 for (final MapEntryNode mapEntryNode : mapEntryNodes) {
155 addDataNodeFromNormalizedNode(currentDataNode, mapEntryNode);
159 private static DataNode createAndAddChildDataNode(final DataNode parentDataNode, final String childXpath) {
161 final DataNode newChildDataNode = new DataNodeBuilder()
162 .withXpath(parentDataNode.getXpath() + childXpath)
164 final Set<DataNode> allChildDataNodes = new ImmutableSet.Builder<DataNode>()
165 .addAll(parentDataNode.getChildDataNodes())
166 .add(newChildDataNode)
168 parentDataNode.setChildDataNodes(allChildDataNodes);
169 return newChildDataNode;