Replace gson mapper with jackson mapper
[cps.git] / cps-ncmp-service / src / main / java / org / onap / cps / ncmp / api / impl / NetworkCmProxyDataServiceImpl.java
1 /*
2  *  ============LICENSE_START=======================================================
3  *  Copyright (C) 2021 highstreet technologies GmbH
4  *  Modifications Copyright (C) 2021-2022 Nordix Foundation
5  *  Modifications Copyright (C) 2021 Pantheon.tech
6  *  Modifications Copyright (C) 2021 Bell Canada
7  *  ================================================================================
8  *  Licensed under the Apache License, Version 2.0 (the "License");
9  *  you may not use this file except in compliance with the License.
10  *  You may obtain a copy of the License at
11  *
12  *        http://www.apache.org/licenses/LICENSE-2.0
13  *
14  *  Unless required by applicable law or agreed to in writing, software
15  *  distributed under the License is distributed on an "AS IS" BASIS,
16  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  *  See the License for the specific language governing permissions and
18  *  limitations under the License.
19  *
20  *  SPDX-License-Identifier: Apache-2.0
21  *  ============LICENSE_END=========================================================
22  */
23
24 package org.onap.cps.ncmp.api.impl;
25
26 import static org.onap.cps.ncmp.api.impl.operations.DmiRequestBody.OperationEnum;
27 import static org.onap.cps.spi.CascadeDeleteAllowed.CASCADE_DELETE_ALLOWED;
28
29 import com.fasterxml.jackson.core.JsonProcessingException;
30 import java.time.OffsetDateTime;
31 import java.util.ArrayList;
32 import java.util.Collection;
33 import java.util.HashMap;
34 import java.util.List;
35 import java.util.Map;
36 import lombok.RequiredArgsConstructor;
37 import lombok.extern.slf4j.Slf4j;
38 import org.onap.cps.api.CpsAdminService;
39 import org.onap.cps.api.CpsDataService;
40 import org.onap.cps.api.CpsModuleService;
41 import org.onap.cps.ncmp.api.NetworkCmProxyDataService;
42 import org.onap.cps.ncmp.api.impl.exception.NcmpException;
43 import org.onap.cps.ncmp.api.impl.operations.DmiDataOperations;
44 import org.onap.cps.ncmp.api.impl.operations.DmiModelOperations;
45 import org.onap.cps.ncmp.api.impl.operations.DmiOperations;
46 import org.onap.cps.ncmp.api.models.CmHandle;
47 import org.onap.cps.ncmp.api.models.DmiPluginRegistration;
48 import org.onap.cps.ncmp.api.models.PersistenceCmHandle;
49 import org.onap.cps.ncmp.api.models.PersistenceCmHandlesList;
50 import org.onap.cps.spi.exceptions.DataNodeNotFoundException;
51 import org.onap.cps.spi.exceptions.DataValidationException;
52 import org.onap.cps.spi.model.ModuleReference;
53 import org.onap.cps.utils.JsonObjectMapper;
54 import org.springframework.http.ResponseEntity;
55 import org.springframework.stereotype.Service;
56
57 @Slf4j
58 @Service
59 @RequiredArgsConstructor
60 public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService {
61
62     private static final String NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME = "NFP-Operational";
63
64     private static final String NCMP_DATASPACE_NAME = "NCMP-Admin";
65
66     private static final String NCMP_DMI_REGISTRY_ANCHOR = "ncmp-dmi-registry";
67
68     private static final OffsetDateTime NO_TIMESTAMP = null;
69
70     private final CpsDataService cpsDataService;
71
72     private final JsonObjectMapper jsonObjectMapper;
73
74     private final DmiDataOperations dmiDataOperations;
75
76     private final DmiModelOperations dmiModelOperations;
77
78     private final CpsModuleService cpsModuleService;
79
80     private final CpsAdminService cpsAdminService;
81
82     @Override
83     public void updateDmiRegistrationAndSyncModule(final DmiPluginRegistration dmiPluginRegistration) {
84         dmiPluginRegistration.validateDmiPluginRegistration();
85         try {
86             if (dmiPluginRegistration.getCreatedCmHandles() != null) {
87                 parseAndCreateCmHandlesInDmiRegistrationAndSyncModules(dmiPluginRegistration);
88             }
89             if (dmiPluginRegistration.getUpdatedCmHandles() != null) {
90                 parseAndUpdateCmHandlesInDmiRegistration(dmiPluginRegistration);
91             }
92             if (dmiPluginRegistration.getRemovedCmHandles() != null) {
93                 parseAndRemoveCmHandlesInDmiRegistration(dmiPluginRegistration);
94             }
95         } catch (final JsonProcessingException e) {
96             handleJsonProcessingException(dmiPluginRegistration, e);
97         }
98     }
99
100     @Override
101     public Object getResourceDataOperationalForCmHandle(final String cmHandle,
102                                                         final String resourceIdentifier,
103                                                         final String acceptParamInHeader,
104                                                         final String optionsParamInQuery) {
105         return handleResponse(dmiDataOperations.getResourceDataFromDmi(
106             cmHandle,
107             resourceIdentifier,
108             optionsParamInQuery,
109             acceptParamInHeader,
110             DmiOperations.DataStoreEnum.PASSTHROUGH_OPERATIONAL), "Not able to get resource data.");
111     }
112
113     @Override
114     public Object getResourceDataPassThroughRunningForCmHandle(final String cmHandle,
115                                                                final String resourceIdentifier,
116                                                                final String acceptParamInHeader,
117                                                                final String optionsParamInQuery) {
118         return handleResponse(dmiDataOperations.getResourceDataFromDmi(
119             cmHandle,
120             resourceIdentifier,
121             optionsParamInQuery,
122             acceptParamInHeader,
123             DmiOperations.DataStoreEnum.PASSTHROUGH_RUNNING), "Not able to get resource data.");
124     }
125
126     @Override
127     public Object writeResourceDataPassThroughRunningForCmHandle(final String cmHandle,
128                                                                final String resourceIdentifier,
129                                                                final OperationEnum operation,
130                                                                final String requestData,
131                                                                final String dataType) {
132         return handleResponse(
133             dmiDataOperations.writeResourceDataPassThroughRunningFromDmi(
134                 cmHandle, resourceIdentifier, operation, requestData, dataType),
135             "Not able to " + operation + " resource data.");
136     }
137
138
139     @Override
140     public Collection<ModuleReference> getYangResourcesModuleReferences(final String cmHandle) {
141         return cpsModuleService.getYangResourcesModuleReferences(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, cmHandle);
142     }
143
144     /**
145      * Retrieve cm handle identifiers for the given list of module names.
146      *
147      * @param moduleNames module names.
148      * @return a collection of anchor identifiers
149      */
150     @Override
151     public Collection<String> executeCmHandleHasAllModulesSearch(final Collection<String> moduleNames) {
152         return cpsAdminService.queryAnchorNames(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, moduleNames);
153     }
154
155     /**
156      * THis method registers a cm handle and intiates modules sync.
157      *
158      * @param dmiPluginRegistration dmi plugin registration information.
159      * @throws JsonProcessingException thrown if json is malformed or missing.
160      */
161     public void parseAndCreateCmHandlesInDmiRegistrationAndSyncModules(
162         final DmiPluginRegistration dmiPluginRegistration) throws JsonProcessingException {
163         final PersistenceCmHandlesList createdPersistenceCmHandlesList =
164             getUpdatedPersistenceCmHandlesList(dmiPluginRegistration, dmiPluginRegistration.getCreatedCmHandles());
165         registerAndSyncNewCmHandles(createdPersistenceCmHandlesList);
166     }
167
168     private static Object handleResponse(final ResponseEntity<?> responseEntity,
169                                          final String exceptionMessage) {
170         if (responseEntity.getStatusCode().is2xxSuccessful()) {
171             return responseEntity.getBody();
172         } else {
173             throw new NcmpException(exceptionMessage,
174                     "DMI status code: " + responseEntity.getStatusCodeValue()
175                             + ", DMI response body: " + responseEntity.getBody());
176         }
177     }
178
179     private void parseAndUpdateCmHandlesInDmiRegistration(final DmiPluginRegistration dmiPluginRegistration)
180         throws JsonProcessingException {
181         final PersistenceCmHandlesList updatedPersistenceCmHandlesList =
182             getUpdatedPersistenceCmHandlesList(dmiPluginRegistration, dmiPluginRegistration.getUpdatedCmHandles());
183         final String cmHandlesAsJson = jsonObjectMapper.asJsonString(updatedPersistenceCmHandlesList);
184         cpsDataService.updateNodeLeavesAndExistingDescendantLeaves(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR,
185                 "/dmi-registry", cmHandlesAsJson, NO_TIMESTAMP);
186     }
187
188     private PersistenceCmHandlesList getUpdatedPersistenceCmHandlesList(
189         final DmiPluginRegistration dmiPluginRegistration,
190         final List<CmHandle> updatedCmHandles) {
191         return PersistenceCmHandlesList.toPersistenceCmHandlesList(
192             dmiPluginRegistration.getDmiPlugin(),
193             dmiPluginRegistration.getDmiDataPlugin(),
194             dmiPluginRegistration.getDmiModelPlugin(),
195             updatedCmHandles);
196     }
197
198     private static void handleJsonProcessingException(final DmiPluginRegistration dmiPluginRegistration,
199                                                       final JsonProcessingException e) {
200         final String message = "Parsing error occurred while processing DMI Plugin Registration"
201             + dmiPluginRegistration;
202         log.error(message);
203         throw new DataValidationException(message, e.getMessage(), e);
204     }
205
206     private void registerAndSyncNewCmHandles(final PersistenceCmHandlesList persistenceCmHandlesList)
207         throws JsonProcessingException  {
208         final String cmHandleJsonData = jsonObjectMapper.asJsonString(persistenceCmHandlesList);
209         cpsDataService.saveListElements(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, "/dmi-registry",
210             cmHandleJsonData, NO_TIMESTAMP);
211
212         for (final PersistenceCmHandle persistenceCmHandle : persistenceCmHandlesList.getPersistenceCmHandles()) {
213             syncModulesAndCreateAnchor(persistenceCmHandle);
214         }
215     }
216
217     protected void syncModulesAndCreateAnchor(final PersistenceCmHandle persistenceCmHandle) {
218         syncAndCreateSchemaSet(persistenceCmHandle);
219         createAnchor(persistenceCmHandle);
220     }
221
222     private void parseAndRemoveCmHandlesInDmiRegistration(final DmiPluginRegistration dmiPluginRegistration) {
223         for (final String cmHandle : dmiPluginRegistration.getRemovedCmHandles()) {
224             try {
225                 attemptToDeleteSchemaSetWithCascade(cmHandle);
226                 cpsDataService.deleteListOrListElement(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR,
227                     "/dmi-registry/cm-handles[@id='" + cmHandle + "']", NO_TIMESTAMP);
228             } catch (final DataNodeNotFoundException e) {
229                 log.warn("Datanode {} not deleted message {}", cmHandle, e.getMessage());
230             }
231         }
232     }
233
234     private void attemptToDeleteSchemaSetWithCascade(final String schemaSetName) {
235         try {
236             cpsModuleService.deleteSchemaSet(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, schemaSetName,
237                 CASCADE_DELETE_ALLOWED);
238         } catch (final Exception e) {
239             log.warn("Schema set {} delete failed, reason {}", schemaSetName, e.getMessage());
240         }
241     }
242
243     private void syncAndCreateSchemaSet(final PersistenceCmHandle persistenceCmHandle) {
244         final List<ModuleReference> moduleReferencesFromCmHandle =
245             dmiModelOperations.getModuleReferences(persistenceCmHandle);
246         final List<ModuleReference> existingModuleReferences = new ArrayList<>();
247         final List<ModuleReference> unknownModuleReferences = new ArrayList<>();
248         prepareModuleSubsets(moduleReferencesFromCmHandle, existingModuleReferences, unknownModuleReferences);
249
250         final Map<String, String> newYangResourcesModuleNameToContentMap;
251         if (unknownModuleReferences.isEmpty()) {
252             newYangResourcesModuleNameToContentMap = new HashMap<>();
253         } else {
254             newYangResourcesModuleNameToContentMap = dmiModelOperations.getNewYangResourcesFromDmi(persistenceCmHandle,
255                 unknownModuleReferences);
256         }
257         cpsModuleService
258             .createSchemaSetFromModules(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, persistenceCmHandle.getId(),
259                 newYangResourcesModuleNameToContentMap, existingModuleReferences);
260     }
261
262     private void prepareModuleSubsets(final List<ModuleReference> moduleReferencesFromCmHandle,
263                                       final List<ModuleReference> existingModuleReferences,
264                                       final List<ModuleReference> unknownModuleReferences) {
265
266         final Collection<ModuleReference> knownModuleReferencesInCps =
267             cpsModuleService.getYangResourceModuleReferences(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME);
268
269         for (final ModuleReference moduleReferenceFromDmiForCmHandle : moduleReferencesFromCmHandle) {
270             if (knownModuleReferencesInCps.contains(moduleReferenceFromDmiForCmHandle)) {
271                 existingModuleReferences.add(moduleReferenceFromDmiForCmHandle);
272             } else {
273                 unknownModuleReferences.add(moduleReferenceFromDmiForCmHandle);
274             }
275         }
276     }
277
278     private void createAnchor(final PersistenceCmHandle persistenceCmHandle) {
279         cpsAdminService.createAnchor(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, persistenceCmHandle.getId(),
280             persistenceCmHandle.getId());
281     }
282
283
284
285 }