Incorrect response to {} for cmhandle id-searches
[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.YangDataConverter.convertYangModelCmHandleToNcmpServiceCmHandle;
24 import static org.onap.cps.spi.FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS;
25 import static org.onap.cps.utils.CmHandleQueryRestParametersValidator.validateCpsPathConditionProperties;
26 import static org.onap.cps.utils.CmHandleQueryRestParametersValidator.validateModuleNameConditionProperties;
27
28 import java.util.ArrayList;
29 import java.util.Collection;
30 import java.util.Collections;
31 import java.util.HashMap;
32 import java.util.HashSet;
33 import java.util.List;
34 import java.util.Map;
35 import java.util.Set;
36 import java.util.function.Function;
37 import java.util.stream.Collectors;
38 import lombok.RequiredArgsConstructor;
39 import lombok.extern.slf4j.Slf4j;
40 import org.onap.cps.cpspath.parser.PathParsingException;
41 import org.onap.cps.ncmp.api.NetworkCmProxyCmHandlerQueryService;
42 import org.onap.cps.ncmp.api.impl.utils.YangDataConverter;
43 import org.onap.cps.ncmp.api.inventory.CmHandleQueries;
44 import org.onap.cps.ncmp.api.inventory.InventoryPersistence;
45 import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle;
46 import org.onap.cps.spi.exceptions.DataValidationException;
47 import org.onap.cps.spi.model.Anchor;
48 import org.onap.cps.spi.model.CmHandleQueryServiceParameters;
49 import org.onap.cps.spi.model.ConditionProperties;
50 import org.onap.cps.spi.model.DataNode;
51 import org.onap.cps.utils.ValidQueryProperties;
52 import org.springframework.stereotype.Service;
53
54 @Service
55 @Slf4j
56 @RequiredArgsConstructor
57 public class NetworkCmProxyCmHandlerQueryServiceImpl implements NetworkCmProxyCmHandlerQueryService {
58
59     private static final Map<String, NcmpServiceCmHandle> NO_QUERY_TO_EXECUTE = null;
60     private final CmHandleQueries cmHandleQueries;
61     private final InventoryPersistence inventoryPersistence;
62
63     /**
64      * Query and return cm handles that match the given query parameters.
65      *
66      * @param cmHandleQueryServiceParameters the cm handle query parameters
67      * @return collection of cm handles
68      */
69     @Override
70     public Set<NcmpServiceCmHandle> queryCmHandles(
71         final CmHandleQueryServiceParameters cmHandleQueryServiceParameters) {
72
73         if (cmHandleQueryServiceParameters.getCmHandleQueryParameters().isEmpty()) {
74             return getAllCmHandles();
75         }
76
77         final Map<String, NcmpServiceCmHandle> combinedQueryResult = executeInventoryQueries(
78             cmHandleQueryServiceParameters);
79
80         return new HashSet<>(combineWithModuleNameQuery(cmHandleQueryServiceParameters, combinedQueryResult).values());
81     }
82
83     /**
84      * Query and return cm handles that match the given query parameters.
85      *
86      * @param cmHandleQueryServiceParameters the cm handle query parameters
87      * @return collection of cm handle ids
88      */
89     @Override
90     public Set<String> queryCmHandleIds(
91         final CmHandleQueryServiceParameters cmHandleQueryServiceParameters) {
92
93         if (cmHandleQueryServiceParameters.getCmHandleQueryParameters().isEmpty()) {
94             return getAllCmHandleIds();
95         }
96
97         final Map<String, NcmpServiceCmHandle> combinedQueryResult = executeInventoryQueries(
98             cmHandleQueryServiceParameters);
99
100         final Collection<String> moduleNamesForQuery =
101             getModuleNamesForQuery(cmHandleQueryServiceParameters.getCmHandleQueryParameters());
102         if (moduleNamesForQuery.isEmpty()) {
103             return combinedQueryResult.keySet();
104         }
105         final Set<String> moduleNameQueryResult = getNamesOfAnchorsWithGivenModules(moduleNamesForQuery);
106
107         if (combinedQueryResult == NO_QUERY_TO_EXECUTE) {
108             return moduleNameQueryResult;
109         }
110
111         moduleNameQueryResult.retainAll(combinedQueryResult.keySet());
112         return moduleNameQueryResult;
113     }
114
115     private Map<String, NcmpServiceCmHandle> combineWithModuleNameQuery(
116         final CmHandleQueryServiceParameters cmHandleQueryServiceParameters,
117         final Map<String, NcmpServiceCmHandle> previousQueryResult) {
118         final Collection<String> moduleNamesForQuery =
119             getModuleNamesForQuery(cmHandleQueryServiceParameters.getCmHandleQueryParameters());
120         if (moduleNamesForQuery.isEmpty()) {
121             return previousQueryResult;
122         }
123         final Collection<String> cmHandleIdsByModuleName = getNamesOfAnchorsWithGivenModules(moduleNamesForQuery);
124         if (cmHandleIdsByModuleName.isEmpty()) {
125             return Collections.emptyMap();
126         }
127         final Map<String, NcmpServiceCmHandle> queryResult = new HashMap<>(cmHandleIdsByModuleName.size());
128         if (previousQueryResult == NO_QUERY_TO_EXECUTE) {
129             cmHandleIdsByModuleName.forEach(cmHandleId ->
130                     queryResult.put(cmHandleId, createNcmpServiceCmHandle(
131                             inventoryPersistence.getDataNode("/dmi-registry/cm-handles[@id='" + cmHandleId + "']")))
132             );
133             return queryResult;
134         }
135         previousQueryResult.keySet().retainAll(cmHandleIdsByModuleName);
136         queryResult.putAll(previousQueryResult);
137         return queryResult;
138     }
139
140     private Map<String, NcmpServiceCmHandle> executeInventoryQueries(
141         final CmHandleQueryServiceParameters cmHandleQueryServiceParameters) {
142         final Map<String, String> cpsPath = getCpsPath(cmHandleQueryServiceParameters.getCmHandleQueryParameters());
143         if (!validateCpsPathConditionProperties(cpsPath)) {
144             return Collections.emptyMap();
145         }
146         final Map<String, NcmpServiceCmHandle> cpsPathQueryResult;
147         if (cpsPath.isEmpty()) {
148             cpsPathQueryResult = NO_QUERY_TO_EXECUTE;
149         } else {
150             try {
151                 cpsPathQueryResult = cmHandleQueries.getCmHandleDataNodesByCpsPath(
152                     cpsPath.get("cpsPath"), INCLUDE_ALL_DESCENDANTS)
153                     .stream().map(this::createNcmpServiceCmHandle)
154                     .collect(Collectors.toMap(NcmpServiceCmHandle::getCmHandleId,
155                         Function.identity()));
156             } catch (final PathParsingException pathParsingException) {
157                 throw new DataValidationException(pathParsingException.getMessage(), pathParsingException.getDetails(),
158                     pathParsingException);
159             }
160             if (cpsPathQueryResult.isEmpty()) {
161                 return Collections.emptyMap();
162             }
163         }
164
165         final Map<String, String> publicPropertyQueryPairs =
166             getPublicPropertyPairs(cmHandleQueryServiceParameters.getCmHandleQueryParameters());
167         final Map<String, NcmpServiceCmHandle> propertiesQueryResult = publicPropertyQueryPairs.isEmpty()
168             ? NO_QUERY_TO_EXECUTE : cmHandleQueries.queryCmHandlePublicProperties(publicPropertyQueryPairs);
169
170         return cmHandleQueries.combineCmHandleQueries(cpsPathQueryResult, propertiesQueryResult);
171     }
172
173     private Set<String> getNamesOfAnchorsWithGivenModules(final Collection<String> moduleNamesForQuery) {
174         final Collection<Anchor> anchors = inventoryPersistence.queryAnchors(moduleNamesForQuery);
175         return anchors.parallelStream().map(Anchor::getName).collect(Collectors.toSet());
176     }
177
178     private Collection<String> getModuleNamesForQuery(final List<ConditionProperties> conditionProperties) {
179         final List<String> result = new ArrayList<>();
180         getConditions(conditionProperties, ValidQueryProperties.HAS_ALL_MODULES.getQueryProperty())
181             .parallelStream().forEach(
182                 conditionProperty -> {
183                     validateModuleNameConditionProperties(conditionProperty);
184                     result.add(conditionProperty.get("moduleName"));
185                 }
186             );
187         return result;
188     }
189
190     private Map<String, String> getCpsPath(final List<ConditionProperties> conditionProperties) {
191         final Map<String, String> result = new HashMap<>();
192         getConditions(conditionProperties, ValidQueryProperties.WITH_CPS_PATH.getQueryProperty()).forEach(
193             result::putAll);
194         return result;
195     }
196
197     private Map<String, String> getPublicPropertyPairs(final List<ConditionProperties> conditionProperties) {
198         final Map<String, String> result = new HashMap<>();
199         getConditions(conditionProperties,
200             ValidQueryProperties.HAS_ALL_PROPERTIES.getQueryProperty()).forEach(result::putAll);
201         return result;
202     }
203
204     private List<Map<String, String>> getConditions(final List<ConditionProperties> conditionProperties,
205                                                     final String name) {
206         for (final ConditionProperties conditionProperty : conditionProperties) {
207             if (conditionProperty.getConditionName().equals(name)) {
208                 return conditionProperty.getConditionParameters();
209             }
210         }
211         return Collections.emptyList();
212     }
213
214     private Set<NcmpServiceCmHandle> getAllCmHandles() {
215         return inventoryPersistence.getDataNode("/dmi-registry")
216             .getChildDataNodes().stream().map(this::createNcmpServiceCmHandle).collect(Collectors.toSet());
217     }
218
219     private Set<String> getAllCmHandleIds() {
220         return inventoryPersistence.getDataNode("/dmi-registry")
221             .getChildDataNodes().stream().map(dataNode -> dataNode.getLeaves().get("id").toString())
222             .collect(Collectors.toSet());
223     }
224
225     private NcmpServiceCmHandle createNcmpServiceCmHandle(final DataNode dataNode) {
226         return convertYangModelCmHandleToNcmpServiceCmHandle(YangDataConverter
227             .convertCmHandleToYangModel(dataNode, dataNode.getLeaves().get("id").toString()));
228     }
229 }