Merge "CM SUBSCRIPTION: add new subscription for non existing xpath"
[cps.git] / cps-service / src / main / java / org / onap / cps / utils / DataMapUtils.java
1 /*
2  *  ============LICENSE_START=======================================================
3  *  Copyright (C) 2021 Pantheon.tech
4  *  Modifications (C) 2021-2023 Nordix Foundation
5  *  Modifications Copyright (C) 2022 Bell Canada
6  *  Modifications Copyright (C) 2022-2023 TechMahindra Ltd.
7  *  ================================================================================
8  *  Licensed under the Apache License, Version 2.0 (the "License");
9  *  you may not use this file except in compliance with the License.
10  *  You may obtain a copy of the License at
11  *
12  *        http://www.apache.org/licenses/LICENSE-2.0
13  *  Unless required by applicable law or agreed to in writing, software
14  *  distributed under the License is distributed on an "AS IS" BASIS,
15  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  *  See the License for the specific language governing permissions and
17  *  limitations under the License.
18  *
19  *  SPDX-License-Identifier: Apache-2.0
20  *  ============LICENSE_END=========================================================
21  */
22
23 package org.onap.cps.utils;
24
25 import static java.util.stream.Collectors.groupingBy;
26 import static java.util.stream.Collectors.mapping;
27 import static java.util.stream.Collectors.toUnmodifiableList;
28 import static java.util.stream.Collectors.toUnmodifiableMap;
29
30 import com.google.common.collect.ImmutableMap;
31 import java.util.ArrayList;
32 import java.util.Collection;
33 import java.util.Collections;
34 import java.util.List;
35 import java.util.Map;
36 import lombok.AccessLevel;
37 import lombok.NoArgsConstructor;
38 import org.onap.cps.cpspath.parser.CpsPathQuery;
39 import org.onap.cps.cpspath.parser.CpsPathUtil;
40 import org.onap.cps.spi.model.DataNode;
41
42 @NoArgsConstructor(access = AccessLevel.PRIVATE)
43 public class DataMapUtils {
44
45     /**
46      * Converts DataNode structure into a map including the root node identifier for a JSON response.
47      *
48      * @param dataNode data node object
49      * @return a map representing same data with the root node identifier
50      */
51     public static Map<String, Object> toDataMapWithIdentifier(final DataNode dataNode, final String prefix) {
52         final String nodeIdentifierWithPrefix = getNodeIdentifierWithPrefix(dataNode.getXpath(), prefix);
53         return ImmutableMap.<String, Object>builder().put(nodeIdentifierWithPrefix, toDataMap(dataNode)).build();
54     }
55
56     /**
57      * Converts list of DataNode structure into a map including the root node identifier for a JSON response.
58      * @param dataNodeList list of data nodes for a given anchor name
59      * @param anchorName anchor name
60      * @param prefix prefix
61      * @return a map representing same list of data for given anchor with the root node identifier
62      */
63     public static Map<String, Object> toDataMapWithIdentifierAndAnchor(final List<DataNode> dataNodeList,
64                                                                        final String anchorName, final String prefix) {
65         final List<Map<String, Object>> dataMaps = toDataNodesWithIdentifier(dataNodeList, prefix);
66         return ImmutableMap.<String, Object>builder().put("anchorName", anchorName)
67                 .put("dataNodes", dataMaps).build();
68     }
69
70     private static List<Map<String, Object>> toDataNodesWithIdentifier(final List<DataNode> dataNodeList,
71                                                                        final String prefix) {
72         final List<Map<String, Object>> dataMaps = new ArrayList<>(dataNodeList.size());
73         for (final DataNode dataNode: dataNodeList) {
74             final String nodeIdentifierWithPrefix = getNodeIdentifierWithPrefix(dataNode.getXpath(), prefix);
75             final Map<String, Object> dataMap = ImmutableMap.<String, Object>builder()
76                     .put(nodeIdentifierWithPrefix, toDataMap(dataNode)).build();
77             dataMaps.add(dataMap);
78         }
79         return dataMaps;
80     }
81
82     /**
83      * Converts DataNode structure into a map for a JSON response.
84      *
85      * @param dataNode data node object
86      * @return a map representing same data
87      */
88     public static Map<String, Object> toDataMap(final DataNode dataNode) {
89         return ImmutableMap.<String, Object>builder()
90             .putAll(dataNode.getLeaves())
91             .putAll(listElementsAsMap(dataNode.getChildDataNodes()))
92             .putAll(containerElementsAsMap(dataNode.getChildDataNodes()))
93             .build();
94     }
95
96     private static Map<String, Object> listElementsAsMap(final Collection<DataNode> dataNodes) {
97         if (dataNodes.isEmpty()) {
98             return Collections.emptyMap();
99         }
100         return ImmutableMap.<String, Object>builder()
101             .putAll(
102                 dataNodes.stream()
103                     .filter(dataNode -> isListElement(dataNode.getXpath()))
104                     .collect(groupingBy(
105                         dataNode -> getNodeIdentifier(dataNode.getXpath()),
106                         mapping(DataMapUtils::toDataMap, toUnmodifiableList())
107                     ))
108             ).build();
109     }
110
111     private static Map<String, Object> containerElementsAsMap(final Collection<DataNode> dataNodes) {
112         if (dataNodes.isEmpty()) {
113             return Collections.emptyMap();
114         }
115         return dataNodes.stream()
116             .filter(dataNode -> isContainerNode(dataNode.getXpath()))
117             .collect(
118                 toUnmodifiableMap(
119                     dataNode -> getNodeIdentifier(dataNode.getXpath()),
120                     DataMapUtils::toDataMap
121                 ));
122     }
123
124     private static String getNodeIdentifier(String xpath) {
125         final CpsPathQuery cpsPathQuery = CpsPathUtil.getCpsPathQuery(xpath);
126         if (cpsPathQuery.isPathToListElement()) {
127             xpath = cpsPathQuery.getXpathPrefix();
128         }
129         final int fromIndex = xpath.lastIndexOf('/') + 1;
130         return xpath.substring(fromIndex);
131     }
132
133     private static String getNodeIdentifierWithPrefix(final String xpath, final String moduleNamePrefix) {
134         if (moduleNamePrefix != null) {
135             return moduleNamePrefix + ":" + getNodeIdentifier(xpath);
136         }
137         return getNodeIdentifier(xpath);
138     }
139
140     private static boolean isContainerNode(final String xpath) {
141         return !isListElement(xpath);
142     }
143
144     private static boolean isListElement(final String xpath) {
145         return xpath.endsWith("]");
146     }
147 }