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