Fix upload size to be greater than 1MB
[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  *  Modifications Copyright (C) 2021 Pantheon.tech
5  *  ================================================================================
6  *  Licensed under the Apache License, Version 2.0 (the "License");
7  *  you may not use this file except in compliance with the License.
8  *  You may obtain a copy of the License at
9  *
10  *        http://www.apache.org/licenses/LICENSE-2.0
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  *  SPDX-License-Identifier: Apache-2.0
18  *  ============LICENSE_END=========================================================
19  */
20
21 package org.onap.cps.spi.model;
22
23 import com.google.common.collect.ImmutableMap;
24 import com.google.common.collect.ImmutableSet;
25 import java.util.Collection;
26 import java.util.Collections;
27 import java.util.List;
28 import java.util.Map;
29 import java.util.Set;
30 import java.util.stream.Collectors;
31 import lombok.extern.slf4j.Slf4j;
32 import org.onap.cps.utils.YangUtils;
33 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
34 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerNode;
35 import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode;
36 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
37 import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
38 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
39 import org.opendaylight.yangtools.yang.data.api.schema.ValueNode;
40
41 @Slf4j
42 public class DataNodeBuilder {
43
44     private NormalizedNode<?, ?> normalizedNodeTree;
45     private String xpath;
46     private String parentNodeXpath = "";
47     private Map<String, Object> leaves = Collections.emptyMap();
48     private Collection<DataNode> childDataNodes = Collections.emptySet();
49
50     /**
51      * To use parent node xpath for creating {@link DataNode}.
52      *
53      * @param parentNodeXpath xpath of a parent node
54      * @return this {@link DataNodeBuilder} object
55      */
56     public DataNodeBuilder withParentNodeXpath(final String parentNodeXpath) {
57         this.parentNodeXpath = parentNodeXpath;
58         return this;
59     }
60
61
62     /**
63      * To use {@link NormalizedNode} for creating {@link DataNode}.
64      *
65      * @param normalizedNodeTree used for creating the Data Node
66      * @return this {@link DataNodeBuilder} object
67      */
68     public DataNodeBuilder withNormalizedNodeTree(final NormalizedNode<?, ?> normalizedNodeTree) {
69         this.normalizedNodeTree = normalizedNodeTree;
70         return this;
71     }
72
73     /**
74      * To use xpath for creating {@link DataNode}.
75      *
76      * @param xpath for the data node
77      * @return DataNodeBuilder
78      */
79     public DataNodeBuilder withXpath(final String xpath) {
80         this.xpath = xpath;
81         return this;
82     }
83
84     /**
85      * To use attributes for creating {@link DataNode}.
86      *
87      * @param leaves for the data node
88      * @return DataNodeBuilder
89      */
90     public DataNodeBuilder withLeaves(final Map<String, Object> leaves) {
91         this.leaves = leaves;
92         return this;
93     }
94
95     /**
96      * To specify child nodes needs to be used while creating {@link DataNode}.
97      *
98      * @param childDataNodes to be added to the dataNode
99      * @return DataNodeBuilder
100      */
101     public DataNodeBuilder withChildDataNodes(final Collection<DataNode> childDataNodes) {
102         // Added as this is being set from test cases .
103         // Open for suggestions
104         this.childDataNodes = childDataNodes;
105         return this;
106     }
107
108     /**
109      * To create the {@link DataNode}.
110      *
111      * @return {@link DataNode}
112      */
113     public DataNode build() {
114         if (normalizedNodeTree != null) {
115             return buildFromNormalizedNodeTree();
116         } else {
117             return buildFromAttributes();
118         }
119     }
120
121     private DataNode buildFromAttributes() {
122         final DataNode dataNode = new DataNode();
123         dataNode.setXpath(xpath);
124         dataNode.setLeaves(leaves);
125         dataNode.setChildDataNodes(childDataNodes);
126         return dataNode;
127     }
128
129     private DataNode buildFromNormalizedNodeTree() {
130         final DataNode parentDataNode = new DataNodeBuilder().withXpath(parentNodeXpath).build();
131         addDataNodeFromNormalizedNode(parentDataNode, normalizedNodeTree);
132         return parentDataNode.getChildDataNodes().iterator().next();
133     }
134
135     private static void addDataNodeFromNormalizedNode(final DataNode currentDataNode,
136         final NormalizedNode<?, ?> normalizedNode) {
137
138         if (normalizedNode instanceof DataContainerNode) {
139             addYangContainer(currentDataNode, (DataContainerNode<?>) normalizedNode);
140         } else if (normalizedNode instanceof MapNode) {
141             addDataNodeForEachListElement(currentDataNode, (MapNode) normalizedNode);
142         } else if (normalizedNode instanceof ValueNode) {
143             final ValueNode<?, ?> valuesNode = (ValueNode<?, ?>) normalizedNode;
144             addYangLeaf(currentDataNode, valuesNode.getNodeType().getLocalName(), valuesNode.getValue());
145         } else if (normalizedNode instanceof LeafSetNode) {
146             addYangLeafList(currentDataNode, (LeafSetNode<?>) normalizedNode);
147         } else {
148             log.warn("Unsupported NormalizedNode type detected: {}", normalizedNode.getClass());
149         }
150     }
151
152     private static void addYangContainer(final DataNode currentDataNode, final DataContainerNode<?> dataContainerNode) {
153         final DataNode dataContainerDataNode = createAndAddChildDataNode(currentDataNode,
154             YangUtils.buildXpath(dataContainerNode.getIdentifier()));
155         final Collection<DataContainerChild<?, ?>> normalizedChildNodes = dataContainerNode.getValue();
156         for (final NormalizedNode<?, ?> normalizedNode : normalizedChildNodes) {
157             addDataNodeFromNormalizedNode(dataContainerDataNode, normalizedNode);
158         }
159     }
160
161     private static void addYangLeaf(final DataNode currentDataNode, final String leafName, final Object leafValue) {
162         final Map<String, Object> leaves = new ImmutableMap.Builder<String, Object>()
163             .putAll(currentDataNode.getLeaves())
164             .put(leafName, leafValue)
165             .build();
166         currentDataNode.setLeaves(leaves);
167     }
168
169     private static void addYangLeafList(final DataNode currentDataNode, final LeafSetNode<?> leafSetNode) {
170         final String leafListName = leafSetNode.getNodeType().getLocalName();
171         final List<?> leafListValues = ((Collection<? extends NormalizedNode<?, ?>>) leafSetNode.getValue())
172             .stream()
173             .map(normalizedNode -> ((ValueNode<?, ?>) normalizedNode).getValue())
174             .collect(Collectors.toUnmodifiableList());
175         addYangLeaf(currentDataNode, leafListName, leafListValues);
176     }
177
178     private static void addDataNodeForEachListElement(final DataNode currentDataNode, final MapNode mapNode) {
179         final Collection<MapEntryNode> mapEntryNodes = mapNode.getValue();
180         for (final MapEntryNode mapEntryNode : mapEntryNodes) {
181             addDataNodeFromNormalizedNode(currentDataNode, mapEntryNode);
182         }
183     }
184
185     private static DataNode createAndAddChildDataNode(final DataNode parentDataNode, final String childXpath) {
186
187         final DataNode newChildDataNode = new DataNodeBuilder()
188             .withXpath(parentDataNode.getXpath() + childXpath)
189             .build();
190         final Set<DataNode> allChildDataNodes = new ImmutableSet.Builder<DataNode>()
191             .addAll(parentDataNode.getChildDataNodes())
192             .add(newChildDataNode)
193             .build();
194         parentDataNode.setChildDataNodes(allChildDataNodes);
195         return newChildDataNode;
196     }
197
198 }