Add performance tests for update data nodes
[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  *  Modifications Copyright (C) 2023 TechMahindra Ltd.
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  *
12  *  Unless required by applicable law or agreed to in writing, software
13  *  distributed under the License is distributed on an "AS IS" BASIS,
14  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  *  See the License for the specific language governing permissions and
16  *  limitations under the License.
17  *
18  *  SPDX-License-Identifier: Apache-2.0
19  *  ============LICENSE_END=========================================================
20  */
21
22 package org.onap.cps.ncmp.api.impl;
23
24 import static org.onap.cps.ncmp.api.impl.utils.RestQueryParametersValidator.validateCpsPathConditionProperties;
25 import static org.onap.cps.ncmp.api.impl.utils.RestQueryParametersValidator.validateModuleNameConditionProperties;
26 import static org.onap.cps.ncmp.api.impl.utils.YangDataConverter.convertYangModelCmHandleToNcmpServiceCmHandle;
27 import static org.onap.cps.spi.FetchDescendantsOption.FETCH_DIRECT_CHILDREN_ONLY;
28 import static org.onap.cps.spi.FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS;
29 import static org.onap.cps.spi.FetchDescendantsOption.OMIT_DESCENDANTS;
30
31 import java.util.ArrayList;
32 import java.util.Collection;
33 import java.util.Collections;
34 import java.util.HashMap;
35 import java.util.HashSet;
36 import java.util.List;
37 import java.util.Map;
38 import java.util.Set;
39 import java.util.function.Function;
40 import java.util.stream.Collectors;
41 import lombok.RequiredArgsConstructor;
42 import lombok.extern.slf4j.Slf4j;
43 import org.onap.cps.cpspath.parser.PathParsingException;
44 import org.onap.cps.ncmp.api.NetworkCmProxyCmHandlerQueryService;
45 import org.onap.cps.ncmp.api.impl.utils.CmHandleQueryConditions;
46 import org.onap.cps.ncmp.api.impl.utils.InventoryQueryConditions;
47 import org.onap.cps.ncmp.api.impl.utils.YangDataConverter;
48 import org.onap.cps.ncmp.api.inventory.CmHandleQueries;
49 import org.onap.cps.ncmp.api.inventory.InventoryPersistence;
50 import org.onap.cps.ncmp.api.inventory.enums.PropertyType;
51 import org.onap.cps.ncmp.api.models.CmHandleQueryServiceParameters;
52 import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle;
53 import org.onap.cps.spi.FetchDescendantsOption;
54 import org.onap.cps.spi.exceptions.DataValidationException;
55 import org.onap.cps.spi.model.ConditionProperties;
56 import org.onap.cps.spi.model.DataNode;
57 import org.springframework.stereotype.Service;
58
59 @Service
60 @Slf4j
61 @RequiredArgsConstructor
62 public class NetworkCmProxyCmHandlerQueryServiceImpl implements NetworkCmProxyCmHandlerQueryService {
63
64     private static final Map<String, NcmpServiceCmHandle> NO_QUERY_TO_EXECUTE = null;
65     private final CmHandleQueries cmHandleQueries;
66     private final InventoryPersistence inventoryPersistence;
67
68     /**
69      * Query and return cm handles that match the given query parameters.
70      *
71      * @param cmHandleQueryServiceParameters the cm handle query parameters
72      * @return collection of cm handles
73      */
74     @Override
75     public Set<NcmpServiceCmHandle> queryCmHandles(
76             final CmHandleQueryServiceParameters cmHandleQueryServiceParameters) {
77
78         if (cmHandleQueryServiceParameters.getCmHandleQueryParameters().isEmpty()) {
79             return getAllCmHandles();
80         }
81
82         final Map<String, NcmpServiceCmHandle> combinedQueryResult = executeInventoryQueries(
83                 cmHandleQueryServiceParameters, INCLUDE_ALL_DESCENDANTS);
84
85         return new HashSet<>(combineWithModuleNameQuery(cmHandleQueryServiceParameters, combinedQueryResult).values());
86     }
87
88     /**
89      * Query and return cm handles that match the given query parameters.
90      *
91      * @param cmHandleQueryServiceParameters the cm handle query parameters
92      * @return collection of cm handle ids
93      */
94     @Override
95     public Set<String> queryCmHandleIds(
96             final CmHandleQueryServiceParameters cmHandleQueryServiceParameters) {
97
98         if (cmHandleQueryServiceParameters.getCmHandleQueryParameters().isEmpty()) {
99             return getAllCmHandleIds();
100         }
101
102         final Map<String, NcmpServiceCmHandle> combinedQueryResult = executeInventoryQueries(
103                 cmHandleQueryServiceParameters, OMIT_DESCENDANTS);
104
105         final Collection<String> moduleNamesForQuery =
106                 getModuleNamesForQuery(cmHandleQueryServiceParameters.getCmHandleQueryParameters());
107         if (moduleNamesForQuery.isEmpty()) {
108             return combinedQueryResult.keySet();
109         }
110         final Set<String> moduleNameQueryResult =
111                 new HashSet<>(inventoryPersistence.getCmHandleIdsWithGivenModules(moduleNamesForQuery));
112
113         if (combinedQueryResult == NO_QUERY_TO_EXECUTE) {
114             return moduleNameQueryResult;
115         }
116
117         moduleNameQueryResult.retainAll(combinedQueryResult.keySet());
118         return moduleNameQueryResult;
119     }
120
121     @Override
122     public Set<String> queryCmHandleIdsForInventory(
123             final CmHandleQueryServiceParameters cmHandleQueryServiceParameters) {
124
125         if (cmHandleQueryServiceParameters.getCmHandleQueryParameters().isEmpty()) {
126             return getAllCmHandleIds();
127         }
128
129         final Map<String, NcmpServiceCmHandle> publicPropertiesQueryResult = queryCmHandlesByPublicProperties(
130                 cmHandleQueryServiceParameters);
131         if (publicPropertiesQueryResult != null && publicPropertiesQueryResult.isEmpty()) {
132             return Collections.emptySet();
133         }
134
135         final Map<String, NcmpServiceCmHandle> privatePropertiesQueryResult = queryCmHandlesByPrivateProperties(
136                 cmHandleQueryServiceParameters);
137         if (privatePropertiesQueryResult != null && privatePropertiesQueryResult.isEmpty()) {
138             return Collections.emptySet();
139         }
140
141         final Map<String, NcmpServiceCmHandle> dmiPropertiesQueryResult = queryCmHandlesByDmiPlugin(
142                 cmHandleQueryServiceParameters);
143         if (dmiPropertiesQueryResult != null && dmiPropertiesQueryResult.isEmpty()) {
144             return Collections.emptySet();
145         }
146
147         final Map<String, NcmpServiceCmHandle> combinedResult =
148               combineQueryResults(publicPropertiesQueryResult, privatePropertiesQueryResult, dmiPropertiesQueryResult);
149
150         return combinedResult.keySet();
151     }
152
153     private Map<String, NcmpServiceCmHandle> queryCmHandlesByDmiPlugin(
154             final CmHandleQueryServiceParameters cmHandleQueryServiceParameters) {
155         final Map<String, String> dmiPropertyQueryPairs =
156                 getPropertyPairs(cmHandleQueryServiceParameters.getCmHandleQueryParameters(),
157                         InventoryQueryConditions.CM_HANDLE_WITH_DMI_PLUGIN.getName());
158         if (dmiPropertyQueryPairs.isEmpty()) {
159             return NO_QUERY_TO_EXECUTE;
160         }
161
162         final String dmiPluginIdentifierValue = dmiPropertyQueryPairs.get(
163                 PropertyType.DMI_PLUGIN.getYangContainerName());
164
165         final Set<NcmpServiceCmHandle> cmHandlesByDmiPluginIdentifier = cmHandleQueries
166                 .getCmHandlesByDmiPluginIdentifier(dmiPluginIdentifierValue);
167
168         return cmHandlesByDmiPluginIdentifier.stream()
169                 .collect(Collectors.toMap(NcmpServiceCmHandle::getCmHandleId, cmH -> cmH));
170     }
171
172     private Map<String, NcmpServiceCmHandle> queryCmHandlesByPrivateProperties(
173             final CmHandleQueryServiceParameters cmHandleQueryServiceParameters) {
174
175         final Map<String, String> privatePropertyQueryPairs =
176                 getPropertyPairs(cmHandleQueryServiceParameters.getCmHandleQueryParameters(),
177                         InventoryQueryConditions.HAS_ALL_ADDITIONAL_PROPERTIES.getName());
178
179         return privatePropertyQueryPairs.isEmpty()
180                 ? NO_QUERY_TO_EXECUTE
181                 : cmHandleQueries.queryCmHandleAdditionalProperties(privatePropertyQueryPairs);
182     }
183
184     private Map<String, NcmpServiceCmHandle> queryCmHandlesByPublicProperties(
185             final CmHandleQueryServiceParameters cmHandleQueryServiceParameters) {
186
187         final Map<String, String> publicPropertyQueryPairs =
188                 getPropertyPairs(cmHandleQueryServiceParameters.getCmHandleQueryParameters(),
189                         CmHandleQueryConditions.HAS_ALL_PROPERTIES.getConditionName());
190
191         return publicPropertyQueryPairs.isEmpty()
192                 ? NO_QUERY_TO_EXECUTE
193                 : cmHandleQueries.queryCmHandlePublicProperties(publicPropertyQueryPairs);
194     }
195
196     private Map<String, NcmpServiceCmHandle> combineQueryResults(
197             final Map<String, NcmpServiceCmHandle> publicPropertiesQueryResult,
198             final Map<String, NcmpServiceCmHandle> privatePropertiesQueryResult,
199             final Map<String, NcmpServiceCmHandle> dmiPropertiesQueryResult) {
200
201         final Map<String, NcmpServiceCmHandle> propertiesCombinedResult = cmHandleQueries
202                 .combineCmHandleQueries(publicPropertiesQueryResult, privatePropertiesQueryResult);
203         return cmHandleQueries
204                 .combineCmHandleQueries(propertiesCombinedResult, dmiPropertiesQueryResult);
205     }
206
207     private Map<String, NcmpServiceCmHandle> combineWithModuleNameQuery(
208             final CmHandleQueryServiceParameters cmHandleQueryServiceParameters,
209             final Map<String, NcmpServiceCmHandle> previousQueryResult) {
210         final Collection<String> moduleNamesForQuery =
211                 getModuleNamesForQuery(cmHandleQueryServiceParameters.getCmHandleQueryParameters());
212         if (moduleNamesForQuery.isEmpty()) {
213             return previousQueryResult;
214         }
215         final Collection<String> cmHandleIdsByModuleName =
216                 inventoryPersistence.getCmHandleIdsWithGivenModules(moduleNamesForQuery);
217         if (cmHandleIdsByModuleName.isEmpty()) {
218             return Collections.emptyMap();
219         }
220         final Map<String, NcmpServiceCmHandle> queryResult = new HashMap<>(cmHandleIdsByModuleName.size());
221         if (previousQueryResult == NO_QUERY_TO_EXECUTE) {
222             cmHandleIdsByModuleName.forEach(cmHandleId ->
223                     queryResult.put(cmHandleId, createNcmpServiceCmHandle(inventoryPersistence
224                             .getDataNode("/dmi-registry/cm-handles[@id='" + cmHandleId + "']").iterator().next()))
225             );
226             return queryResult;
227         }
228         previousQueryResult.keySet().retainAll(cmHandleIdsByModuleName);
229         queryResult.putAll(previousQueryResult);
230         return queryResult;
231     }
232
233     private Map<String, NcmpServiceCmHandle> executeInventoryQueries(
234             final CmHandleQueryServiceParameters cmHandleQueryServiceParameters,
235             final FetchDescendantsOption fetchDescendantsOption) {
236         final Map<String, String> cpsPath = getCpsPath(cmHandleQueryServiceParameters.getCmHandleQueryParameters());
237         if (!validateCpsPathConditionProperties(cpsPath)) {
238             return Collections.emptyMap();
239         }
240         final Map<String, NcmpServiceCmHandle> cpsPathQueryResult;
241         if (cpsPath.isEmpty()) {
242             cpsPathQueryResult = NO_QUERY_TO_EXECUTE;
243         } else {
244             try {
245                 cpsPathQueryResult = cmHandleQueries.queryCmHandleDataNodesByCpsPath(
246                                 cpsPath.get("cpsPath"), fetchDescendantsOption)
247                         .stream().map(this::createNcmpServiceCmHandle)
248                         .collect(Collectors.toMap(NcmpServiceCmHandle::getCmHandleId,
249                                 Function.identity()));
250             } catch (final PathParsingException pathParsingException) {
251                 throw new DataValidationException(pathParsingException.getMessage(), pathParsingException.getDetails(),
252                         pathParsingException);
253             }
254             if (cpsPathQueryResult.isEmpty()) {
255                 return Collections.emptyMap();
256             }
257         }
258
259         final Map<String, String> publicPropertyQueryPairs =
260                 getPropertyPairs(cmHandleQueryServiceParameters.getCmHandleQueryParameters(),
261                         CmHandleQueryConditions.HAS_ALL_PROPERTIES.getConditionName());
262         final Map<String, NcmpServiceCmHandle> propertiesQueryResult = publicPropertyQueryPairs.isEmpty()
263                 ? NO_QUERY_TO_EXECUTE : cmHandleQueries.queryCmHandlePublicProperties(publicPropertyQueryPairs);
264
265         return cmHandleQueries.combineCmHandleQueries(cpsPathQueryResult, propertiesQueryResult);
266     }
267
268     private Collection<String> getModuleNamesForQuery(final List<ConditionProperties> conditionProperties) {
269         final List<String> result = new ArrayList<>();
270         getConditions(conditionProperties, CmHandleQueryConditions.HAS_ALL_MODULES.getConditionName())
271             .parallelStream().forEach(
272                 conditionProperty -> {
273                     validateModuleNameConditionProperties(conditionProperty);
274                     result.add(conditionProperty.get("moduleName"));
275                 }
276             );
277         return result;
278     }
279
280     private Map<String, String> getCpsPath(final List<ConditionProperties> conditionProperties) {
281         final Map<String, String> result = new HashMap<>();
282         getConditions(conditionProperties, CmHandleQueryConditions.WITH_CPS_PATH.getConditionName()).forEach(
283                 result::putAll);
284         return result;
285     }
286
287     private Map<String, String> getPropertyPairs(final List<ConditionProperties> conditionProperties,
288                                                        final String queryProperty) {
289         final Map<String, String> result = new HashMap<>();
290         getConditions(conditionProperties, queryProperty).forEach(result::putAll);
291         return result;
292     }
293
294     private List<Map<String, String>> getConditions(final List<ConditionProperties> conditionProperties,
295                                                     final String name) {
296         for (final ConditionProperties conditionProperty : conditionProperties) {
297             if (conditionProperty.getConditionName().equals(name)) {
298                 return conditionProperty.getConditionParameters();
299             }
300         }
301         return Collections.emptyList();
302     }
303
304     private Set<NcmpServiceCmHandle> getAllCmHandles() {
305         final DataNode dataNode = inventoryPersistence.getDataNode("/dmi-registry").iterator().next();
306         return dataNode.getChildDataNodes().stream().map(this::createNcmpServiceCmHandle).collect(Collectors.toSet());
307     }
308
309     private Set<String> getAllCmHandleIds() {
310         final DataNode dataNodes = inventoryPersistence.getDataNode("/dmi-registry", FETCH_DIRECT_CHILDREN_ONLY)
311                 .iterator().next();
312         return dataNodes.getChildDataNodes().stream().map(dataNode -> dataNode.getLeaves().get("id").toString())
313                 .collect(Collectors.toSet());
314     }
315
316     private NcmpServiceCmHandle createNcmpServiceCmHandle(final DataNode dataNode) {
317         return convertYangModelCmHandleToNcmpServiceCmHandle(YangDataConverter
318                 .convertCmHandleToYangModel(dataNode, dataNode.getLeaves().get("id").toString()));
319     }
320 }