Merge "Remove CmHandle in DMI-Registry"
[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 Nordix Foundation
5  *  Modifications Copyright (C) 2021 Pantheon.tech
6  *  ================================================================================
7  *  Licensed under the Apache License, Version 2.0 (the "License");
8  *  you may not use this file except in compliance with the License.
9  *  You may obtain a copy of the License at
10  *
11  *        http://www.apache.org/licenses/LICENSE-2.0
12  *
13  *  Unless required by applicable law or agreed to in writing, software
14  *  distributed under the License is distributed on an "AS IS" BASIS,
15  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  *  See the License for the specific language governing permissions and
17  *  limitations under the License.
18  *
19  *  SPDX-License-Identifier: Apache-2.0
20  *  ============LICENSE_END=========================================================
21  */
22
23 package org.onap.cps.ncmp.api.impl;
24
25 import com.fasterxml.jackson.core.JsonProcessingException;
26 import com.fasterxml.jackson.databind.ObjectMapper;
27 import java.util.Collection;
28 import java.util.Collections;
29 import java.util.LinkedHashMap;
30 import java.util.LinkedList;
31 import java.util.List;
32 import java.util.Map;
33 import javax.validation.constraints.NotNull;
34 import lombok.extern.slf4j.Slf4j;
35 import org.onap.cps.api.CpsDataService;
36 import org.onap.cps.api.CpsQueryService;
37 import org.onap.cps.ncmp.api.NetworkCmProxyDataService;
38 import org.onap.cps.ncmp.api.impl.exception.NcmpException;
39 import org.onap.cps.ncmp.api.impl.operation.DmiOperations;
40 import org.onap.cps.ncmp.api.models.CmHandle;
41 import org.onap.cps.ncmp.api.models.DmiPluginRegistration;
42 import org.onap.cps.ncmp.api.models.GenericRequestBody;
43 import org.onap.cps.ncmp.api.models.PersistenceCmHandle;
44 import org.onap.cps.ncmp.api.models.PersistenceCmHandlesList;
45 import org.onap.cps.spi.FetchDescendantsOption;
46 import org.onap.cps.spi.exceptions.DataNodeNotFoundException;
47 import org.onap.cps.spi.exceptions.DataValidationException;
48 import org.onap.cps.spi.model.DataNode;
49 import org.springframework.http.HttpStatus;
50 import org.springframework.http.ResponseEntity;
51 import org.springframework.stereotype.Service;
52 import org.springframework.util.StringUtils;
53
54
55 @Slf4j
56 @Service
57 public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService {
58
59     private static final String NF_PROXY_DATASPACE_NAME = "NFP-Operational";
60
61     private static final String NCMP_DATASPACE_NAME = "NCMP-Admin";
62
63     private static final String NCMP_DMI_REGISTRY_ANCHOR = "ncmp-dmi-registry";
64
65     private CpsDataService cpsDataService;
66
67     private ObjectMapper objectMapper;
68
69     private CpsQueryService cpsQueryService;
70
71     private DmiOperations dmiOperations;
72
73     /**
74      * Constructor Injection for Dependencies.
75      *
76      * @param dmiOperations   dmi operation
77      * @param cpsDataService  Data Service Interface
78      * @param cpsQueryService Query Service Interface
79      * @param objectMapper    Object Mapper
80      */
81     public NetworkCmProxyDataServiceImpl(final DmiOperations dmiOperations, final CpsDataService cpsDataService,
82         final CpsQueryService cpsQueryService, final ObjectMapper objectMapper) {
83         this.dmiOperations = dmiOperations;
84         this.cpsDataService = cpsDataService;
85         this.cpsQueryService = cpsQueryService;
86         this.objectMapper = objectMapper;
87     }
88
89     private String getDataspaceName() {
90         return NF_PROXY_DATASPACE_NAME;
91     }
92
93     @Override
94     public DataNode getDataNode(final String cmHandle, final String xpath,
95         final FetchDescendantsOption fetchDescendantsOption) {
96         return cpsDataService.getDataNode(getDataspaceName(), cmHandle, xpath, fetchDescendantsOption);
97     }
98
99     @Override
100     public Collection<DataNode> queryDataNodes(final String cmHandle, final String cpsPath,
101         final FetchDescendantsOption fetchDescendantsOption) {
102         return cpsQueryService.queryDataNodes(getDataspaceName(), cmHandle, cpsPath, fetchDescendantsOption);
103     }
104
105     @Override
106     public void createDataNode(final String cmHandle, final String parentNodeXpath, final String jsonData) {
107         if (!StringUtils.hasText(parentNodeXpath) || "/".equals(parentNodeXpath)) {
108             cpsDataService.saveData(getDataspaceName(), cmHandle, jsonData);
109         } else {
110             cpsDataService.saveData(getDataspaceName(), cmHandle, parentNodeXpath, jsonData);
111         }
112     }
113
114     @Override
115     public void addListNodeElements(final String cmHandle, final String parentNodeXpath, final String jsonData) {
116         cpsDataService.saveListNodeData(getDataspaceName(), cmHandle, parentNodeXpath, jsonData);
117     }
118
119     @Override
120     public void updateNodeLeaves(final String cmHandle, final String parentNodeXpath, final String jsonData) {
121         cpsDataService.updateNodeLeaves(getDataspaceName(), cmHandle, parentNodeXpath, jsonData);
122     }
123
124     @Override
125     public void replaceNodeTree(final String cmHandle, final String parentNodeXpath, final String jsonData) {
126         cpsDataService.replaceNodeTree(getDataspaceName(), cmHandle, parentNodeXpath, jsonData);
127     }
128
129     @Override
130     public void updateDmiPluginRegistration(final DmiPluginRegistration dmiPluginRegistration) {
131         if (dmiPluginRegistration.getCreatedCmHandles() != null) {
132             parseAndCreateCmHandlesInDmiRegistration(dmiPluginRegistration);
133         }
134         if (dmiPluginRegistration.getUpdatedCmHandles() != null) {
135             parseAndUpdateCmHandlesInDmiRegistration(dmiPluginRegistration);
136         }
137         if (dmiPluginRegistration.getRemovedCmHandles() != null) {
138             parseAndRemoveCmHandlesInDmiRegistration(dmiPluginRegistration);
139         }
140     }
141
142     private void parseAndCreateCmHandlesInDmiRegistration(final DmiPluginRegistration dmiPluginRegistration) {
143         try {
144             final List<PersistenceCmHandle> createdPersistenceCmHandles =
145                 new LinkedList<>();
146             for (final CmHandle cmHandle : dmiPluginRegistration.getCreatedCmHandles()) {
147                 createdPersistenceCmHandles.add(toPersistenceCmHandle(dmiPluginRegistration, cmHandle));
148             }
149             final PersistenceCmHandlesList persistenceCmHandlesList = new PersistenceCmHandlesList();
150             persistenceCmHandlesList.setCmHandles(createdPersistenceCmHandles);
151             final String cmHandleJsonData = objectMapper.writeValueAsString(persistenceCmHandlesList);
152             cpsDataService.saveListNodeData(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, "/dmi-registry",
153                 cmHandleJsonData);
154         } catch (final JsonProcessingException e) {
155             log.error("Parsing error occurred while converting Object to JSON for Dmi Registry.");
156             throw new DataValidationException(
157                 "Parsing error occurred while processing DMI Plugin Registration" + dmiPluginRegistration, e
158                 .getMessage(), e);
159         }
160     }
161
162     private void parseAndUpdateCmHandlesInDmiRegistration(final DmiPluginRegistration dmiPluginRegistration) {
163         try {
164             final List<PersistenceCmHandle> updatedPersistenceCmHandles =
165                 new LinkedList<>();
166             for (final CmHandle cmHandle : dmiPluginRegistration.getUpdatedCmHandles()) {
167                 updatedPersistenceCmHandles.add(toPersistenceCmHandle(dmiPluginRegistration, cmHandle));
168             }
169             final PersistenceCmHandlesList persistenceCmHandlesList = new PersistenceCmHandlesList();
170             persistenceCmHandlesList.setCmHandles(updatedPersistenceCmHandles);
171             final String cmHandlesJsonData = objectMapper.writeValueAsString(persistenceCmHandlesList);
172             cpsDataService.updateNodeLeavesAndExistingDescendantLeaves(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR,
173                 "/dmi-registry", cmHandlesJsonData);
174         } catch (final JsonProcessingException e) {
175             log.error("Parsing error occurred while converting Object to JSON Dmi Registry.");
176             throw new DataValidationException(
177                 "Parsing error occurred while processing DMI Plugin Registration" + dmiPluginRegistration, e
178                 .getMessage(), e);
179         }
180     }
181
182     private void parseAndRemoveCmHandlesInDmiRegistration(final DmiPluginRegistration dmiPluginRegistration) {
183         for (final String cmHandle: dmiPluginRegistration.getRemovedCmHandles()) {
184             try {
185                 cpsDataService.deleteListNodeData(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR,
186                     "/dmi-registry/cm-handles[@id='" + cmHandle + "']");
187             } catch (final DataNodeNotFoundException e) {
188                 log.warn("Datanode {} not deleted message {}", cmHandle, e.getMessage());
189             }
190         }
191     }
192
193     @Override
194     public Object getResourceDataOperationalForCmHandle(final @NotNull String cmHandle,
195         final @NotNull String resourceIdentifier,
196         final String acceptParam,
197         final String fieldsQueryParam,
198         final Integer depthQueryParam) {
199
200         final var dataNode = fetchDataNodeFromDmiRegistryForCmHandle(cmHandle);
201         final var dmiServiceName = String.valueOf(dataNode.getLeaves().get("dmi-service-name"));
202         final Collection<DataNode> additionalPropsList = dataNode.getChildDataNodes();
203         final var jsonBody = prepareOperationBody(GenericRequestBody.OperationEnum.READ, additionalPropsList);
204         final ResponseEntity<Object> response = dmiOperations.getResouceDataOperationalFromDmi(dmiServiceName,
205             cmHandle,
206             resourceIdentifier,
207             fieldsQueryParam,
208             depthQueryParam,
209             acceptParam,
210             jsonBody);
211         return handleResponse(response);
212     }
213
214     @Override
215     public Object getResourceDataPassThroughRunningForCmHandle(final @NotNull String cmHandle,
216         final @NotNull String resourceIdentifier,
217         final String accept,
218         final String fields,
219         final Integer depth) {
220         final var cmHandleDataNode = fetchDataNodeFromDmiRegistryForCmHandle(cmHandle);
221         final var dmiServiceName = String.valueOf(cmHandleDataNode.getLeaves().get("dmi-service-name"));
222         final Collection<DataNode> additionalPropsList = cmHandleDataNode.getChildDataNodes();
223         final var dmiRequesBody = prepareOperationBody(GenericRequestBody.OperationEnum.READ, additionalPropsList);
224         final ResponseEntity<Object> response = dmiOperations.getResouceDataPassThroughRunningFromDmi(dmiServiceName,
225             cmHandle,
226             resourceIdentifier,
227             fields,
228             depth,
229             accept,
230             dmiRequesBody);
231         return handleResponse(response);
232     }
233
234     private DataNode fetchDataNodeFromDmiRegistryForCmHandle(final String cmHandle) {
235         final String xpathForDmiRegistryToFetchCmHandle = "/dmi-registry/cm-handles[@id='" + cmHandle + "']";
236         final var dataNode = cpsDataService.getDataNode(NCMP_DATASPACE_NAME,
237             NCMP_DMI_REGISTRY_ANCHOR,
238             xpathForDmiRegistryToFetchCmHandle,
239             FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS);
240         return dataNode;
241     }
242
243     private String prepareOperationBody(final GenericRequestBody.OperationEnum operation,
244         final Collection<DataNode> additionalPropertyList) {
245         final var requestBody = new GenericRequestBody();
246         final Map<String, String> additionalPropertyMap = getAdditionalPropertiesMap(additionalPropertyList);
247         requestBody.setOperation(GenericRequestBody.OperationEnum.READ);
248         requestBody.setCmHandleProperties(additionalPropertyMap);
249         try {
250             final var requestJson = objectMapper.writeValueAsString(requestBody);
251             return requestJson;
252         } catch (final JsonProcessingException je) {
253             log.error("Parsing error occurred while converting Object to JSON.");
254             throw new NcmpException("Parsing error occurred while converting given object to JSON.",
255                 je.getMessage());
256         }
257     }
258
259     private Map<String, String> getAdditionalPropertiesMap(final Collection<DataNode> additionalPropertyList) {
260         if (additionalPropertyList == null || additionalPropertyList.size() == 0) {
261             return null;
262         }
263         final Map<String, String> additionalPropertyMap = new LinkedHashMap<>();
264         for (final var node : additionalPropertyList) {
265             additionalPropertyMap.put(String.valueOf(node.getLeaves().get("name")),
266                 String.valueOf(node.getLeaves().get("value")));
267         }
268         return additionalPropertyMap;
269     }
270
271     private Object handleResponse(final ResponseEntity<Object> responseEntity) {
272         if (responseEntity.getStatusCode() == HttpStatus.OK) {
273             return responseEntity.getBody();
274         } else {
275             throw new NcmpException("Not able to get resource data.",
276                 "DMI status code: " + responseEntity.getStatusCodeValue()
277                     + ", DMI response body: " + responseEntity.getBody());
278         }
279     }
280
281     private PersistenceCmHandle toPersistenceCmHandle(final DmiPluginRegistration dmiPluginRegistration,
282         final CmHandle cmHandle) {
283         final PersistenceCmHandle persistenceCmHandle = new PersistenceCmHandle();
284         persistenceCmHandle.setDmiServiceName(dmiPluginRegistration.getDmiPlugin());
285         persistenceCmHandle.setId(cmHandle.getCmHandleID());
286         if (cmHandle.getCmHandleProperties() == null) {
287             persistenceCmHandle.setAdditionalProperties(Collections.EMPTY_MAP);
288         } else {
289             persistenceCmHandle.setAdditionalProperties(cmHandle.getCmHandleProperties());
290         }
291         return persistenceCmHandle;
292     }
293
294 }