a8fc6d7057041056f122b3fe050a61fcfb0035ba
[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.RestQueryParametersValidator.validateCpsPathConditionProperties;
24 import static org.onap.cps.ncmp.api.impl.utils.RestQueryParametersValidator.validateModuleNameConditionProperties;
25 import static org.onap.cps.ncmp.api.impl.utils.YangDataConverter.convertYangModelCmHandleToNcmpServiceCmHandle;
26 import static org.onap.cps.spi.FetchDescendantsOption.FETCH_DIRECT_CHILDREN_ONLY;
27 import static org.onap.cps.spi.FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS;
28
29 import java.util.ArrayList;
30 import java.util.Collection;
31 import java.util.Collections;
32 import java.util.HashMap;
33 import java.util.HashSet;
34 import java.util.List;
35 import java.util.Map;
36 import java.util.Set;
37 import java.util.function.Function;
38 import java.util.stream.Collectors;
39 import lombok.RequiredArgsConstructor;
40 import lombok.extern.slf4j.Slf4j;
41 import org.onap.cps.cpspath.parser.PathParsingException;
42 import org.onap.cps.ncmp.api.NetworkCmProxyCmHandlerQueryService;
43 import org.onap.cps.ncmp.api.impl.utils.CmHandleQueryConditions;
44 import org.onap.cps.ncmp.api.impl.utils.InventoryQueryConditions;
45 import org.onap.cps.ncmp.api.impl.utils.YangDataConverter;
46 import org.onap.cps.ncmp.api.inventory.CmHandleQueries;
47 import org.onap.cps.ncmp.api.inventory.InventoryPersistence;
48 import org.onap.cps.ncmp.api.inventory.enums.PropertyType;
49 import org.onap.cps.ncmp.api.models.CmHandleQueryServiceParameters;
50 import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle;
51 import org.onap.cps.spi.exceptions.DataValidationException;
52 import org.onap.cps.spi.model.Anchor;
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 = getNamesOfAnchorsWithGivenModules(moduleNamesForQuery);
109
110         if (combinedQueryResult == NO_QUERY_TO_EXECUTE) {
111             return moduleNameQueryResult;
112         }
113
114         moduleNameQueryResult.retainAll(combinedQueryResult.keySet());
115         return moduleNameQueryResult;
116     }
117
118     @Override
119     public Set<String> queryCmHandleIdsForInventory(
120             final CmHandleQueryServiceParameters cmHandleQueryServiceParameters) {
121
122         if (cmHandleQueryServiceParameters.getCmHandleQueryParameters().isEmpty()) {
123             return getAllCmHandleIds();
124         }
125
126         final Map<String, NcmpServiceCmHandle> publicPropertiesQueryResult = queryCmHandlesByPublicProperties(
127                 cmHandleQueryServiceParameters);
128         if (publicPropertiesQueryResult != null && publicPropertiesQueryResult.isEmpty()) {
129             return Collections.emptySet();
130         }
131
132         final Map<String, NcmpServiceCmHandle> privatePropertiesQueryResult = queryCmHandlesByPrivateProperties(
133                 cmHandleQueryServiceParameters);
134         if (privatePropertiesQueryResult != null && privatePropertiesQueryResult.isEmpty()) {
135             return Collections.emptySet();
136         }
137
138         final Map<String, NcmpServiceCmHandle> dmiPropertiesQueryResult = queryCmHandlesByDmiPlugin(
139                 cmHandleQueryServiceParameters);
140         if (dmiPropertiesQueryResult != null && dmiPropertiesQueryResult.isEmpty()) {
141             return Collections.emptySet();
142         }
143
144         final Map<String, NcmpServiceCmHandle> combinedResult =
145               combineQueryResults(publicPropertiesQueryResult, privatePropertiesQueryResult, dmiPropertiesQueryResult);
146
147         return combinedResult.keySet();
148     }
149
150     private Map<String, NcmpServiceCmHandle> queryCmHandlesByDmiPlugin(
151             final CmHandleQueryServiceParameters cmHandleQueryServiceParameters) {
152         final Map<String, String> dmiPropertyQueryPairs =
153                 getPropertyPairs(cmHandleQueryServiceParameters.getCmHandleQueryParameters(),
154                         InventoryQueryConditions.CM_HANDLE_WITH_DMI_PLUGIN.getName());
155         if (dmiPropertyQueryPairs.isEmpty()) {
156             return NO_QUERY_TO_EXECUTE;
157         }
158
159         final String dmiPluginIdentifierValue = dmiPropertyQueryPairs.get(
160                 PropertyType.DMI_PLUGIN.getYangContainerName());
161
162         final Set<NcmpServiceCmHandle> cmHandlesByDmiPluginIdentifier = cmHandleQueries
163                 .getCmHandlesByDmiPluginIdentifier(dmiPluginIdentifierValue);
164
165         return cmHandlesByDmiPluginIdentifier.stream()
166                 .collect(Collectors.toMap(NcmpServiceCmHandle::getCmHandleId, cmH -> cmH));
167     }
168
169     private Map<String, NcmpServiceCmHandle> queryCmHandlesByPrivateProperties(
170             final CmHandleQueryServiceParameters cmHandleQueryServiceParameters) {
171
172         final Map<String, String> privatePropertyQueryPairs =
173                 getPropertyPairs(cmHandleQueryServiceParameters.getCmHandleQueryParameters(),
174                         InventoryQueryConditions.HAS_ALL_ADDITIONAL_PROPERTIES.getName());
175
176         return privatePropertyQueryPairs.isEmpty()
177                 ? NO_QUERY_TO_EXECUTE
178                 : cmHandleQueries.queryCmHandleAdditionalProperties(privatePropertyQueryPairs);
179     }
180
181     private Map<String, NcmpServiceCmHandle> queryCmHandlesByPublicProperties(
182             final CmHandleQueryServiceParameters cmHandleQueryServiceParameters) {
183
184         final Map<String, String> publicPropertyQueryPairs =
185                 getPropertyPairs(cmHandleQueryServiceParameters.getCmHandleQueryParameters(),
186                         CmHandleQueryConditions.HAS_ALL_PROPERTIES.getConditionName());
187
188         return publicPropertyQueryPairs.isEmpty()
189                 ? NO_QUERY_TO_EXECUTE
190                 : cmHandleQueries.queryCmHandlePublicProperties(publicPropertyQueryPairs);
191     }
192
193     private Map<String, NcmpServiceCmHandle> combineQueryResults(
194             final Map<String, NcmpServiceCmHandle> publicPropertiesQueryResult,
195             final Map<String, NcmpServiceCmHandle> privatePropertiesQueryResult,
196             final Map<String, NcmpServiceCmHandle> dmiPropertiesQueryResult) {
197
198         final Map<String, NcmpServiceCmHandle> propertiesCombinedResult = cmHandleQueries
199                 .combineCmHandleQueries(publicPropertiesQueryResult, privatePropertiesQueryResult);
200         return cmHandleQueries
201                 .combineCmHandleQueries(propertiesCombinedResult, dmiPropertiesQueryResult);
202     }
203
204     private Map<String, NcmpServiceCmHandle> combineWithModuleNameQuery(
205             final CmHandleQueryServiceParameters cmHandleQueryServiceParameters,
206             final Map<String, NcmpServiceCmHandle> previousQueryResult) {
207         final Collection<String> moduleNamesForQuery =
208                 getModuleNamesForQuery(cmHandleQueryServiceParameters.getCmHandleQueryParameters());
209         if (moduleNamesForQuery.isEmpty()) {
210             return previousQueryResult;
211         }
212         final Collection<String> cmHandleIdsByModuleName = getNamesOfAnchorsWithGivenModules(moduleNamesForQuery);
213         if (cmHandleIdsByModuleName.isEmpty()) {
214             return Collections.emptyMap();
215         }
216         final Map<String, NcmpServiceCmHandle> queryResult = new HashMap<>(cmHandleIdsByModuleName.size());
217         if (previousQueryResult == NO_QUERY_TO_EXECUTE) {
218             cmHandleIdsByModuleName.forEach(cmHandleId ->
219                     queryResult.put(cmHandleId, createNcmpServiceCmHandle(
220                             inventoryPersistence.getDataNode("/dmi-registry/cm-handles[@id='" + cmHandleId + "']")))
221             );
222             return queryResult;
223         }
224         previousQueryResult.keySet().retainAll(cmHandleIdsByModuleName);
225         queryResult.putAll(previousQueryResult);
226         return queryResult;
227     }
228
229     private Map<String, NcmpServiceCmHandle> executeInventoryQueries(
230             final CmHandleQueryServiceParameters cmHandleQueryServiceParameters) {
231         final Map<String, String> cpsPath = getCpsPath(cmHandleQueryServiceParameters.getCmHandleQueryParameters());
232         if (!validateCpsPathConditionProperties(cpsPath)) {
233             return Collections.emptyMap();
234         }
235         final Map<String, NcmpServiceCmHandle> cpsPathQueryResult;
236         if (cpsPath.isEmpty()) {
237             cpsPathQueryResult = NO_QUERY_TO_EXECUTE;
238         } else {
239             try {
240                 cpsPathQueryResult = cmHandleQueries.queryCmHandleDataNodesByCpsPath(
241                                 cpsPath.get("cpsPath"), INCLUDE_ALL_DESCENDANTS)
242                         .stream().map(this::createNcmpServiceCmHandle)
243                         .collect(Collectors.toMap(NcmpServiceCmHandle::getCmHandleId,
244                                 Function.identity()));
245             } catch (final PathParsingException pathParsingException) {
246                 throw new DataValidationException(pathParsingException.getMessage(), pathParsingException.getDetails(),
247                         pathParsingException);
248             }
249             if (cpsPathQueryResult.isEmpty()) {
250                 return Collections.emptyMap();
251             }
252         }
253
254         final Map<String, String> publicPropertyQueryPairs =
255                 getPropertyPairs(cmHandleQueryServiceParameters.getCmHandleQueryParameters(),
256                         CmHandleQueryConditions.HAS_ALL_PROPERTIES.getConditionName());
257         final Map<String, NcmpServiceCmHandle> propertiesQueryResult = publicPropertyQueryPairs.isEmpty()
258                 ? NO_QUERY_TO_EXECUTE : cmHandleQueries.queryCmHandlePublicProperties(publicPropertyQueryPairs);
259
260         return cmHandleQueries.combineCmHandleQueries(cpsPathQueryResult, propertiesQueryResult);
261     }
262
263     private Set<String> getNamesOfAnchorsWithGivenModules(final Collection<String> moduleNamesForQuery) {
264         final Collection<Anchor> anchors = inventoryPersistence.queryAnchors(moduleNamesForQuery);
265         return anchors.parallelStream().map(Anchor::getName).collect(Collectors.toSet());
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         return inventoryPersistence.getDataNode("/dmi-registry")
306                 .getChildDataNodes().stream().map(this::createNcmpServiceCmHandle).collect(Collectors.toSet());
307     }
308
309     private Set<String> getAllCmHandleIds() {
310         return inventoryPersistence.getDataNode("/dmi-registry", FETCH_DIRECT_CHILDREN_ONLY)
311                 .getChildDataNodes().stream().map(dataNode -> dataNode.getLeaves().get("id").toString())
312                 .collect(Collectors.toSet());
313     }
314
315     private NcmpServiceCmHandle createNcmpServiceCmHandle(final DataNode dataNode) {
316         return convertYangModelCmHandleToNcmpServiceCmHandle(YangDataConverter
317                 .convertCmHandleToYangModel(dataNode, dataNode.getLeaves().get("id").toString()));
318     }
319 }