Merge "Define Initial Data Sync Enabled Flag and state"
[cps.git] / cps-ncmp-service / src / main / java / org / onap / cps / ncmp / api / impl / NetworkCmProxyCmHandlerQueryServiceImpl.java
1 /*
2  *  ============LICENSE_START=======================================================
3  *  Copyright (C) 2022 Nordix Foundation
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  *
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.ncmp.api.impl;
22
23 import static org.onap.cps.ncmp.api.impl.utils.YangDataConverter.convertYangModelCmHandleToNcmpServiceCmHandle;
24 import static org.onap.cps.utils.CmHandleQueryRestParametersValidator.validateModuleNameConditionProperties;
25
26 import java.util.ArrayList;
27 import java.util.Collection;
28 import java.util.Collections;
29 import java.util.HashMap;
30 import java.util.HashSet;
31 import java.util.List;
32 import java.util.Map;
33 import java.util.Set;
34 import java.util.stream.Collectors;
35 import lombok.RequiredArgsConstructor;
36 import lombok.extern.slf4j.Slf4j;
37 import org.onap.cps.ncmp.api.NetworkCmProxyCmHandlerQueryService;
38 import org.onap.cps.ncmp.api.impl.utils.YangDataConverter;
39 import org.onap.cps.ncmp.api.inventory.InventoryPersistence;
40 import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle;
41 import org.onap.cps.spi.model.Anchor;
42 import org.onap.cps.spi.model.CmHandleQueryServiceParameters;
43 import org.onap.cps.spi.model.ConditionProperties;
44 import org.onap.cps.spi.model.DataNode;
45 import org.springframework.stereotype.Service;
46
47 @Service
48 @Slf4j
49 @RequiredArgsConstructor
50 public class NetworkCmProxyCmHandlerQueryServiceImpl implements NetworkCmProxyCmHandlerQueryService {
51
52     private static final String PROPERTY_QUERY_NAME = "hasAllProperties";
53     private static final String MODULE_QUERY_NAME = "hasAllModules";
54     private static final Map<String, NcmpServiceCmHandle> NO_QUERY_EXECUTED = null;
55     private final InventoryPersistence inventoryPersistence;
56
57     /**
58      * Query and return cm handles that match the given query parameters.
59      *
60      * @param cmHandleQueryServiceParameters the cm handle query parameters
61      * @return collection of cm handles
62      */
63     @Override
64     public Set<NcmpServiceCmHandle> queryCmHandles(
65         final CmHandleQueryServiceParameters cmHandleQueryServiceParameters) {
66
67         if (cmHandleQueryServiceParameters.getCmHandleQueryParameters().isEmpty()) {
68             return getAllCmHandles();
69         }
70
71         final Map<String, NcmpServiceCmHandle> publicPropertyQueryResult
72             = executePublicPropertyQueries(cmHandleQueryServiceParameters);
73
74         final Map<String, NcmpServiceCmHandle> combinedQueryResult =
75             combineWithModuleNameQuery(cmHandleQueryServiceParameters, publicPropertyQueryResult);
76
77         return combinedQueryResult == NO_QUERY_EXECUTED
78             ? Collections.emptySet() : new HashSet<>(combinedQueryResult.values());
79     }
80
81     /**
82      * Query and return cm handles that match the given query parameters.
83      *
84      * @param cmHandleQueryServiceParameters the cm handle query parameters
85      * @return collection of cm handle ids
86      */
87     @Override
88     public Set<String> queryCmHandleIds(
89         final CmHandleQueryServiceParameters cmHandleQueryServiceParameters) {
90
91         if (cmHandleQueryServiceParameters.getCmHandleQueryParameters().isEmpty()) {
92             return getAllCmHandleIds();
93         }
94
95         final Map<String, NcmpServiceCmHandle> publicPropertyQueryResult
96             = executePublicPropertyQueries(cmHandleQueryServiceParameters);
97
98         final Collection<String> moduleNamesForQuery =
99             getModuleNamesForQuery(cmHandleQueryServiceParameters.getCmHandleQueryParameters());
100         if (moduleNamesForQuery.isEmpty()) {
101             return publicPropertyQueryResult == NO_QUERY_EXECUTED
102                 ? Collections.emptySet() : publicPropertyQueryResult.keySet();
103         }
104         final Set<String> moduleNameQueryResult = getNamesOfAnchorsWithGivenModules(moduleNamesForQuery);
105
106         if (publicPropertyQueryResult == NO_QUERY_EXECUTED) {
107             return moduleNameQueryResult;
108         }
109
110         moduleNameQueryResult.retainAll(publicPropertyQueryResult.keySet());
111         return moduleNameQueryResult;
112     }
113
114     private Map<String, NcmpServiceCmHandle> executePublicPropertyQueries(
115         final CmHandleQueryServiceParameters cmHandleQueryServiceParameters) {
116         final Map<String, String> publicPropertyQueryPairs =
117             getPublicPropertyPairs(cmHandleQueryServiceParameters.getCmHandleQueryParameters());
118         if (publicPropertyQueryPairs.isEmpty()) {
119             return NO_QUERY_EXECUTED;
120         }
121         Map<String, NcmpServiceCmHandle> cmHandleIdToNcmpServiceCmHandles = null;
122         for (final Map.Entry<String, String> entry : publicPropertyQueryPairs.entrySet()) {
123             final String cpsPath = "//public-properties[@name='" + entry.getKey() + "' and @value='"
124                 + entry.getValue() + "']/ancestor::cm-handles";
125
126             final Collection<DataNode> dataNodes = inventoryPersistence.queryDataNodes(cpsPath);
127             if (cmHandleIdToNcmpServiceCmHandles == NO_QUERY_EXECUTED) {
128                 cmHandleIdToNcmpServiceCmHandles = collectDataNodesToNcmpServiceCmHandles(dataNodes);
129             } else {
130                 final Collection<String> cmHandleIdsToRetain = dataNodes.parallelStream()
131                     .map(dataNode -> dataNode.getLeaves().get("id").toString()).collect(Collectors.toSet());
132                 cmHandleIdToNcmpServiceCmHandles.keySet().retainAll(cmHandleIdsToRetain);
133             }
134             if (cmHandleIdToNcmpServiceCmHandles.isEmpty()) {
135                 break;
136             }
137         }
138         return cmHandleIdToNcmpServiceCmHandles;
139     }
140
141     private Map<String, NcmpServiceCmHandle> combineWithModuleNameQuery(
142         final CmHandleQueryServiceParameters cmHandleQueryServiceParameters,
143         final Map<String, NcmpServiceCmHandle> previousQueryResult) {
144         final Collection<String> moduleNamesForQuery =
145             getModuleNamesForQuery(cmHandleQueryServiceParameters.getCmHandleQueryParameters());
146         if (moduleNamesForQuery.isEmpty()) {
147             return previousQueryResult;
148         }
149         final Collection<String> cmHandleIdsByModuleName = getNamesOfAnchorsWithGivenModules(moduleNamesForQuery);
150         if (cmHandleIdsByModuleName.isEmpty()) {
151             return Collections.emptyMap();
152         }
153         final Map<String, NcmpServiceCmHandle> queryResult = new HashMap<>(cmHandleIdsByModuleName.size());
154         if (previousQueryResult == NO_QUERY_EXECUTED) {
155             cmHandleIdsByModuleName.forEach(cmHandleId ->
156                     queryResult.put(cmHandleId, createNcmpServiceCmHandle(
157                             inventoryPersistence.getDataNode("/dmi-registry/cm-handles[@id='" + cmHandleId + "']")))
158             );
159             return queryResult;
160         }
161         previousQueryResult.keySet().retainAll(cmHandleIdsByModuleName);
162         queryResult.putAll(previousQueryResult);
163         return queryResult;
164     }
165
166     private Set<String> getNamesOfAnchorsWithGivenModules(final Collection<String> moduleNamesForQuery) {
167         final Collection<Anchor> anchors = inventoryPersistence.queryAnchors(moduleNamesForQuery);
168         return anchors.parallelStream().map(Anchor::getName).collect(Collectors.toSet());
169     }
170
171     private Map<String, NcmpServiceCmHandle> collectDataNodesToNcmpServiceCmHandles(
172         final Collection<DataNode> dataNodes) {
173         final Map<String, NcmpServiceCmHandle> cmHandleIdToNcmpServiceCmHandle = new HashMap<>();
174         dataNodes.forEach(dataNode -> {
175             final NcmpServiceCmHandle ncmpServiceCmHandle = createNcmpServiceCmHandle(dataNode);
176             cmHandleIdToNcmpServiceCmHandle.put(ncmpServiceCmHandle.getCmHandleId(), ncmpServiceCmHandle);
177         });
178         return cmHandleIdToNcmpServiceCmHandle;
179     }
180
181     private List<Map<String, String>> getConditions(final List<ConditionProperties> conditionProperties,
182                                                     final String name) {
183         for (final ConditionProperties conditionProperty : conditionProperties) {
184             if (conditionProperty.getConditionName().equals(name)) {
185                 return conditionProperty.getConditionParameters();
186             }
187         }
188         return Collections.emptyList();
189     }
190
191     private Collection<String> getModuleNamesForQuery(final List<ConditionProperties> conditionProperties) {
192         final List<String> result = new ArrayList<>();
193         getConditions(conditionProperties, MODULE_QUERY_NAME).parallelStream().forEach(
194             conditionProperty -> {
195                 validateModuleNameConditionProperties(conditionProperty);
196                 result.add(conditionProperty.get("moduleName"));
197             }
198         );
199         return result;
200     }
201
202     private Map<String, String> getPublicPropertyPairs(final List<ConditionProperties> conditionProperties) {
203         final Map<String, String> result = new HashMap<>();
204         getConditions(conditionProperties, PROPERTY_QUERY_NAME).forEach(result::putAll);
205         return result;
206     }
207
208     private Set<NcmpServiceCmHandle> getAllCmHandles() {
209         return inventoryPersistence.getDataNode("/dmi-registry")
210             .getChildDataNodes().stream().map(this::createNcmpServiceCmHandle).collect(Collectors.toSet());
211     }
212
213     private Set<String> getAllCmHandleIds() {
214         return inventoryPersistence.getAnchors().parallelStream().map(Anchor::getName).collect(Collectors.toSet());
215     }
216
217     private NcmpServiceCmHandle createNcmpServiceCmHandle(final DataNode dataNode) {
218         return convertYangModelCmHandleToNcmpServiceCmHandle(YangDataConverter
219             .convertCmHandleToYangModel(dataNode, dataNode.getLeaves().get("id").toString()));
220     }
221 }