Add support for object characteristic type in Service Order
[externalapi/nbi.git] / src / main / java / org / onap / nbi / apis / serviceorder / workflow / PostSoProcessor.java
1 /**
2  * Copyright (c) 2018 Orange
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5  * in compliance with the License. You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software distributed under the License
10  * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11  * or implied. See the License for the specific language governing permissions and limitations under
12  * the License.
13  */
14 package org.onap.nbi.apis.serviceorder.workflow;
15
16 import java.io.IOException;
17 import java.util.ArrayList;
18 import java.util.HashMap;
19 import java.util.Iterator;
20 import java.util.List;
21 import java.util.Map;
22 import org.onap.nbi.apis.serviceorder.SoClient;
23 import org.onap.nbi.apis.serviceorder.model.ServiceCharacteristic;
24 import org.onap.nbi.apis.serviceorder.model.ServiceOrder;
25 import org.onap.nbi.apis.serviceorder.model.ServiceOrderItem;
26 import org.onap.nbi.apis.serviceorder.model.StateType;
27 import org.onap.nbi.apis.serviceorder.model.consumer.CloudConfiguration;
28 import org.onap.nbi.apis.serviceorder.model.consumer.CreateE2EServiceInstanceResponse;
29 import org.onap.nbi.apis.serviceorder.model.consumer.CreateServiceInstanceResponse;
30 import org.onap.nbi.apis.serviceorder.model.consumer.MSOE2EPayload;
31 import org.onap.nbi.apis.serviceorder.model.consumer.MSOPayload;
32 import org.onap.nbi.apis.serviceorder.model.consumer.ModelInfo;
33 import org.onap.nbi.apis.serviceorder.model.consumer.OwningEntity;
34 import org.onap.nbi.apis.serviceorder.model.consumer.ParametersModel;
35 import org.onap.nbi.apis.serviceorder.model.consumer.Project;
36 import org.onap.nbi.apis.serviceorder.model.consumer.RequestDetails;
37 import org.onap.nbi.apis.serviceorder.model.consumer.RequestInfo;
38 import org.onap.nbi.apis.serviceorder.model.consumer.RequestParameters;
39 import org.onap.nbi.apis.serviceorder.model.consumer.ResourceModel;
40 import org.onap.nbi.apis.serviceorder.model.consumer.ServiceModel;
41 import org.onap.nbi.apis.serviceorder.model.consumer.SubscriberInfo;
42 import org.onap.nbi.apis.serviceorder.model.consumer.UserParams;
43 import org.onap.nbi.apis.serviceorder.model.orchestrator.ServiceOrderInfo;
44 import org.onap.nbi.apis.serviceorder.service.ServiceOrderService;
45 import org.slf4j.Logger;
46 import org.slf4j.LoggerFactory;
47 import org.springframework.beans.factory.annotation.Autowired;
48 import org.springframework.beans.factory.annotation.Value;
49 import org.springframework.http.ResponseEntity;
50 import org.springframework.stereotype.Service;
51 import org.springframework.util.CollectionUtils;
52 import com.fasterxml.jackson.databind.JsonNode;
53 import com.fasterxml.jackson.databind.ObjectMapper;
54 import com.fasterxml.jackson.databind.node.ArrayNode;
55 import com.fasterxml.jackson.databind.node.ObjectNode;
56
57 @Service
58 public class PostSoProcessor {
59
60   private static final Logger LOGGER = LoggerFactory.getLogger(PostSoProcessor.class);
61
62   @Value("${onap.lcpCloudRegionId}")
63   private String lcpCloudRegionId;
64
65   @Value("${onap.tenantId}")
66   private String tenantId;
67
68   @Value("${so.owning.entity.id}")
69   private String soOwningEntityId;
70
71   @Value("${so.owning.entity.name}")
72   private String soOwningEntityName;
73
74   @Value("${so.project.name}")
75   private String soProjectName;
76
77
78   @Autowired
79   private ServiceOrderService serviceOrderService;
80
81   @Autowired
82   private SoClient soClient;
83
84
85
86   public ResponseEntity<CreateServiceInstanceResponse> postServiceOrderItem(
87       ServiceOrderInfo serviceOrderInfo, ServiceOrderItem serviceOrderItem) {
88     ResponseEntity<CreateServiceInstanceResponse> response = null;
89     try {
90       response = postSORequest(serviceOrderItem, serviceOrderInfo);
91     } catch (NullPointerException e) {
92       LOGGER.error(
93           "Unable to create service instance for serviceOrderItem.id=" + serviceOrderItem.getId(),
94           e);
95       response = null;
96     }
97     return response;
98   }
99
100   public ResponseEntity<CreateE2EServiceInstanceResponse> postE2EServiceOrderItem(
101       ServiceOrderInfo serviceOrderInfo, ServiceOrderItem serviceOrderItem,
102       ServiceOrder serviceOrder) {
103     ResponseEntity<CreateE2EServiceInstanceResponse> response;
104     try {
105       response = postE2ESORequest(serviceOrderItem, serviceOrderInfo, serviceOrder);
106     } catch (NullPointerException e) {
107       LOGGER.error(
108           "Unable to create service instance for serviceOrderItem.id=" + serviceOrderItem.getId(),
109           e);
110       response = null;
111     }
112     return response;
113   }
114
115   private ResponseEntity<CreateServiceInstanceResponse> postSORequest(
116       ServiceOrderItem serviceOrderItem, ServiceOrderInfo serviceOrderInfo) {
117     RequestDetails requestDetails =
118         buildSoRequest(
119             serviceOrderItem, serviceOrderInfo.getServiceOrderItemInfos()
120                 .get(serviceOrderItem.getId()).getCatalogResponse(),
121             serviceOrderInfo.getSubscriberInfo());
122     MSOPayload msoPayload = new MSOPayload(requestDetails);
123     ResponseEntity<CreateServiceInstanceResponse> response = null;
124
125     switch (serviceOrderItem.getAction()) {
126       case ADD:
127         response = soClient.callCreateServiceInstance(msoPayload);
128         break;
129       case DELETE:
130         response =
131             soClient.callDeleteServiceInstance(msoPayload, serviceOrderItem.getService().getId());
132         break;
133       case MODIFY:
134         if (StateType.INPROGRESS_MODIFY_ITEM_TO_CREATE == serviceOrderItem.getState()) {
135           response = soClient.callCreateServiceInstance(msoPayload);
136         }
137         if (StateType.ACKNOWLEDGED == serviceOrderItem.getState()) {
138           response =
139               soClient.callDeleteServiceInstance(msoPayload, serviceOrderItem.getService().getId());
140         }
141         break;
142       default:
143         break;
144     }
145     return response;
146   }
147
148   private ResponseEntity<CreateE2EServiceInstanceResponse> postE2ESORequest(
149       ServiceOrderItem serviceOrderItem, ServiceOrderInfo serviceOrderInfo,
150       ServiceOrder serviceOrder) {
151     ServiceModel service =
152         buildE2ESoRequest(
153             serviceOrderItem, serviceOrderInfo.getServiceOrderItemInfos()
154                 .get(serviceOrderItem.getId()).getCatalogResponse(),
155             serviceOrderInfo.getSubscriberInfo(), serviceOrder);
156     MSOE2EPayload msoE2EPayload = new MSOE2EPayload(service);
157     ResponseEntity<CreateE2EServiceInstanceResponse> response = null;
158     switch (serviceOrderItem.getAction()) {
159       case ADD:
160         response = soClient.callE2ECreateServiceInstance(msoE2EPayload);
161         break;
162       case DELETE:
163         response = soClient.callE2EDeleteServiceInstance(service.getGlobalSubscriberId(),
164             service.getServiceType(), serviceOrderItem.getService().getId());
165         break;
166       case MODIFY:
167         if (StateType.INPROGRESS_MODIFY_ITEM_TO_CREATE == serviceOrderItem.getState()) {
168           response = soClient.callE2ECreateServiceInstance(msoE2EPayload);
169         }
170         if (StateType.ACKNOWLEDGED == serviceOrderItem.getState()) {
171           response = soClient.callE2EDeleteServiceInstance(service.getGlobalSubscriberId(),
172               service.getServiceType(), serviceOrderItem.getService().getId());
173         }
174         break;
175       default:
176         break;
177     }
178     return response;
179   }
180
181
182
183   /**
184    * Build SO CREATE request from the ServiceOrder and catalog informations from SDC
185    *
186    * @param orderItem
187    * @param sdcInfos
188    * @param subscriberInfo
189    * @return
190    */
191   private RequestDetails buildSoRequest(ServiceOrderItem orderItem, Map<String, Object> sdcInfos,
192       SubscriberInfo subscriberInfo) {
193     RequestDetails requestDetails = new RequestDetails();
194
195     requestDetails.setSubscriberInfo(subscriberInfo);
196
197     ModelInfo modelInfo = new ModelInfo();
198     modelInfo.setModelType("service");
199     modelInfo.setModelInvariantId((String) sdcInfos.get("invariantUUID"));
200     modelInfo.setModelNameVersionId(orderItem.getService().getServiceSpecification().getId());
201     modelInfo.setModelVersionId(orderItem.getService().getServiceSpecification().getId());
202     modelInfo.setModelName((String) sdcInfos.get("name"));
203     modelInfo.setModelVersion((String) sdcInfos.get("version"));
204     requestDetails.setModelInfo(modelInfo);
205
206     RequestInfo requestInfo = new RequestInfo();
207     requestInfo.setInstanceName(orderItem.getService().getName());
208     requestInfo.setSource("VID");
209     requestInfo.setSuppressRollback(false);
210     requestInfo.setRequestorId("NBI");
211     requestDetails.setRequestInfo(requestInfo);
212
213     RequestParameters requestParameters = new RequestParameters();
214     requestParameters.setSubscriptionServiceType((String) sdcInfos.get("name"));
215     requestParameters.setUserParams(retrieveUserParamsFromServiceCharacteristics(
216         orderItem.getService().getServiceCharacteristic()));
217     requestParameters.setaLaCarte(true);
218     requestDetails.setRequestParameters(requestParameters);
219
220     CloudConfiguration cloudConfiguration = new CloudConfiguration(lcpCloudRegionId, tenantId);
221     requestDetails.setCloudConfiguration(cloudConfiguration);
222
223     OwningEntity owningEntity = new OwningEntity();
224     owningEntity.setOwningEntityId(soOwningEntityId);
225     owningEntity.setOwningEntityName(soOwningEntityName);
226     requestDetails.setOwningEntity(owningEntity);
227
228     Project project = new Project();
229     project.setProjectName(soProjectName);
230
231     requestDetails.setProject(project);
232
233     return requestDetails;
234   }
235
236   /**
237    * Build E2E SO CREATE request from the ServiceOrder and catalog informations from SDC
238    *
239    * @param serviceOrderItem
240    * @param serviceOrder
241    * @param sdcInfos
242    * @return
243    */
244   // ServiceOrderItem serviceOrderItem --> orderItem?
245   private ServiceModel buildE2ESoRequest(ServiceOrderItem serviceOrderItem,
246       Map<String, Object> sdcInfos, SubscriberInfo subscriberInfo, ServiceOrder serviceOrder) {
247
248     subscriberInfo.getGlobalSubscriberId();
249     ServiceModel service = new ServiceModel();
250     service.setName(serviceOrderItem.getService().getName());
251     service.setDescription(serviceOrder.getDescription());
252     service.setServiceUuid(serviceOrderItem.getService().getServiceSpecification().getId());
253     service.setServiceInvariantUuid((String) sdcInfos.get("invariantUUID"));
254     service.setGlobalSubscriberId(subscriberInfo.getGlobalSubscriberId());
255     service.setServiceType((String) sdcInfos.get("name"));
256
257     ParametersModel parameters = new ParametersModel();
258     ArrayList<ResourceModel> resources = new ArrayList();
259
260     ArrayList<Object> resourceObjects = (ArrayList<Object>) sdcInfos.get("resourceSpecification");
261
262     for (int i = 0; i < resourceObjects.size(); i++) {
263
264       ResourceModel resourceModel = new ResourceModel((Map<String, Object>) resourceObjects.get(i));
265       ParametersModel resourceParameters = new ParametersModel();
266       resourceModel.setParameters(resourceParameters);
267       resources.add(resourceModel);
268
269     }
270     parameters.setResources(resources);
271     List<UserParams> userParams = retrieveUserParamsFromServiceCharacteristics(
272         serviceOrderItem.getService().getServiceCharacteristic());
273
274     // If there are ServiceCharacteristics add them to requestInputs
275     if (!userParams.isEmpty()) {
276       Map<String, String> requestInputs = new HashMap<String, String>();
277       for (int i = 0; i < userParams.size(); i++) {
278         requestInputs.put(userParams.get(i).getName(), userParams.get(i).getValue());
279       }
280
281       parameters.setRequestInputs(requestInputs);
282     }
283     service.setParameters(parameters);
284
285     return service;
286   }
287
288   /**
289    * Build a list of UserParams for the SO request by browsing a list of ServiceCharacteristics from
290    * SDC
291    */
292   private List<UserParams> retrieveUserParamsFromServiceCharacteristics(
293       List<ServiceCharacteristic> characteristics) {
294     List<UserParams> userParams = new ArrayList<>();
295     UserParams userParam;
296
297     if (!CollectionUtils.isEmpty(characteristics)) {
298       for (ServiceCharacteristic characteristic : characteristics) {
299         // Check is the characteristic is of type object, if proceed as before to allow for
300         // backwards compatibility.
301         if (characteristic.getValueType() != null && !characteristic.getValueType().isEmpty()
302             && characteristic.getValueType().equals("object")) {
303           ObjectMapper mapper = new ObjectMapper();
304           JsonNode jsonNode = null;
305           try {
306             jsonNode = mapper.readTree(characteristic.getValue().getServiceCharacteristicValue());
307           } catch (IOException e) {
308             LOGGER.error("Failed to read object json {} , exception is ",
309                 characteristic.getValue().getServiceCharacteristicValue(), e.getMessage());
310           }
311           ObjectNode objectNode = (ObjectNode) jsonNode;
312           Iterator<Map.Entry<String, JsonNode>> iter = objectNode.fields();
313           while (iter.hasNext()) {
314             Map.Entry<String, JsonNode> entry = iter.next();
315             if (!entry.getValue().isArray()) {
316               userParam = new UserParams(entry.getKey(), entry.getValue().asText());
317             } else {
318               ArrayNode arrayNode = (ArrayNode) entry.getValue();
319               String arrayNodeValueString = arrayNode.toString();
320               userParam = new UserParams(entry.getKey(), arrayNodeValueString);
321             }
322             userParams.add(userParam);
323           }
324         }
325         // as UserParams for all other types, boolean, string, integer etc
326         else {
327           userParam = new UserParams(characteristic.getName(),
328               characteristic.getValue().getServiceCharacteristicValue());
329           userParams.add(userParam);
330         }
331       }
332     }
333
334     return userParams;
335   }
336
337
338 }