Merge "Eliminate cmhandle-properties tag"
[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.spi.FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS;
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.List;
33 import java.util.Map;
34 import java.util.stream.Collectors;
35 import lombok.RequiredArgsConstructor;
36 import lombok.extern.slf4j.Slf4j;
37 import org.onap.cps.ncmp.api.NetworkCmProxyCmHandlerQueryService;
38 import org.onap.cps.spi.CpsAdminPersistenceService;
39 import org.onap.cps.spi.CpsDataPersistenceService;
40 import org.onap.cps.spi.model.Anchor;
41 import org.onap.cps.spi.model.CmHandleQueryServiceParameters;
42 import org.onap.cps.spi.model.ConditionProperties;
43 import org.onap.cps.spi.model.DataNode;
44 import org.onap.cps.spi.model.DataNodeIdentifier;
45 import org.onap.cps.utils.JsonObjectMapper;
46 import org.springframework.stereotype.Service;
47
48 @Service
49 @Slf4j
50 @RequiredArgsConstructor
51 public class NetworkCmProxyCmHandlerQueryServiceImpl implements NetworkCmProxyCmHandlerQueryService {
52
53     private static final String PROPERTY_QUERY_NAME = "hasAllProperties";
54     private static final String MODULE_QUERY_NAME = "hasAllModules";
55     private final CpsDataPersistenceService cpsDataPersistenceService;
56     private final CpsAdminPersistenceService cpsAdminPersistenceService;
57     private final JsonObjectMapper jsonObjectMapper;
58
59     /**
60      * Query and return cm handles that match the given query parameters.
61      *
62      * @param cmHandleQueryServiceParameters the cm handle query parameters
63      * @return collection of cm handles
64      */
65     @Override
66     public Collection<DataNode> queryCmHandles(final CmHandleQueryServiceParameters cmHandleQueryServiceParameters) {
67
68         if (cmHandleQueryServiceParameters.getCmHandleQueryParameters().isEmpty()) {
69             return getAllCmHandles();
70         }
71
72         final Collection<DataNodeIdentifier> amalgamatedQueryResultIdentifiers = new ArrayList<>();
73         final Map<DataNodeIdentifier, DataNode> amalgamatedQueryResults = new HashMap<>();
74
75         final boolean firstQuery = moduleNameQuery(cmHandleQueryServiceParameters,
76                 amalgamatedQueryResultIdentifiers, amalgamatedQueryResults);
77
78         publicPropertyQuery(cmHandleQueryServiceParameters, amalgamatedQueryResultIdentifiers,
79                 amalgamatedQueryResults, firstQuery);
80
81         final Collection<DataNode> filteredDataNodes = new ArrayList<>();
82         amalgamatedQueryResultIdentifiers.forEach(amalgamatedQueryResultIdentifier ->
83             filteredDataNodes.add(amalgamatedQueryResults.get(amalgamatedQueryResultIdentifier))
84         );
85
86         return filteredDataNodes;
87     }
88
89     private void publicPropertyQuery(final CmHandleQueryServiceParameters cmHandleQueryServiceParameters,
90                                      final Collection<DataNodeIdentifier> amalgamatedQueryResultIdentifiers,
91                                      final Map<DataNodeIdentifier, DataNode> amalgamatedQueryResults,
92                                      boolean firstQuery) {
93         for (final Map.Entry<String, String> entry :
94                 getPublicPropertyPairs(cmHandleQueryServiceParameters.getCmHandleQueryParameters()).entrySet()) {
95             final String cmHandlePath = "//public-properties[@name='" + entry.getKey() + "' " + "and @value='"
96                     + entry.getValue() + "']" + "/ancestor::cm-handles";
97
98             final Collection<DataNode> dataNodes = getDataNodes(cmHandlePath);
99
100             if (firstQuery) {
101                 firstQuery = false;
102                 dataNodes.forEach(dataNode -> {
103                     final DataNodeIdentifier dataNodeIdentifier =
104                             jsonObjectMapper.convertToValueType(dataNode, DataNodeIdentifier.class);
105                     amalgamatedQueryResultIdentifiers.add(dataNodeIdentifier);
106                     amalgamatedQueryResults.put(dataNodeIdentifier, dataNode);
107                 });
108             } else {
109                 final Collection<DataNodeIdentifier> singleConditionQueryDataNodeIdentifiers = new ArrayList<>();
110                 dataNodes.forEach(dataNode -> {
111                     final DataNodeIdentifier dataNodeIdentifier =
112                             jsonObjectMapper.convertToValueType(dataNode, DataNodeIdentifier.class);
113                     singleConditionQueryDataNodeIdentifiers.add(dataNodeIdentifier);
114                     amalgamatedQueryResults.put(dataNodeIdentifier, dataNode);
115                 });
116                 amalgamatedQueryResultIdentifiers.retainAll(singleConditionQueryDataNodeIdentifiers);
117             }
118
119             if (amalgamatedQueryResultIdentifiers.isEmpty()) {
120                 break;
121             }
122         }
123     }
124
125     private boolean moduleNameQuery(final CmHandleQueryServiceParameters cmHandleQueryServiceParameters,
126                                     final Collection<DataNodeIdentifier> amalgamatedQueryResultIdentifiers,
127                                     final Map<DataNodeIdentifier, DataNode> amalgamatedQueryResults) {
128         boolean firstQuery = true;
129         if (!getModuleNames(cmHandleQueryServiceParameters.getCmHandleQueryParameters()).isEmpty()) {
130             final Collection<String> anchorNames = cpsAdminPersistenceService.queryAnchors("NFP-Operational",
131                     getModuleNames(cmHandleQueryServiceParameters.getCmHandleQueryParameters()))
132                     .parallelStream().map(Anchor::getName).collect(Collectors.toList());
133
134             getAllCmHandles().forEach(dataNode -> {
135                 if (anchorNames.contains(dataNode.getLeaves().get("id").toString())) {
136                     final DataNodeIdentifier dataNodeIdentifier =
137                             jsonObjectMapper.convertToValueType(dataNode, DataNodeIdentifier.class);
138                     amalgamatedQueryResultIdentifiers.add(dataNodeIdentifier);
139                     amalgamatedQueryResults.put(dataNodeIdentifier, dataNode);
140                 }
141             });
142
143             firstQuery = false;
144         }
145         return firstQuery;
146     }
147
148     private List<Map<String, String>> getConditions(final List<ConditionProperties> conditionProperties,
149                                                     final String name) {
150         for (final ConditionProperties conditionProperty : conditionProperties) {
151             if (conditionProperty.getConditionName().equals(name)) {
152                 return conditionProperty.getConditionParameters();
153             }
154         }
155         return Collections.emptyList();
156     }
157
158     private List<String> getModuleNames(final List<ConditionProperties> conditionProperties) {
159         final List<String> result = new ArrayList<>();
160         getConditions(conditionProperties, MODULE_QUERY_NAME).parallelStream().forEach(
161                 conditionProperty -> {
162                     validateModuleNameConditionProperties(conditionProperty);
163                     result.add(conditionProperty.get("moduleName"));
164                 }
165         );
166         return result;
167     }
168
169     private Map<String, String> getPublicPropertyPairs(final List<ConditionProperties> conditionProperties) {
170         final Map<String, String> result = new HashMap<>();
171         getConditions(conditionProperties, PROPERTY_QUERY_NAME).forEach(result::putAll);
172         return result;
173     }
174
175     private Collection<DataNode> getAllCmHandles() {
176         return getDataNodes("//public-properties/ancestor::cm-handles");
177     }
178
179     private List<DataNode> getDataNodes(final String cmHandlePath) {
180         return cpsDataPersistenceService.queryDataNodes(
181                 NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, cmHandlePath, INCLUDE_ALL_DESCENDANTS);
182     }
183 }