bafb06578e34e081a9c214dd52a6fa0c7062d11c
[cps.git] /
1 /*
2  *  ============LICENSE_START=======================================================
3  *  Copyright (C) 2022-2025 OpenInfra Foundation Europe. All rights reserved.
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.impl.inventory;
22
23 import static org.onap.cps.api.parameters.FetchDescendantsOption.DIRECT_CHILDREN_ONLY;
24 import static org.onap.cps.ncmp.impl.inventory.CmHandleQueryParametersValidator.validateCpsPathConditionProperties;
25 import static org.onap.cps.ncmp.impl.inventory.CmHandleQueryParametersValidator.validateModuleNameConditionProperties;
26 import static org.onap.cps.ncmp.impl.inventory.NcmpPersistence.NCMP_DMI_REGISTRY_PARENT;
27 import static org.onap.cps.ncmp.impl.inventory.models.CmHandleQueryConditions.HAS_ALL_MODULES;
28 import static org.onap.cps.ncmp.impl.inventory.models.CmHandleQueryConditions.HAS_ALL_PROPERTIES;
29 import static org.onap.cps.ncmp.impl.inventory.models.CmHandleQueryConditions.WITH_CPS_PATH;
30 import static org.onap.cps.ncmp.impl.inventory.models.CmHandleQueryConditions.WITH_TRUST_LEVEL;
31 import static org.onap.cps.ncmp.impl.utils.YangDataConverter.toNcmpServiceCmHandle;
32
33 import java.util.ArrayList;
34 import java.util.Collection;
35 import java.util.Collections;
36 import java.util.HashMap;
37 import java.util.List;
38 import java.util.Map;
39 import java.util.function.BiFunction;
40 import java.util.stream.Collectors;
41 import lombok.RequiredArgsConstructor;
42 import org.onap.cps.api.exceptions.DataValidationException;
43 import org.onap.cps.api.model.ConditionProperties;
44 import org.onap.cps.api.model.DataNode;
45 import org.onap.cps.cpspath.parser.PathParsingException;
46 import org.onap.cps.ncmp.api.inventory.models.CmHandleQueryServiceParameters;
47 import org.onap.cps.ncmp.api.inventory.models.NcmpServiceCmHandle;
48 import org.onap.cps.ncmp.impl.inventory.models.InventoryQueryConditions;
49 import org.onap.cps.ncmp.impl.inventory.models.PropertyType;
50 import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle;
51 import org.onap.cps.ncmp.impl.inventory.trustlevel.TrustLevelManager;
52 import org.onap.cps.ncmp.impl.utils.YangDataConverter;
53 import org.springframework.stereotype.Service;
54 import reactor.core.publisher.Flux;
55
56 @Service
57 @RequiredArgsConstructor
58 public class ParameterizedCmHandleQueryServiceImpl implements ParameterizedCmHandleQueryService {
59
60     private static final int FLUX_BUFFER_SIZE = 1000;
61     private static final Collection<String> NO_QUERY_TO_EXECUTE = null;
62     private final CmHandleQueryService cmHandleQueryService;
63     private final InventoryPersistence inventoryPersistence;
64     private final TrustLevelManager trustLevelManager;
65
66     @Override
67     public Collection<String> queryCmHandleReferenceIds(
68             final CmHandleQueryServiceParameters cmHandleQueryServiceParameters,
69             final boolean outputAlternateId) {
70         return executeQueries(cmHandleQueryServiceParameters, outputAlternateId,
71                 this::executeCpsPathQuery,
72                 this::queryCmHandlesByPublicProperties,
73                 this::executeModuleNameQuery,
74                 this::queryCmHandlesByTrustLevel);
75     }
76
77     @Override
78     public Collection<String> queryCmHandleIdsForInventory(
79             final CmHandleQueryServiceParameters cmHandleQueryServiceParameters,
80             final boolean outputAlternateId) {
81         return executeQueries(cmHandleQueryServiceParameters, outputAlternateId,
82                 this::executeCpsPathQuery,
83                 this::queryCmHandlesByPublicProperties,
84                 this::queryCmHandlesByPrivateProperties,
85                 this::queryCmHandlesByDmiPlugin);
86     }
87
88     @Override
89     public Flux<NcmpServiceCmHandle> queryCmHandles(final CmHandleQueryServiceParameters queryParameters) {
90         final Collection<String> cmHandleIds = queryCmHandleReferenceIds(queryParameters, false);
91         return getNcmpServiceCmHandles(cmHandleIds);
92     }
93
94     @Override
95     public Collection<NcmpServiceCmHandle> getAllCmHandlesWithoutProperties() {
96         return toNcmpServiceCmHandles(inventoryPersistence.getDataNode(NCMP_DMI_REGISTRY_PARENT, DIRECT_CHILDREN_ONLY));
97     }
98
99     private Collection<NcmpServiceCmHandle> toNcmpServiceCmHandles(final Collection<DataNode> dataNodes) {
100         final DataNode dataNode = dataNodes.iterator().next();
101         return dataNode.getChildDataNodes().stream().map(this::createNcmpServiceCmHandle).collect(Collectors.toSet());
102     }
103
104     private Collection<String> queryCmHandlesByDmiPlugin(
105             final CmHandleQueryServiceParameters cmHandleQueryServiceParameters, final boolean outputAlternateId) {
106         final Map<String, String> dmiPropertyQueryPairs =
107                 getPropertyPairs(cmHandleQueryServiceParameters.getCmHandleQueryParameters(),
108                         InventoryQueryConditions.CM_HANDLE_WITH_DMI_PLUGIN.getName());
109         if (dmiPropertyQueryPairs.isEmpty()) {
110             return NO_QUERY_TO_EXECUTE;
111         }
112
113         final String dmiPluginIdentifierValue = dmiPropertyQueryPairs
114                 .get(PropertyType.DMI_PLUGIN.getYangContainerName());
115
116         return cmHandleQueryService.getCmHandleReferencesByDmiPluginIdentifier(
117                 dmiPluginIdentifierValue, outputAlternateId);
118
119     }
120
121     private Collection<String> queryCmHandlesByPrivateProperties(
122             final CmHandleQueryServiceParameters cmHandleQueryServiceParameters, final boolean outputAlternateId) {
123
124         final Map<String, String> privatePropertyQueryPairs =
125                 getPropertyPairs(cmHandleQueryServiceParameters.getCmHandleQueryParameters(),
126                         InventoryQueryConditions.HAS_ALL_ADDITIONAL_PROPERTIES.getName());
127
128         if (privatePropertyQueryPairs.isEmpty()) {
129             return NO_QUERY_TO_EXECUTE;
130         }
131         return cmHandleQueryService.queryCmHandleAdditionalProperties(privatePropertyQueryPairs, outputAlternateId);
132     }
133
134     private Collection<String> queryCmHandlesByPublicProperties(
135             final CmHandleQueryServiceParameters cmHandleQueryServiceParameters, final boolean outputAlternateId) {
136
137         final Map<String, String> publicPropertyQueryPairs =
138                 getPropertyPairs(cmHandleQueryServiceParameters.getCmHandleQueryParameters(),
139                         HAS_ALL_PROPERTIES.getConditionName());
140
141         if (publicPropertyQueryPairs.isEmpty()) {
142             return NO_QUERY_TO_EXECUTE;
143         }
144         return cmHandleQueryService.queryCmHandlePublicProperties(publicPropertyQueryPairs, outputAlternateId);
145     }
146
147     private Collection<String> queryCmHandlesByTrustLevel(final CmHandleQueryServiceParameters
148                                                                   cmHandleQueryServiceParameters,
149                                                           final boolean outputAlternateId) {
150
151         final Map<String, String> trustLevelPropertyQueryPairs =
152                 getPropertyPairs(cmHandleQueryServiceParameters.getCmHandleQueryParameters(),
153                         WITH_TRUST_LEVEL.getConditionName());
154
155         if (trustLevelPropertyQueryPairs.isEmpty()) {
156             return NO_QUERY_TO_EXECUTE;
157         }
158         return cmHandleQueryService.queryCmHandlesByTrustLevel(trustLevelPropertyQueryPairs, outputAlternateId);
159     }
160
161     private Collection<String> executeModuleNameQuery(
162             final CmHandleQueryServiceParameters cmHandleQueryServiceParameters, final boolean outputAlternateId) {
163         final Collection<String> moduleNamesForQuery =
164                 getModuleNamesForQuery(cmHandleQueryServiceParameters.getCmHandleQueryParameters());
165         if (moduleNamesForQuery.isEmpty()) {
166             return NO_QUERY_TO_EXECUTE;
167         }
168         return inventoryPersistence.getCmHandleReferencesWithGivenModules(moduleNamesForQuery, outputAlternateId);
169     }
170
171     private Collection<String> executeCpsPathQuery(
172             final CmHandleQueryServiceParameters cmHandleQueryServiceParameters, final boolean outputAlternateId) {
173         final Map<String, String> cpsPathCondition
174                 = getCpsPathCondition(cmHandleQueryServiceParameters.getCmHandleQueryParameters());
175         if (!validateCpsPathConditionProperties(cpsPathCondition)) {
176             return Collections.emptySet();
177         }
178         final Collection<String> cpsPathQueryResult;
179         if (cpsPathCondition.isEmpty()) {
180             return NO_QUERY_TO_EXECUTE;
181         }
182         try {
183             cpsPathQueryResult = cmHandleQueryService.getCmHandleReferencesByCpsPath(cpsPathCondition.get("cpsPath"),
184                     outputAlternateId);
185         } catch (final PathParsingException pathParsingException) {
186             throw new DataValidationException(pathParsingException.getMessage(), pathParsingException.getDetails(),
187                     pathParsingException);
188         }
189         return cpsPathQueryResult;
190     }
191
192     private Collection<String> getModuleNamesForQuery(final List<ConditionProperties> conditionProperties) {
193         final List<String> result = new ArrayList<>();
194         getConditions(conditionProperties, HAS_ALL_MODULES.getConditionName()).forEach(
195                 conditionProperty -> {
196                     validateModuleNameConditionProperties(conditionProperty);
197                     result.add(conditionProperty.get("moduleName"));
198                 });
199         return result;
200     }
201
202     private Map<String, String> getCpsPathCondition(final List<ConditionProperties> conditionProperties) {
203         final Map<String, String> result = new HashMap<>();
204         getConditions(conditionProperties, WITH_CPS_PATH.getConditionName()).forEach(result::putAll);
205         return result;
206     }
207
208     private Map<String, String> getPropertyPairs(final List<ConditionProperties> conditionProperties,
209                                                  final String queryProperty) {
210         final Map<String, String> result = new HashMap<>();
211         getConditions(conditionProperties, queryProperty).forEach(result::putAll);
212         return result;
213     }
214
215     private List<Map<String, String>> getConditions(final List<ConditionProperties> conditionProperties,
216                                                     final String name) {
217         for (final ConditionProperties conditionProperty : conditionProperties) {
218             if (conditionProperty.getConditionName().equals(name)) {
219                 return conditionProperty.getConditionParameters();
220             }
221         }
222         return Collections.emptyList();
223     }
224
225     private Collection<String> getAllCmHandleReferences(final boolean outputAlternateId) {
226         return cmHandleQueryService.getAllCmHandleReferences(outputAlternateId);
227     }
228
229     private Flux<NcmpServiceCmHandle> getNcmpServiceCmHandles(final Collection<String> cmHandleIds) {
230         return Flux.fromIterable(cmHandleIds)
231                 .buffer(FLUX_BUFFER_SIZE)
232                 .map(this::getNcmpServiceCmHandleBatch)
233                 .flatMap(Flux::fromIterable);
234     }
235
236     private Collection<NcmpServiceCmHandle> getNcmpServiceCmHandleBatch(final Collection<String> cmHandleIds) {
237         final Collection<YangModelCmHandle> yangModelcmHandles
238                 = inventoryPersistence.getYangModelCmHandles(cmHandleIds);
239
240         final Collection<NcmpServiceCmHandle> ncmpServiceCmHandles = new ArrayList<>(yangModelcmHandles.size());
241
242         yangModelcmHandles.forEach(yangModelcmHandle ->
243                 ncmpServiceCmHandles.add(YangDataConverter.toNcmpServiceCmHandle(yangModelcmHandle))
244         );
245         trustLevelManager.applyEffectiveTrustLevels(ncmpServiceCmHandles);
246         return ncmpServiceCmHandles;
247     }
248
249     private NcmpServiceCmHandle createNcmpServiceCmHandle(final DataNode dataNode) {
250         return toNcmpServiceCmHandle(YangDataConverter.toYangModelCmHandle(dataNode));
251     }
252
253     private Collection<String> executeQueries(final CmHandleQueryServiceParameters cmHandleQueryServiceParameters,
254                                               final boolean outputAlternateId,
255                                               final BiFunction<CmHandleQueryServiceParameters, Boolean,
256                                                       Collection<String>>... queryFunctions) {
257         if (cmHandleQueryServiceParameters.getCmHandleQueryParameters().isEmpty()) {
258             return getAllCmHandleReferences(outputAlternateId);
259         }
260         Collection<String> combinedQueryResult = NO_QUERY_TO_EXECUTE;
261         for (final BiFunction<CmHandleQueryServiceParameters, Boolean,
262                 Collection<String>> queryFunction : queryFunctions) {
263             final Collection<String> queryResult = queryFunction.apply(cmHandleQueryServiceParameters,
264                     outputAlternateId);
265             if (noEntriesFoundCanStopQuerying(queryResult)) {
266                 return Collections.emptySet();
267             }
268             combinedQueryResult = combineCmHandleQueryResults(combinedQueryResult, queryResult);
269         }
270         return combinedQueryResult;
271     }
272
273     private boolean noEntriesFoundCanStopQuerying(final Collection<String> queryResult) {
274         return queryResult != NO_QUERY_TO_EXECUTE && queryResult.isEmpty();
275     }
276
277     private Collection<String> combineCmHandleQueryResults(final Collection<String> firstQuery,
278                                                            final Collection<String> secondQuery) {
279         if (firstQuery == NO_QUERY_TO_EXECUTE && secondQuery == NO_QUERY_TO_EXECUTE) {
280             return NO_QUERY_TO_EXECUTE;
281         } else if (firstQuery == NO_QUERY_TO_EXECUTE) {
282             return secondQuery;
283         } else if (secondQuery == NO_QUERY_TO_EXECUTE) {
284             return firstQuery;
285         } else {
286             firstQuery.retainAll(secondQuery);
287             return firstQuery;
288         }
289     }
290
291 }