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
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 * SPDX-License-Identifier: Apache-2.0
18 * ============LICENSE_END=========================================================
21 package org.onap.cps.ncmp.impl.inventory;
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;
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;
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;
57 @RequiredArgsConstructor
58 public class ParameterizedCmHandleQueryServiceImpl implements ParameterizedCmHandleQueryService {
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;
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);
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);
89 public Flux<NcmpServiceCmHandle> queryCmHandles(final CmHandleQueryServiceParameters queryParameters) {
90 final Collection<String> cmHandleIds = queryCmHandleReferenceIds(queryParameters, false);
91 return getNcmpServiceCmHandles(cmHandleIds);
95 public Collection<NcmpServiceCmHandle> getAllCmHandlesWithoutProperties() {
96 return toNcmpServiceCmHandles(inventoryPersistence.getDataNode(NCMP_DMI_REGISTRY_PARENT, DIRECT_CHILDREN_ONLY));
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());
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;
113 final String dmiPluginIdentifierValue = dmiPropertyQueryPairs
114 .get(PropertyType.DMI_PLUGIN.getYangContainerName());
116 return cmHandleQueryService.getCmHandleReferencesByDmiPluginIdentifier(
117 dmiPluginIdentifierValue, outputAlternateId);
121 private Collection<String> queryCmHandlesByPrivateProperties(
122 final CmHandleQueryServiceParameters cmHandleQueryServiceParameters, final boolean outputAlternateId) {
124 final Map<String, String> privatePropertyQueryPairs =
125 getPropertyPairs(cmHandleQueryServiceParameters.getCmHandleQueryParameters(),
126 InventoryQueryConditions.HAS_ALL_ADDITIONAL_PROPERTIES.getName());
128 if (privatePropertyQueryPairs.isEmpty()) {
129 return NO_QUERY_TO_EXECUTE;
131 return cmHandleQueryService.queryCmHandleAdditionalProperties(privatePropertyQueryPairs, outputAlternateId);
134 private Collection<String> queryCmHandlesByPublicProperties(
135 final CmHandleQueryServiceParameters cmHandleQueryServiceParameters, final boolean outputAlternateId) {
137 final Map<String, String> publicPropertyQueryPairs =
138 getPropertyPairs(cmHandleQueryServiceParameters.getCmHandleQueryParameters(),
139 HAS_ALL_PROPERTIES.getConditionName());
141 if (publicPropertyQueryPairs.isEmpty()) {
142 return NO_QUERY_TO_EXECUTE;
144 return cmHandleQueryService.queryCmHandlePublicProperties(publicPropertyQueryPairs, outputAlternateId);
147 private Collection<String> queryCmHandlesByTrustLevel(final CmHandleQueryServiceParameters
148 cmHandleQueryServiceParameters,
149 final boolean outputAlternateId) {
151 final Map<String, String> trustLevelPropertyQueryPairs =
152 getPropertyPairs(cmHandleQueryServiceParameters.getCmHandleQueryParameters(),
153 WITH_TRUST_LEVEL.getConditionName());
155 if (trustLevelPropertyQueryPairs.isEmpty()) {
156 return NO_QUERY_TO_EXECUTE;
158 return cmHandleQueryService.queryCmHandlesByTrustLevel(trustLevelPropertyQueryPairs, outputAlternateId);
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;
168 return inventoryPersistence.getCmHandleReferencesWithGivenModules(moduleNamesForQuery, outputAlternateId);
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();
178 final Collection<String> cpsPathQueryResult;
179 if (cpsPathCondition.isEmpty()) {
180 return NO_QUERY_TO_EXECUTE;
183 cpsPathQueryResult = cmHandleQueryService.getCmHandleReferencesByCpsPath(cpsPathCondition.get("cpsPath"),
185 } catch (final PathParsingException pathParsingException) {
186 throw new DataValidationException(pathParsingException.getMessage(), pathParsingException.getDetails(),
187 pathParsingException);
189 return cpsPathQueryResult;
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"));
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);
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);
215 private List<Map<String, String>> getConditions(final List<ConditionProperties> conditionProperties,
217 for (final ConditionProperties conditionProperty : conditionProperties) {
218 if (conditionProperty.getConditionName().equals(name)) {
219 return conditionProperty.getConditionParameters();
222 return Collections.emptyList();
225 private Collection<String> getAllCmHandleReferences(final boolean outputAlternateId) {
226 return cmHandleQueryService.getAllCmHandleReferences(outputAlternateId);
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);
236 private Collection<NcmpServiceCmHandle> getNcmpServiceCmHandleBatch(final Collection<String> cmHandleIds) {
237 final Collection<YangModelCmHandle> yangModelcmHandles
238 = inventoryPersistence.getYangModelCmHandles(cmHandleIds);
240 final Collection<NcmpServiceCmHandle> ncmpServiceCmHandles = new ArrayList<>(yangModelcmHandles.size());
242 yangModelcmHandles.forEach(yangModelcmHandle ->
243 ncmpServiceCmHandles.add(YangDataConverter.toNcmpServiceCmHandle(yangModelcmHandle))
245 trustLevelManager.applyEffectiveTrustLevels(ncmpServiceCmHandles);
246 return ncmpServiceCmHandles;
249 private NcmpServiceCmHandle createNcmpServiceCmHandle(final DataNode dataNode) {
250 return toNcmpServiceCmHandle(YangDataConverter.toYangModelCmHandle(dataNode));
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);
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,
265 if (noEntriesFoundCanStopQuerying(queryResult)) {
266 return Collections.emptySet();
268 combinedQueryResult = combineCmHandleQueryResults(combinedQueryResult, queryResult);
270 return combinedQueryResult;
273 private boolean noEntriesFoundCanStopQuerying(final Collection<String> queryResult) {
274 return queryResult != NO_QUERY_TO_EXECUTE && queryResult.isEmpty();
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) {
283 } else if (secondQuery == NO_QUERY_TO_EXECUTE) {
286 firstQuery.retainAll(secondQuery);