d187f62e0ff197ac08a1a6cae1c1a8a0a3fa6016
[cps.git] / cps-service / src / main / java / org / onap / cps / spi / model / DataNodeBuilder.java
1 /*
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
8  *
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.
15  *
16  *  SPDX-License-Identifier: Apache-2.0
17  *  ============LICENSE_END=========================================================
18  */
19
20 package org.onap.cps.spi.model;
21
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;
27 import java.util.Map;
28 import java.util.Set;
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;
39
40 @Slf4j
41 public class DataNodeBuilder {
42
43     private NormalizedNode<?, ?> normalizedNodeTree;
44     private String xpath;
45     private Collection<DataNode> childDataNodes = Collections.emptySet();
46
47
48     /**
49      * To use {@link NormalizedNode} for creating {@link DataNode}.
50      *
51      * @param normalizedNodeTree used for creating the Data Node
52      * @return this {@link DataNodeBuilder} object
53      */
54     public DataNodeBuilder withNormalizedNodeTree(final NormalizedNode<?, ?> normalizedNodeTree) {
55         this.normalizedNodeTree = normalizedNodeTree;
56         return this;
57     }
58
59     /**
60      * To use xpath for creating {@link DataNode}.
61      *
62      * @param xpath for the data node
63      * @return DataNodeBuilder
64      */
65     public DataNodeBuilder withXpath(final String xpath) {
66         this.xpath = xpath;
67         return this;
68     }
69
70     /**
71      * To specify child nodes needs to be used while creating {@link DataNode}.
72      *
73      * @param childDataNodes to be added to the dataNode
74      * @return DataNodeBuilder
75      */
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;
80         return this;
81     }
82
83     /**
84      * To create the {@link DataNode}.
85      *
86      * @return {@link DataNode}
87      */
88     public DataNode build() {
89         if (normalizedNodeTree != null) {
90             return buildFromNormalizedNodeTree();
91         } else {
92             return buildFromAttributes();
93         }
94     }
95
96     private DataNode buildFromAttributes() {
97         final DataNode dataNode = new DataNode();
98         dataNode.setXpath(xpath);
99         dataNode.setChildDataNodes(childDataNodes);
100         return dataNode;
101     }
102
103     private DataNode buildFromNormalizedNodeTree() {
104         final DataNode formalRootDataNode = new DataNodeBuilder().withXpath("").build();
105         addDataNodeFromNormalizedNode(formalRootDataNode, normalizedNodeTree);
106         return formalRootDataNode.getChildDataNodes().iterator().next();
107     }
108
109     private static void addDataNodeFromNormalizedNode(final DataNode currentDataNode,
110         final NormalizedNode<?, ?> normalizedNode) {
111
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);
121         } else {
122             log.warn("Unsupported NormalizedNode type detected: {}", normalizedNode.getClass());
123         }
124     }
125
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);
132         }
133     }
134
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)
139             .build();
140         currentDataNode.setLeaves(leaves);
141     }
142
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())
146             .stream()
147             .map(normalizedNode -> ((ValueNode<?, ?>) normalizedNode).getValue())
148             .collect(Collectors.toUnmodifiableList());
149         addYangLeaf(currentDataNode, leafListName, leafListValues);
150     }
151
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);
156         }
157     }
158
159     private static DataNode createAndAddChildDataNode(final DataNode parentDataNode, final String childXpath) {
160
161         final DataNode newChildDataNode = new DataNodeBuilder()
162             .withXpath(parentDataNode.getXpath() + childXpath)
163             .build();
164         final Set<DataNode> allChildDataNodes = new ImmutableSet.Builder<DataNode>()
165             .addAll(parentDataNode.getChildDataNodes())
166             .add(newChildDataNode)
167             .build();
168         parentDataNode.setChildDataNodes(allChildDataNodes);
169         return newChildDataNode;
170     }
171
172 }