Define Initial Data Sync Enabled Flag and state
[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.constants.DmiRegistryConstants.NCMP_DATASPACE_NAME;
24 import static org.onap.cps.ncmp.api.impl.constants.DmiRegistryConstants.NCMP_DMI_REGISTRY_ANCHOR;
25 import static org.onap.cps.ncmp.api.impl.utils.YangDataConverter.convertYangModelCmHandleToNcmpServiceCmHandle;
26 import static org.onap.cps.spi.FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS;
27 import static org.onap.cps.utils.CmHandleQueryRestParametersValidator.validateModuleNameConditionProperties;
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.stream.Collectors;
38 import lombok.RequiredArgsConstructor;
39 import lombok.extern.slf4j.Slf4j;
40 import org.onap.cps.ncmp.api.NetworkCmProxyCmHandlerQueryService;
41 import org.onap.cps.ncmp.api.impl.utils.YangDataConverter;
42 import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle;
43 import org.onap.cps.spi.CpsAdminPersistenceService;
44 import org.onap.cps.spi.CpsDataPersistenceService;
45 import org.onap.cps.spi.model.Anchor;
46 import org.onap.cps.spi.model.CmHandleQueryServiceParameters;
47 import org.onap.cps.spi.model.ConditionProperties;
48 import org.onap.cps.spi.model.DataNode;
49 import org.springframework.stereotype.Service;
50
51 @Service
52 @Slf4j
53 @RequiredArgsConstructor
54 public class NetworkCmProxyCmHandlerQueryServiceImpl implements NetworkCmProxyCmHandlerQueryService {
55
56     private static final String PROPERTY_QUERY_NAME = "hasAllProperties";
57     private static final String MODULE_QUERY_NAME = "hasAllModules";
58     private static final Map<String, NcmpServiceCmHandle> NO_QUERY_EXECUTED = null;
59     private final CpsDataPersistenceService cpsDataPersistenceService;
60     private final CpsAdminPersistenceService cpsAdminPersistenceService;
61
62     /**
63      * Query and return cm handles that match the given query parameters.
64      *
65      * @param cmHandleQueryServiceParameters the cm handle query parameters
66      * @return collection of cm handles
67      */
68     @Override
69     public Set<NcmpServiceCmHandle> queryCmHandles(
70         final CmHandleQueryServiceParameters cmHandleQueryServiceParameters) {
71
72         if (cmHandleQueryServiceParameters.getCmHandleQueryParameters().isEmpty()) {
73             return getAllCmHandles();
74         }
75
76         final Map<String, NcmpServiceCmHandle> publicPropertyQueryResult
77             = executePublicPropertyQueries(cmHandleQueryServiceParameters);
78
79         final Map<String, NcmpServiceCmHandle> combinedQueryResult =
80             combineWithModuleNameQuery(cmHandleQueryServiceParameters, publicPropertyQueryResult);
81
82         return combinedQueryResult == NO_QUERY_EXECUTED
83             ? Collections.emptySet() : new HashSet<>(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> publicPropertyQueryResult
101             = executePublicPropertyQueries(cmHandleQueryServiceParameters);
102
103         final Collection<String> moduleNamesForQuery =
104             getModuleNamesForQuery(cmHandleQueryServiceParameters.getCmHandleQueryParameters());
105         if (moduleNamesForQuery.isEmpty()) {
106             return publicPropertyQueryResult == NO_QUERY_EXECUTED
107                 ? Collections.emptySet() : publicPropertyQueryResult.keySet();
108         }
109         final Set<String> moduleNameQueryResult = getNamesOfAnchorsWithGivenModules(moduleNamesForQuery);
110
111         if (publicPropertyQueryResult == NO_QUERY_EXECUTED) {
112             return moduleNameQueryResult;
113         }
114
115         moduleNameQueryResult.retainAll(publicPropertyQueryResult.keySet());
116         return moduleNameQueryResult;
117     }
118
119     private Map<String, NcmpServiceCmHandle> executePublicPropertyQueries(
120         final CmHandleQueryServiceParameters cmHandleQueryServiceParameters) {
121         final Map<String, String> publicPropertyQueryPairs =
122             getPublicPropertyPairs(cmHandleQueryServiceParameters.getCmHandleQueryParameters());
123         if (publicPropertyQueryPairs.isEmpty()) {
124             return NO_QUERY_EXECUTED;
125         }
126         Map<String, NcmpServiceCmHandle> cmHandleIdToNcmpServiceCmHandles = null;
127         for (final Map.Entry<String, String> entry : publicPropertyQueryPairs.entrySet()) {
128             final String cpsPath = "//public-properties[@name='" + entry.getKey() + "' and @value='"
129                 + entry.getValue() + "']/ancestor::cm-handles";
130
131             final Collection<DataNode> dataNodes = queryDataNodes(cpsPath);
132             if (cmHandleIdToNcmpServiceCmHandles == NO_QUERY_EXECUTED) {
133                 cmHandleIdToNcmpServiceCmHandles = collectDataNodesToNcmpServiceCmHandles(dataNodes);
134             } else {
135                 final Collection<String> cmHandleIdsToRetain = dataNodes.parallelStream()
136                     .map(dataNode -> dataNode.getLeaves().get("id").toString()).collect(Collectors.toSet());
137                 cmHandleIdToNcmpServiceCmHandles.keySet().retainAll(cmHandleIdsToRetain);
138             }
139             if (cmHandleIdToNcmpServiceCmHandles.isEmpty()) {
140                 break;
141             }
142         }
143         return cmHandleIdToNcmpServiceCmHandles;
144     }
145
146     private Map<String, NcmpServiceCmHandle> combineWithModuleNameQuery(
147         final CmHandleQueryServiceParameters cmHandleQueryServiceParameters,
148         final Map<String, NcmpServiceCmHandle> previousQueryResult) {
149         final Collection<String> moduleNamesForQuery =
150             getModuleNamesForQuery(cmHandleQueryServiceParameters.getCmHandleQueryParameters());
151         if (moduleNamesForQuery.isEmpty()) {
152             return previousQueryResult;
153         }
154         final Collection<String> cmHandleIdsByModuleName = getNamesOfAnchorsWithGivenModules(moduleNamesForQuery);
155         if (cmHandleIdsByModuleName.isEmpty()) {
156             return Collections.emptyMap();
157         }
158         final Map<String, NcmpServiceCmHandle> queryResult = new HashMap<>(cmHandleIdsByModuleName.size());
159         if (previousQueryResult == NO_QUERY_EXECUTED) {
160             cmHandleIdsByModuleName.forEach(cmHandleId ->
161                     queryResult.put(cmHandleId, createNcmpServiceCmHandle(
162                             getDataNode("/dmi-registry/cm-handles[@id='" + cmHandleId + "']")))
163             );
164             return queryResult;
165         }
166         previousQueryResult.keySet().retainAll(cmHandleIdsByModuleName);
167         queryResult.putAll(previousQueryResult);
168         return queryResult;
169     }
170
171     private Set<String> getNamesOfAnchorsWithGivenModules(final Collection<String> moduleNamesForQuery) {
172         final Collection<Anchor> anchors =
173             cpsAdminPersistenceService.queryAnchors("NFP-Operational", moduleNamesForQuery);
174         return anchors.parallelStream().map(Anchor::getName).collect(Collectors.toSet());
175     }
176
177     private Map<String, NcmpServiceCmHandle> collectDataNodesToNcmpServiceCmHandles(
178         final Collection<DataNode> dataNodes) {
179         final Map<String, NcmpServiceCmHandle> cmHandleIdToNcmpServiceCmHandle = new HashMap<>();
180         dataNodes.forEach(dataNode -> {
181             final NcmpServiceCmHandle ncmpServiceCmHandle = createNcmpServiceCmHandle(dataNode);
182             cmHandleIdToNcmpServiceCmHandle.put(ncmpServiceCmHandle.getCmHandleId(), ncmpServiceCmHandle);
183         });
184         return cmHandleIdToNcmpServiceCmHandle;
185     }
186
187     private List<Map<String, String>> getConditions(final List<ConditionProperties> conditionProperties,
188                                                     final String name) {
189         for (final ConditionProperties conditionProperty : conditionProperties) {
190             if (conditionProperty.getConditionName().equals(name)) {
191                 return conditionProperty.getConditionParameters();
192             }
193         }
194         return Collections.emptyList();
195     }
196
197     private Collection<String> getModuleNamesForQuery(final List<ConditionProperties> conditionProperties) {
198         final List<String> result = new ArrayList<>();
199         getConditions(conditionProperties, MODULE_QUERY_NAME).parallelStream().forEach(
200             conditionProperty -> {
201                 validateModuleNameConditionProperties(conditionProperty);
202                 result.add(conditionProperty.get("moduleName"));
203             }
204         );
205         return result;
206     }
207
208     private Map<String, String> getPublicPropertyPairs(final List<ConditionProperties> conditionProperties) {
209         final Map<String, String> result = new HashMap<>();
210         getConditions(conditionProperties, PROPERTY_QUERY_NAME).forEach(result::putAll);
211         return result;
212     }
213
214     private Set<NcmpServiceCmHandle> getAllCmHandles() {
215         return getDataNode("/dmi-registry").getChildDataNodes().stream()
216             .map(this::createNcmpServiceCmHandle).collect(Collectors.toSet());
217     }
218
219     private Set<String> getAllCmHandleIds() {
220         return cpsAdminPersistenceService.getAnchors("NFP-Operational")
221             .parallelStream().map(Anchor::getName).collect(Collectors.toSet());
222     }
223
224     private List<DataNode> queryDataNodes(final String cpsPath) {
225         return cpsDataPersistenceService.queryDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR,
226                 cpsPath, INCLUDE_ALL_DESCENDANTS);
227     }
228
229     private DataNode getDataNode(final String cpsPath) {
230         return cpsDataPersistenceService.getDataNode(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR,
231                 cpsPath, INCLUDE_ALL_DESCENDANTS);
232     }
233
234     private NcmpServiceCmHandle createNcmpServiceCmHandle(final DataNode dataNode) {
235         return convertYangModelCmHandleToNcmpServiceCmHandle(YangDataConverter
236             .convertCmHandleToYangModel(dataNode, dataNode.getLeaves().get("id").toString()));
237     }
238 }