Remove legacy certificate handling
[sdc.git] / catalog-be / src / main / java / org / openecomp / sdc / be / servlets / ComponentInstanceServlet.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * SDC
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
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  * ============LICENSE_END=========================================================
19  */
20 package org.openecomp.sdc.be.servlets;
21
22 import com.fasterxml.jackson.core.JsonProcessingException;
23 import com.fasterxml.jackson.databind.ObjectMapper;
24 import com.fasterxml.jackson.databind.SerializationFeature;
25 import com.google.gson.Gson;
26 import com.google.gson.GsonBuilder;
27 import com.google.gson.reflect.TypeToken;
28 import com.jcabi.aspects.Loggable;
29 import fj.data.Either;
30 import io.swagger.v3.oas.annotations.Operation;
31 import io.swagger.v3.oas.annotations.Parameter;
32 import io.swagger.v3.oas.annotations.media.ArraySchema;
33 import io.swagger.v3.oas.annotations.media.Content;
34 import io.swagger.v3.oas.annotations.media.Schema;
35 import io.swagger.v3.oas.annotations.responses.ApiResponse;
36 import io.swagger.v3.oas.annotations.servers.Server;
37 import io.swagger.v3.oas.annotations.tags.Tag;
38 import java.io.IOException;
39 import java.io.InputStream;
40 import java.lang.reflect.Type;
41 import java.util.ArrayList;
42 import java.util.Arrays;
43 import java.util.Collections;
44 import java.util.List;
45 import java.util.Map;
46 import java.util.Optional;
47 import java.util.Set;
48 import javax.inject.Inject;
49 import javax.servlet.http.HttpServletRequest;
50 import javax.ws.rs.Consumes;
51 import javax.ws.rs.DELETE;
52 import javax.ws.rs.GET;
53 import javax.ws.rs.HeaderParam;
54 import javax.ws.rs.POST;
55 import javax.ws.rs.PUT;
56 import javax.ws.rs.Path;
57 import javax.ws.rs.PathParam;
58 import javax.ws.rs.Produces;
59 import javax.ws.rs.QueryParam;
60 import javax.ws.rs.core.Context;
61 import javax.ws.rs.core.MediaType;
62 import javax.ws.rs.core.Response;
63 import org.apache.commons.collections.CollectionUtils;
64 import org.apache.commons.io.IOUtils;
65 import org.apache.commons.lang3.StringUtils;
66 import org.openecomp.sdc.be.components.impl.ComponentBusinessLogic;
67 import org.openecomp.sdc.be.components.impl.ComponentBusinessLogicProvider;
68 import org.openecomp.sdc.be.components.impl.ComponentInstanceBusinessLogic;
69 import org.openecomp.sdc.be.components.impl.ComponentNodeFilterBusinessLogic;
70 import org.openecomp.sdc.be.components.impl.GroupBusinessLogic;
71 import org.openecomp.sdc.be.components.impl.ResourceImportManager;
72 import org.openecomp.sdc.be.components.impl.exceptions.BusinessLogicException;
73 import org.openecomp.sdc.be.components.impl.exceptions.ByActionStatusComponentException;
74 import org.openecomp.sdc.be.components.impl.exceptions.ByResponseFormatComponentException;
75 import org.openecomp.sdc.be.components.impl.exceptions.ComponentException;
76 import org.openecomp.sdc.be.config.BeEcompErrorManager;
77 import org.openecomp.sdc.be.dao.api.ActionStatus;
78 import org.openecomp.sdc.be.datamodel.ForwardingPaths;
79 import org.openecomp.sdc.be.datatypes.elements.CINodeFilterDataDefinition;
80 import org.openecomp.sdc.be.datatypes.elements.GetInputValueDataDefinition;
81 import org.openecomp.sdc.be.datatypes.elements.ToscaGetFunctionDataDefinition;
82 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
83 import org.openecomp.sdc.be.datatypes.enums.CreatedFrom;
84 import org.openecomp.sdc.be.datatypes.enums.JsonPresentationFields;
85 import org.openecomp.sdc.be.datatypes.enums.PropertySource;
86 import org.openecomp.sdc.be.datatypes.tosca.ToscaGetFunctionType;
87 import org.openecomp.sdc.be.externalapi.servlet.representation.ReplaceVNFInfo;
88 import org.openecomp.sdc.be.impl.ComponentsUtils;
89 import org.openecomp.sdc.be.impl.ServletUtils;
90 import org.openecomp.sdc.be.info.CreateAndAssotiateInfo;
91 import org.openecomp.sdc.be.info.GroupDefinitionInfo;
92 import org.openecomp.sdc.be.model.ComponentInstance;
93 import org.openecomp.sdc.be.model.ComponentInstanceAttribute;
94 import org.openecomp.sdc.be.model.ComponentInstanceInput;
95 import org.openecomp.sdc.be.model.ComponentInstanceProperty;
96 import org.openecomp.sdc.be.model.PropertyConstraint;
97 import org.openecomp.sdc.be.model.RequirementCapabilityRelDef;
98 import org.openecomp.sdc.be.model.RequirementDefinition;
99 import org.openecomp.sdc.be.model.Service;
100 import org.openecomp.sdc.be.model.User;
101 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
102 import org.openecomp.sdc.be.model.operations.impl.PropertyOperation.PropertyConstraintDeserialiser;
103 import org.openecomp.sdc.be.resources.data.ComponentMetadataData;
104 import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum;
105 import org.openecomp.sdc.common.api.Constants;
106 import org.openecomp.sdc.common.datastructure.Wrapper;
107 import org.openecomp.sdc.common.log.elements.LoggerSupportability;
108 import org.openecomp.sdc.common.log.enums.LoggerSupportabilityActions;
109 import org.openecomp.sdc.common.log.enums.StatusCode;
110 import org.openecomp.sdc.common.log.wrappers.Logger;
111 import org.openecomp.sdc.exception.ResponseFormat;
112 import org.springframework.stereotype.Controller;
113
114 /**
115  * Root resource (exposed at "/" path) .json.
116  */
117 @Loggable(prepend = true, value = Loggable.DEBUG, trim = false)
118 @Path("/v1/catalog")
119 @Tag(name = "SDCE-2 APIs")
120 @Server(url = "/sdc2/rest")
121 @Controller
122 public class ComponentInstanceServlet extends AbstractValidationsServlet {
123
124     private static final String FAILED_TO_GET_PROPERTIES_OF_COMPONENT_INSTANCE_ID_IN_WITH_ID = "Failed to get properties of component instance ID: {} in {} with ID: {}";
125     private static final String GET_GROUP_ARTIFACT_BY_ID = "getGroupArtifactById";
126     private static final String GET_GROUP_ARTIFACT_BY_ID_UNEXPECTED_EXCEPTION = "getGroupArtifactById unexpected exception";
127     private static final String GET_START_HANDLE_REQUEST_OF = "(GET) Start handle request of {}";
128     private static final String START_HANDLE_REQUEST_OF_UPDATE_RESOURCE_INSTANCE_PROPERTY_RECEIVED_PROPERTY_IS = "Start handle request of updateResourceInstanceProperty. Received property is {}";
129     private static final String START_HANDLE_REQUEST_OF_UPDATE_RESOURCE_INSTANCE_ATTRIBUTE_RECEIVED_ATTRIBUTE_IS = "Start handle request of updateResourceInstanceAttribute. Received attribute is {}";
130     private static final String UPDATE_RESOURCE_INSTANCE = "Update Resource Instance";
131     private static final String RESOURCE_INSTANCE_UPDATE_RESOURCE_INSTANCE = "Resource Instance - updateResourceInstance";
132     private static final String UPDATE_RESOURCE_INSTANCE_WITH_EXCEPTION = "update resource instance with exception";
133     private static final String FAILED_TO_CONVERT_RECEIVED_DATA_TO_BE_FORMAT = "Failed to convert received data to BE format.";
134     private static final String EMPTY_BODY_WAS_SENT = "Empty body was sent.";
135     private static final String START_HANDLE_REQUEST_OF = "Start handle request of {}";
136     private static final String UNSUPPORTED_COMPONENT_TYPE = "Unsupported component type {}";
137     private static final String CREATE_AND_ASSOCIATE_RI_FAILED_WITH_EXCEPTION = "create and associate RI failed with exception: {}";
138     private static final Logger log = Logger.getLogger(ComponentInstanceServlet.class);
139     private static final Type PROPERTY_CONSTRAINT_TYPE = new TypeToken<PropertyConstraint>() {
140     }.getType();
141     private static final Gson gsonDeserializer = new GsonBuilder().registerTypeAdapter(PROPERTY_CONSTRAINT_TYPE, new PropertyConstraintDeserialiser())
142         .create();
143     private static final LoggerSupportability loggerSupportability = LoggerSupportability.getLogger(ComponentInstanceServlet.class.getName());
144     private static final String SERVICES = "services";
145     private final GroupBusinessLogic groupBL;
146     private final ComponentNodeFilterBusinessLogic nodeFilterBusinessLogic;
147     private final ComponentBusinessLogicProvider componentBusinessLogicProvider;
148
149     @Inject
150     public ComponentInstanceServlet(GroupBusinessLogic groupBL,
151                                     ComponentInstanceBusinessLogic componentInstanceBL, ComponentsUtils componentsUtils, ServletUtils servletUtils,
152                                     ResourceImportManager resourceImportManager, ComponentNodeFilterBusinessLogic nodeFilterBusinessLogic,
153                                     ComponentBusinessLogicProvider componentBusinessLogicProvider) {
154         super(componentInstanceBL, componentsUtils, servletUtils, resourceImportManager);
155         this.groupBL = groupBL;
156         this.nodeFilterBusinessLogic = nodeFilterBusinessLogic;
157         this.componentBusinessLogicProvider = componentBusinessLogicProvider;
158     }
159
160     @POST
161     @Path("/{containerComponentType}/{componentId}/resourceInstance")
162     @Consumes(MediaType.APPLICATION_JSON)
163     @Produces(MediaType.APPLICATION_JSON)
164     @Operation(description = "Create ComponentInstance", method = "POST", summary = "Returns created ComponentInstance", responses = {
165         @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
166         @ApiResponse(responseCode = "201", description = "Component created"),
167         @ApiResponse(responseCode = "403", description = "Restricted operation"),
168         @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
169         @ApiResponse(responseCode = "409", description = "Component instance already exist")})
170     public Response createComponentInstance(@Parameter(description = "RI object to be created", required = true) String data,
171                                             @PathParam("componentId") final String containerComponentId,
172                                             @Parameter(description = "valid values: resources / services", schema = @Schema(allowableValues = {
173                                                 ComponentTypeEnum.RESOURCE_PARAM_NAME,
174                                                 ComponentTypeEnum.SERVICE_PARAM_NAME})) @PathParam("containerComponentType") final String containerComponentType,
175                                             @HeaderParam(value = Constants.USER_ID_HEADER) @Parameter(description = "USER_ID of modifier user", required = true) String userId,
176                                             @Context final HttpServletRequest request) {
177         validateNotEmptyBody(data);
178         final ComponentInstance componentInstance;
179         try {
180             componentInstance = RepresentationUtils.fromRepresentation(data, ComponentInstance.class);
181             componentInstance.setInvariantName(null);
182             componentInstance.setCreatedFrom(CreatedFrom.UI);
183         } catch (final Exception e) {
184             BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Create Component Instance");
185             log.debug("create component instance failed with exception", e);
186             return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT, containerComponentType));
187         }
188         loggerSupportability
189             .log(LoggerSupportabilityActions.CREATE_INSTANCE, StatusCode.STARTED, "Starting to create component instance by {}", userId);
190         if (componentInstanceBusinessLogic == null) {
191             log.debug(UNSUPPORTED_COMPONENT_TYPE, containerComponentType);
192             return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.UNSUPPORTED_ERROR, containerComponentType));
193         }
194         final ComponentInstance actionResponse = componentInstanceBusinessLogic
195             .createComponentInstance(containerComponentType, containerComponentId, userId, componentInstance);
196         loggerSupportability.log(LoggerSupportabilityActions.CREATE_INSTANCE, actionResponse.getComponentMetadataForSupportLog(), StatusCode.COMPLETE,
197             "Ending to create component instance by user {}", userId);
198         return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.CREATED), actionResponse);
199     }
200
201     @POST
202     @Path("/{containerComponentType}/{componentId}/resourceInstance/{componentInstanceId}")
203     @Consumes(MediaType.APPLICATION_JSON)
204     @Produces(MediaType.APPLICATION_JSON)
205     @Operation(description = "Update resource instance", method = "POST", summary = "Returns updated resource instance", responses = {
206         @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
207         @ApiResponse(responseCode = "200", description = "Resource instance updated"),
208         @ApiResponse(responseCode = "403", description = "Restricted operation"),
209         @ApiResponse(responseCode = "400", description = "Invalid content / Missing content")})
210     public Response updateComponentInstanceMetadata(@PathParam("componentId") final String componentId,
211                                                     @PathParam("componentInstanceId") final String componentInstanceId,
212                                                     @Parameter(description = "valid values: resources / services / products", schema = @Schema(allowableValues = {
213                                                         ComponentTypeEnum.RESOURCE_PARAM_NAME, ComponentTypeEnum.SERVICE_PARAM_NAME,
214                                                         ComponentTypeEnum.PRODUCT_PARAM_NAME})) @PathParam("containerComponentType") final String containerComponentType,
215                                                     @Context final HttpServletRequest request) throws IOException, BusinessLogicException {
216         final String url = request.getMethod() + " " + request.getRequestURI();
217         log.debug(START_HANDLE_REQUEST_OF, url);
218         loggerSupportability.log(LoggerSupportabilityActions.UPDATE_COMPONENT_INSTANCE, StatusCode.STARTED, "update Component Instance Metadata");
219         final String userId = request.getHeader(Constants.USER_ID_HEADER);
220         try {
221             if (componentInstanceBusinessLogic == null) {
222                 log.debug(UNSUPPORTED_COMPONENT_TYPE, containerComponentType);
223                 return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.UNSUPPORTED_ERROR, containerComponentType));
224             }
225             componentInstanceBusinessLogic.validateUser(userId);
226             log.debug(START_HANDLE_REQUEST_OF, url);
227             final byte[] bytes = IOUtils.toByteArray(request.getInputStream());
228             if (bytes == null || bytes.length == 0) {
229                 log.info(EMPTY_BODY_WAS_SENT);
230                 return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
231             }
232             final String data = new String(bytes);
233             final ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(containerComponentType);
234             final Either<ComponentInstance, ResponseFormat> convertResponse = convertToResourceInstance(data);
235             if (convertResponse.isRight()) {
236                 BeEcompErrorManager.getInstance().logBeSystemError(RESOURCE_INSTANCE_UPDATE_RESOURCE_INSTANCE);
237                 log.debug(FAILED_TO_CONVERT_RECEIVED_DATA_TO_BE_FORMAT);
238                 return buildErrorResponse(convertResponse.right().value());
239             }
240             final ComponentInstance componentInstance = convertResponse.left().value();
241             final Either<ComponentInstance, ResponseFormat> actionResponse = componentInstanceBusinessLogic
242                 .updateComponentInstanceMetadata(containerComponentType, componentId, componentInstanceId, userId, componentInstance);
243             loggerSupportability
244                 .log(LoggerSupportabilityActions.UPDATE_COMPONENT_INSTANCE, actionResponse.left().value().getComponentMetadataForSupportLog(),
245                     StatusCode.COMPLETE, "update Component Instance Metadata by {}", userId);
246             if (actionResponse.isRight()) {
247                 return buildErrorResponse(actionResponse.right().value());
248             }
249             final ComponentInstance resultValue = actionResponse.left().value();
250             if (ComponentTypeEnum.SERVICE.equals(componentTypeEnum) || ComponentTypeEnum.RESOURCE.equals(componentTypeEnum)) {
251                 if (CollectionUtils.isNotEmpty(componentInstance.getDirectives())) {
252                     final Optional<CINodeFilterDataDefinition> nodeFilterDataDefinition = nodeFilterBusinessLogic
253                         .createNodeFilterIfNotExist(componentId, componentInstanceId, true, componentTypeEnum);
254                     if (!nodeFilterDataDefinition.isPresent()) {
255                         BeEcompErrorManager.getInstance().logBeSystemError("Failed to create node filter.");
256                         log.error("Failed to create node filter.");
257                         return buildErrorResponse(convertResponse.right().value());
258                     }
259                     resultValue.setNodeFilter(nodeFilterDataDefinition.get());
260                 } else {
261                     final Optional<String> result = nodeFilterBusinessLogic
262                         .deleteNodeFilterIfExists(componentId, componentInstanceId, true, componentTypeEnum);
263                     if (!result.isPresent()) {
264                         BeEcompErrorManager.getInstance().logBeSystemError("Failed to delete node filter.");
265                         log.error("Failed to delete node filter.");
266                         return buildErrorResponse(convertResponse.right().value());
267                     }
268                     resultValue.setNodeFilter(null);
269                 }
270             }
271             return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), actionResponse.left().value());
272         } catch (final Exception e) {
273             BeEcompErrorManager.getInstance().logBeRestApiGeneralError(UPDATE_RESOURCE_INSTANCE);
274             log.debug(UPDATE_RESOURCE_INSTANCE_WITH_EXCEPTION, e);
275             throw e;
276         }
277     }
278
279     @POST
280     @Path("/{containerComponentType}/{componentId}/resourceInstance/multipleComponentInstance")
281     @Consumes(MediaType.APPLICATION_JSON)
282     @Produces(MediaType.APPLICATION_JSON)
283     @Operation(description = "Update resource instance multiple component", method = "POST", summary = "Returns updated resource instance", responses = {
284         @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
285         @ApiResponse(responseCode = "200", description = "Resource instance updated"),
286         @ApiResponse(responseCode = "403", description = "Restricted operation"),
287         @ApiResponse(responseCode = "400", description = "Invalid content / Missing content")})
288     public Response updateMultipleComponentInstance(@PathParam("componentId") final String componentId,
289                                                     @Parameter(description = "valid values: resources / services / products", schema = @Schema(allowableValues = {
290                                                         ComponentTypeEnum.RESOURCE_PARAM_NAME, ComponentTypeEnum.SERVICE_PARAM_NAME,
291                                                         ComponentTypeEnum.PRODUCT_PARAM_NAME})) @PathParam("containerComponentType") final String containerComponentType,
292                                                     @Context final HttpServletRequest request,
293                                                     @Parameter(description = "Component Instance JSON Array", required = true) final String componentInstanceJsonArray) {
294         String url = request.getMethod() + " " + request.getRequestURI();
295         log.debug(START_HANDLE_REQUEST_OF, url);
296         try {
297             log.debug(START_HANDLE_REQUEST_OF, url);
298             if (componentInstanceJsonArray == null || componentInstanceJsonArray.length() == 0) {
299                 log.info("Empty JSON list was sent.");
300                 return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
301             }
302             String userId = request.getHeader(Constants.USER_ID_HEADER);
303             if (componentInstanceBusinessLogic == null) {
304                 log.debug(UNSUPPORTED_COMPONENT_TYPE, containerComponentType);
305                 return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.UNSUPPORTED_ERROR, containerComponentType));
306             }
307             Either<List<ComponentInstance>, ResponseFormat> convertResponse = convertToMultipleResourceInstance(componentInstanceJsonArray);
308             if (convertResponse.isRight()) {
309                 // Using both ECOMP error methods, show to Sofer
310                 BeEcompErrorManager.getInstance().logBeSystemError(RESOURCE_INSTANCE_UPDATE_RESOURCE_INSTANCE);
311                 log.debug(FAILED_TO_CONVERT_RECEIVED_DATA_TO_BE_FORMAT);
312                 return buildErrorResponse(convertResponse.right().value());
313             }
314             List<ComponentInstance> componentInstanceList = convertResponse.left().value();
315             List<ComponentInstance> actionResponse = componentInstanceBusinessLogic
316                 .updateComponentInstance(containerComponentType, null, componentId, userId, componentInstanceList, true);
317             return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), actionResponse);
318         } catch (Exception e) {
319             BeEcompErrorManager.getInstance().logBeRestApiGeneralError(UPDATE_RESOURCE_INSTANCE);
320             log.debug(UPDATE_RESOURCE_INSTANCE_WITH_EXCEPTION, e);
321             throw e;
322         }
323     }
324
325     @DELETE
326     @Path("/{containerComponentType}/{componentId}/resourceInstance/{resourceInstanceId}")
327     @Consumes(MediaType.APPLICATION_JSON)
328     @Produces(MediaType.APPLICATION_JSON)
329     @Operation(description = "Delete ResourceInstance", method = "DELETE", summary = "Returns delete resourceInstance", responses = {
330         @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
331         @ApiResponse(responseCode = "201", description = "ResourceInstance deleted"),
332         @ApiResponse(responseCode = "403", description = "Restricted operation"),
333         @ApiResponse(responseCode = "400", description = "Invalid content / Missing content")})
334     public Response deleteResourceInstance(@PathParam("componentId") final String componentId,
335                                            @PathParam("resourceInstanceId") final String resourceInstanceId,
336                                            @Parameter(description = "valid values: resources / services / products", schema = @Schema(allowableValues = {
337                                                ComponentTypeEnum.RESOURCE_PARAM_NAME, ComponentTypeEnum.SERVICE_PARAM_NAME,
338                                                ComponentTypeEnum.PRODUCT_PARAM_NAME})) @PathParam("containerComponentType") final String containerComponentType,
339                                            @Context final HttpServletRequest request) {
340         String url = request.getMethod() + " " + request.getRequestURI();
341         try {
342             log.debug(START_HANDLE_REQUEST_OF, url);
343             if (componentInstanceBusinessLogic == null) {
344                 log.debug(UNSUPPORTED_COMPONENT_TYPE, containerComponentType);
345                 return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.UNSUPPORTED_ERROR, containerComponentType));
346             }
347             String userId = request.getHeader(Constants.USER_ID_HEADER);
348             ComponentInstance actionResponse = componentInstanceBusinessLogic
349                 .deleteComponentInstance(containerComponentType, componentId, resourceInstanceId, userId);
350             loggerSupportability
351                 .log(LoggerSupportabilityActions.DELETE_COMPONENT_INSTANCE, actionResponse.getComponentMetadataForSupportLog(), StatusCode.STARTED,
352                     "DELETE_COMPONENT_INSTANCE by user {}", userId);
353             loggerSupportability
354                 .log(LoggerSupportabilityActions.DELETE_COMPONENT_INSTANCE, actionResponse.getComponentMetadataForSupportLog(), StatusCode.COMPLETE,
355                     "DELETE_COMPONENT_INSTANCE by user {}", userId);
356             return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), actionResponse);
357         } catch (Exception e) {
358             BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Delete Resource Instance");
359             log.debug("delete resource instance with exception", e);
360             return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
361         }
362     }
363
364     @Parameter(description = "allowed values are resources /services / products", schema = @Schema(allowableValues = {
365         ComponentTypeEnum.RESOURCE_PARAM_NAME, ComponentTypeEnum.SERVICE_PARAM_NAME, ComponentTypeEnum.PRODUCT_PARAM_NAME}), required = true)
366     @POST
367     @Path("/{containerComponentType}/{componentId}/resourceInstance/associate")
368     @Consumes(MediaType.APPLICATION_JSON)
369     @Produces(MediaType.APPLICATION_JSON)
370     @Operation(description = "Associate RI to RI", method = "POST", summary = "Returns created RelationshipInfo", responses = {
371         @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
372         @ApiResponse(responseCode = "201", description = "Relationship created"),
373         @ApiResponse(responseCode = "403", description = "Missing information"),
374         @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
375         @ApiResponse(responseCode = "409", description = "Relationship already exist")})
376     public Response associateRIToRI(
377         @Parameter(description = "unique id of the container component") @PathParam("componentId") final String componentId,
378         @Parameter(description = "allowed values are resources /services / products", schema = @Schema(allowableValues = {
379             ComponentTypeEnum.RESOURCE_PARAM_NAME, ComponentTypeEnum.SERVICE_PARAM_NAME,
380             ComponentTypeEnum.PRODUCT_PARAM_NAME}), required = true) @PathParam("containerComponentType") final String containerComponentType,
381         @HeaderParam(value = Constants.USER_ID_HEADER) String userId, @Parameter(description = "RelationshipInfo", required = true) String data,
382         @Context final HttpServletRequest request) {
383         String url = request.getMethod() + " " + request.getRequestURI();
384         log.debug(START_HANDLE_REQUEST_OF, url);
385         loggerSupportability
386             .log(LoggerSupportabilityActions.ASSOCIATE_RI_TO_RI, StatusCode.STARTED, "Starting to associate RI To RI for component {} ",
387                 componentId + " by " + userId);
388         try {
389             log.debug(START_HANDLE_REQUEST_OF, url);
390             ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(containerComponentType);
391             if (componentInstanceBusinessLogic == null) {
392                 log.debug(UNSUPPORTED_COMPONENT_TYPE, containerComponentType);
393                 return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.UNSUPPORTED_ERROR, containerComponentType));
394             }
395             RequirementCapabilityRelDef requirementDef = convertToRequirementCapabilityRelDef(data);
396             requirementDef.setOriginUI(true);
397             RequirementCapabilityRelDef actionResponse = componentInstanceBusinessLogic
398                 .associateRIToRI(componentId, userId, requirementDef, componentTypeEnum);
399             loggerSupportability
400                 .log(LoggerSupportabilityActions.ASSOCIATE_RI_TO_RI, StatusCode.COMPLETE, "Ended associate RI To RI for component {} ",
401                     componentId + " by " + userId);
402             return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), actionResponse);
403         } catch (Exception e) {
404             if (!e.getClass().equals(ComponentException.class)) {
405                 BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Associate Resource Instance");
406                 log.debug("associate resource instance to another RI with exception", e);
407                 return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
408             }
409             throw e;
410         }
411     }
412
413     @PUT
414     @Path("/{containerComponentType}/{componentId}/resourceInstance/dissociate")
415     @Consumes(MediaType.APPLICATION_JSON)
416     @Produces(MediaType.APPLICATION_JSON)
417     @Operation(description = "Dissociate RI from RI", method = "PUT", summary = "Returns deleted RelationshipInfo", responses = {
418         @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
419         @ApiResponse(responseCode = "201", description = "Relationship deleted"),
420         @ApiResponse(responseCode = "403", description = "Missing information"),
421         @ApiResponse(responseCode = "400", description = "Invalid content / Missing content")})
422     public Response dissociateRIFromRI(
423         @Parameter(description = "allowed values are resources /services / products", schema = @Schema(allowableValues = {
424             ComponentTypeEnum.RESOURCE_PARAM_NAME, ComponentTypeEnum.SERVICE_PARAM_NAME,
425             ComponentTypeEnum.PRODUCT_PARAM_NAME}), required = true) @PathParam("containerComponentType") final String containerComponentType,
426         @Parameter(description = "unique id of the container component") @PathParam("componentId") final String componentId,
427         @HeaderParam(value = Constants.USER_ID_HEADER) String userId, @Parameter(description = "RelationshipInfo", required = true) String data,
428         @Context final HttpServletRequest request) {
429         String url = request.getMethod() + " " + request.getRequestURI();
430         log.debug(START_HANDLE_REQUEST_OF, url);
431         loggerSupportability
432             .log(LoggerSupportabilityActions.UN_ASSOCIATE_RI_TO_RI, StatusCode.STARTED, "Starting to undo associate RI To RI for component {} ",
433                 componentId + " by " + userId);
434         try {
435             log.debug(START_HANDLE_REQUEST_OF, url);
436             ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(containerComponentType);
437             if (componentInstanceBusinessLogic == null) {
438                 log.debug(UNSUPPORTED_COMPONENT_TYPE, containerComponentType);
439                 return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.UNSUPPORTED_ERROR, containerComponentType));
440             }
441             RequirementCapabilityRelDef requirementDef = convertToRequirementCapabilityRelDef(data);
442             RequirementCapabilityRelDef actionResponse = componentInstanceBusinessLogic
443                 .dissociateRIFromRI(componentId, userId, requirementDef, componentTypeEnum);
444             loggerSupportability
445                 .log(LoggerSupportabilityActions.UN_ASSOCIATE_RI_TO_RI, StatusCode.COMPLETE, "Ended undo associate RI To RI for component {} ",
446                     componentId + " by " + userId);
447             return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), actionResponse);
448         } catch (Exception e) {
449             BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Dissociate Resource Instance");
450             log.debug("dissociate resource instance from service failed with exception", e);
451             throw e;
452         }
453     }
454
455     @POST
456     @Path("/{containerComponentType}/{componentId}/resourceInstance/createAndAssociate")
457     @Consumes(MediaType.APPLICATION_JSON)
458     @Produces(MediaType.APPLICATION_JSON)
459     @Operation(description = "Create RI and associate RI to RI", method = "POST", summary = "Returns created RI and RelationshipInfo", responses = {
460         @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
461         @ApiResponse(responseCode = "201", description = "RI created"), @ApiResponse(responseCode = "403", description = "Restricted operation"),
462         @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
463         @ApiResponse(responseCode = "409", description = "Relationship already exist")})
464     public Response createAndAssociateRIToRI(@PathParam("componentId") final String componentId,
465                                              @Parameter(description = "valid values: resources / services", schema = @Schema(allowableValues = {
466                                                  ComponentTypeEnum.RESOURCE_PARAM_NAME, ComponentTypeEnum.SERVICE_PARAM_NAME,
467                                                  ComponentTypeEnum.PRODUCT_PARAM_NAME})) @PathParam("containerComponentType") final String containerComponentType,
468                                              @Context final HttpServletRequest request) throws IOException {
469         String url = request.getMethod() + " " + request.getRequestURI();
470         log.debug(START_HANDLE_REQUEST_OF, url);
471         try {
472             log.debug(START_HANDLE_REQUEST_OF, url);
473             InputStream inputStream = request.getInputStream();
474             byte[] bytes = IOUtils.toByteArray(inputStream);
475             if (bytes == null || bytes.length == 0) {
476                 log.info(EMPTY_BODY_WAS_SENT);
477                 return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
478             }
479             String userId = request.getHeader(Constants.USER_ID_HEADER);
480             String data = new String(bytes);
481             if (componentInstanceBusinessLogic == null) {
482                 log.debug(UNSUPPORTED_COMPONENT_TYPE, containerComponentType);
483                 return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.UNSUPPORTED_ERROR, containerComponentType));
484             }
485             Either<CreateAndAssotiateInfo, ActionStatus> convertStatus = convertJsonToObject(data, CreateAndAssotiateInfo.class);
486             if (convertStatus.isRight()) {
487                 BeEcompErrorManager.getInstance().logBeSystemError("Resource Instance - createAndAssociateRIToRI");
488                 log.debug(FAILED_TO_CONVERT_RECEIVED_DATA_TO_BE_FORMAT);
489                 Either<Object, ResponseFormat> formattedResponse = Either
490                     .right(getComponentsUtils().getResponseFormat(convertStatus.right().value()));
491                 return buildErrorResponse(formattedResponse.right().value());
492             }
493             CreateAndAssotiateInfo createAndAssotiateInfo = convertStatus.left().value();
494             RequirementCapabilityRelDef requirementDef = createAndAssotiateInfo.getAssociate();
495             requirementDef.setOriginUI(true);
496             Either<CreateAndAssotiateInfo, ResponseFormat> actionResponse = componentInstanceBusinessLogic
497                 .createAndAssociateRIToRI(containerComponentType, componentId, userId, createAndAssotiateInfo);
498             if (actionResponse.isRight()) {
499                 return buildErrorResponse(actionResponse.right().value());
500             }
501             return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.CREATED), actionResponse.left().value());
502         } catch (Exception e) {
503             BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Create and Associate Resource Instance");
504             log.debug("create and associate RI failed with exception", e);
505             throw e;
506         }
507     }
508
509     @POST
510     @Path("/{containerComponentType}/{componentId}/resourceInstance/{componentInstanceId}/properties")
511     @Consumes(MediaType.APPLICATION_JSON)
512     @Produces(MediaType.APPLICATION_JSON)
513     @Operation(description = "Update resource instance property", method = "POST", summary = "Returns updated resource instance property", responses = {
514         @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
515         @ApiResponse(responseCode = "201", description = "Resource instance created"),
516         @ApiResponse(responseCode = "403", description = "Restricted operation"),
517         @ApiResponse(responseCode = "400", description = "Invalid content / Missing content")})
518     public Response updateResourceInstanceProperties(@Parameter(description = "service id") @PathParam("componentId") final String componentId,
519                                                      @Parameter(description = "valid values: resources / services", schema = @Schema(allowableValues = {
520                                                          ComponentTypeEnum.RESOURCE_PARAM_NAME,
521                                                          ComponentTypeEnum.SERVICE_PARAM_NAME})) @PathParam("containerComponentType") final String containerComponentType,
522                                                      @Parameter(description = "resource instance id") @PathParam("componentInstanceId") final String componentInstanceId,
523                                                      @Parameter(description = "id of user initiating the operation") @HeaderParam(value = Constants.USER_ID_HEADER) String userId,
524                                                      @Context final HttpServletRequest request,
525                                                      @Parameter(description = "Component Instance Properties JSON Array", required = true) final String componentInstancePropertiesJsonArray) {
526         String url = request.getMethod() + " " + request.getRequestURI();
527         log.debug(START_HANDLE_REQUEST_OF, url);
528         loggerSupportability.log(LoggerSupportabilityActions.UPDATE_COMPONENT_INSTANCE, StatusCode.STARTED,
529             "Starting to update Resource Instance Properties for component {} ", componentId + " by " + userId);
530         Wrapper<ResponseFormat> errorWrapper = new Wrapper<>();
531         ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(containerComponentType);
532         List<ComponentInstanceProperty> propertiesToUpdate = new ArrayList<>();
533         if (errorWrapper.isEmpty()) {
534             Either<List<ComponentInstanceProperty>, ResponseFormat> propertiesToUpdateEither = convertMultipleProperties(
535                 componentInstancePropertiesJsonArray);
536             if (propertiesToUpdateEither.isRight()) {
537                 errorWrapper.setInnerElement(propertiesToUpdateEither.right().value());
538             } else {
539                 propertiesToUpdate = propertiesToUpdateEither.left().value();
540                 handleDeprecatedComponentInstancePropertyStructure(propertiesToUpdate, componentTypeEnum);
541             }
542         }
543         if (!errorWrapper.isEmpty()) {
544             return buildErrorResponse(errorWrapper.getInnerElement());
545         }
546         log.debug(START_HANDLE_REQUEST_OF_UPDATE_RESOURCE_INSTANCE_PROPERTY_RECEIVED_PROPERTY_IS, propertiesToUpdate);
547         if (componentInstanceBusinessLogic == null) {
548             log.debug(UNSUPPORTED_COMPONENT_TYPE, containerComponentType);
549             return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.UNSUPPORTED_ERROR, containerComponentType));
550         }
551         Either<List<ComponentInstanceProperty>, ResponseFormat> actionResponse = componentInstanceBusinessLogic
552             .createOrUpdatePropertiesValues(componentTypeEnum, componentId, componentInstanceId, propertiesToUpdate, userId);
553         if (actionResponse.isRight()) {
554             return buildErrorResponse(actionResponse.right().value());
555         }
556         List<ComponentInstanceProperty> resourceInstanceProperties = actionResponse.left().value();
557         ObjectMapper mapper = new ObjectMapper();
558         String result;
559         loggerSupportability.log(LoggerSupportabilityActions.UPDATE_COMPONENT_INSTANCE, StatusCode.COMPLETE,
560             "Ended update Resource Instance Properties for component {} ", componentId + " by " + userId);
561         try {
562             result = mapper.writeValueAsString(resourceInstanceProperties);
563         } catch (JsonProcessingException e) {
564             log.error(UPDATE_RESOURCE_INSTANCE_WITH_EXCEPTION, e.getMessage(), e);
565             throw new ByActionStatusComponentException(ActionStatus.GENERAL_ERROR);
566         }
567         loggerSupportability.log(LoggerSupportabilityActions.UPDATE_COMPONENT_INSTANCE, StatusCode.COMPLETE,
568             "Ended update Resource Instance Properties for component {} ", componentId + " by user " + userId);
569         return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), result);
570     }
571
572     private void handleDeprecatedComponentInstancePropertyStructure(final List<ComponentInstanceProperty> propertiesToUpdate,
573                                                                     final ComponentTypeEnum componentTypeEnum) {
574         propertiesToUpdate.stream().forEach(property -> {
575             if (property.getGetInputValues() != null) {
576                 property.getGetInputValues().stream()
577                     .forEach(getInputValue -> property.setToscaFunction(createToscaFunction(getInputValue, componentTypeEnum)));
578             }
579         });
580     }
581
582     private ToscaGetFunctionDataDefinition createToscaFunction(final GetInputValueDataDefinition getInput,
583                                                                final ComponentTypeEnum componentTypeEnum) {
584         final String[] inputIdSplit = getInput.getInputId().split("\\.");
585
586         ToscaGetFunctionDataDefinition toscaFunction = new ToscaGetFunctionDataDefinition();
587         toscaFunction.setFunctionType(ToscaGetFunctionType.GET_INPUT);
588         toscaFunction.setPropertyUniqueId(getInput.getInputId());
589         toscaFunction.setPropertySource(PropertySource.SELF);
590         toscaFunction.setPropertyName(inputIdSplit[1]);
591         toscaFunction.setSourceName(getSourceName(inputIdSplit[0], componentTypeEnum));
592         toscaFunction.setSourceUniqueId(inputIdSplit[0]);
593         toscaFunction.setPropertyPathFromSource(Collections.singletonList(inputIdSplit[1]));
594
595         return toscaFunction;
596     }
597
598     private String getSourceName(final String componentId, final ComponentTypeEnum componentTypeEnum) {
599         ComponentBusinessLogic compBL = componentBusinessLogicProvider.getInstance(componentTypeEnum);
600         final Either<ComponentMetadataData, StorageOperationStatus> componentEither = compBL.getComponentMetadata(componentId);
601         if (componentEither.isLeft()) {
602             return componentEither.left().value().getMetadataDataDefinition().getName();
603         }
604         return "";
605     }
606
607     @POST
608     @Path("/{containerComponentType}/{componentId}/resourceInstance/{componentInstanceId}/inputs")
609     @Consumes(MediaType.APPLICATION_JSON)
610     @Produces(MediaType.APPLICATION_JSON)
611     @Operation(description = "Update resource instance property", method = "POST", summary = "Returns updated resource instance property", responses = {
612         @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
613         @ApiResponse(responseCode = "201", description = "Resource instance created"),
614         @ApiResponse(responseCode = "403", description = "Restricted operation"),
615         @ApiResponse(responseCode = "400", description = "Invalid content / Missing content")})
616     public Response updateResourceInstanceInput(@Parameter(description = "service id") @PathParam("componentId") final String componentId,
617                                                 @Parameter(description = "valid values: resources / services", schema = @Schema(allowableValues = {
618                                                     ComponentTypeEnum.RESOURCE_PARAM_NAME,
619                                                     ComponentTypeEnum.SERVICE_PARAM_NAME})) @PathParam("containerComponentType") final String containerComponentType,
620                                                 @Parameter(description = "resource instance id") @PathParam("componentInstanceId") final String componentInstanceId,
621                                                 @Parameter(description = "id of user initiating the operation") @HeaderParam(value = Constants.USER_ID_HEADER) String userId,
622                                                 @Context final HttpServletRequest request,
623                                                 @Parameter(description = "Component Instance Properties JSON Array", required = true) final String componentInstanceInputsJsonArray) {
624         String url = request.getMethod() + " " + request.getRequestURI();
625         log.debug(START_HANDLE_REQUEST_OF, url);
626         Wrapper<ResponseFormat> errorWrapper = new Wrapper<>();
627         List<ComponentInstanceInput> inputsToUpdate = new ArrayList<>();
628         if (errorWrapper.isEmpty()) {
629             Either<List<ComponentInstanceInput>, ResponseFormat> inputsToUpdateEither = convertMultipleInputs(componentInstanceInputsJsonArray);
630             if (inputsToUpdateEither.isRight()) {
631                 errorWrapper.setInnerElement(inputsToUpdateEither.right().value());
632             } else {
633                 inputsToUpdate = inputsToUpdateEither.left().value();
634             }
635         }
636         if (!errorWrapper.isEmpty()) {
637             return buildErrorResponse(errorWrapper.getInnerElement());
638         }
639         log.debug(START_HANDLE_REQUEST_OF_UPDATE_RESOURCE_INSTANCE_PROPERTY_RECEIVED_PROPERTY_IS, inputsToUpdate);
640         ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(containerComponentType);
641         if (componentInstanceBusinessLogic == null) {
642             log.debug(UNSUPPORTED_COMPONENT_TYPE, containerComponentType);
643             return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.UNSUPPORTED_ERROR, containerComponentType));
644         }
645         Either<List<ComponentInstanceInput>, ResponseFormat> actionResponse = componentInstanceBusinessLogic
646             .createOrUpdateInstanceInputValues(componentTypeEnum, componentId, componentInstanceId, inputsToUpdate, userId);
647         if (actionResponse.isRight()) {
648             return buildErrorResponse(actionResponse.right().value());
649         }
650         List<ComponentInstanceInput> resourceInstanceInput = actionResponse.left().value();
651         ObjectMapper mapper = new ObjectMapper();
652         mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
653         String result;
654         loggerSupportability
655             .log(LoggerSupportabilityActions.UPDATE_PROPERTIES, StatusCode.COMPLETE, "Ending update Resource Instance Input for component {} ",
656                 componentId + " by " + userId);
657         try {
658             result = mapper.writeValueAsString(resourceInstanceInput);
659         } catch (JsonProcessingException e) {
660             log.error(UPDATE_RESOURCE_INSTANCE_WITH_EXCEPTION, e.getMessage(), e);
661             return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
662         }
663         loggerSupportability
664             .log(LoggerSupportabilityActions.UPDATE_PROPERTIES, StatusCode.COMPLETE, "Ending update Resource Instance Input for component {} ",
665                 componentId + " by user " + userId);
666         return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), result);
667     }
668
669     /**
670      * Updates ResourceInstance Attribute
671      *
672      * @param componentId
673      * @param containerComponentType
674      * @param componentInstanceId
675      * @param userId
676      * @param request
677      * @return
678      */
679     @POST
680     @Path("/{containerComponentType}/{componentId}/resourceInstance/{componentInstanceId}/attributes")
681     @Consumes(MediaType.APPLICATION_JSON)
682     @Produces(MediaType.APPLICATION_JSON)
683     @Operation(description = "Update resource instance attribute", method = "POST", summary = "Returns updated resource instance property", responses = {
684         @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
685         @ApiResponse(responseCode = "201", description = "Resource instance created"),
686         @ApiResponse(responseCode = "403", description = "Restricted operation"),
687         @ApiResponse(responseCode = "400", description = "Invalid content / Missing content")})
688     public Response updateResourceInstanceAttribute(@Parameter(description = "service id") @PathParam("componentId") final String componentId,
689                                                     @Parameter(description = "valid values: resources / services", schema = @Schema(allowableValues = {
690                                                         ComponentTypeEnum.RESOURCE_PARAM_NAME,
691                                                         ComponentTypeEnum.SERVICE_PARAM_NAME})) @PathParam("containerComponentType") final String containerComponentType,
692                                                     @Parameter(description = "resource instance id") @PathParam("componentInstanceId") final String componentInstanceId,
693                                                     @Parameter(description = "id of user initiating the operation") @HeaderParam(value = Constants.USER_ID_HEADER) final String userId,
694                                                     @Context final HttpServletRequest request,
695                                                     @Parameter(description = "Component Instance Properties JSON Array", required = true) final String componentInstanceAttributesJsonArray) {
696         final String url = request.getMethod() + " " + request.getRequestURI();
697         log.debug(START_HANDLE_REQUEST_OF, url);
698         loggerSupportability.log(LoggerSupportabilityActions.UPDATE_COMPONENT_INSTANCE, StatusCode.STARTED,
699             "Starting to update Resource Instance Attributes for component {} ", componentId + " by " + userId);
700         final Wrapper<ResponseFormat> errorWrapper = new Wrapper<>();
701         List<ComponentInstanceAttribute> attributesToUpdate = new ArrayList<>();
702         if (errorWrapper.isEmpty()) {
703             final Either<List<ComponentInstanceAttribute>, ResponseFormat> attributesToUpdateEither = convertMultipleAttributes(
704                 componentInstanceAttributesJsonArray);
705             if (attributesToUpdateEither.isRight()) {
706                 errorWrapper.setInnerElement(attributesToUpdateEither.right().value());
707             } else {
708                 attributesToUpdate = attributesToUpdateEither.left().value();
709             }
710         }
711         if (!errorWrapper.isEmpty()) {
712             return buildErrorResponse(errorWrapper.getInnerElement());
713         }
714         log.debug(START_HANDLE_REQUEST_OF_UPDATE_RESOURCE_INSTANCE_ATTRIBUTE_RECEIVED_ATTRIBUTE_IS, attributesToUpdate);
715         final ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(containerComponentType);
716         if (componentInstanceBusinessLogic == null) {
717             log.debug(UNSUPPORTED_COMPONENT_TYPE, containerComponentType);
718             return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.UNSUPPORTED_ERROR, containerComponentType));
719         }
720         final Either<List<ComponentInstanceAttribute>, ResponseFormat> actionResponse = componentInstanceBusinessLogic
721             .createOrUpdateAttributeValues(componentTypeEnum, componentId, componentInstanceId, attributesToUpdate, userId);
722         if (actionResponse.isRight()) {
723             return buildErrorResponse(actionResponse.right().value());
724         }
725         final List<ComponentInstanceAttribute> resourceInstanceAttributes = actionResponse.left().value();
726         final ObjectMapper mapper = new ObjectMapper();
727         String result;
728         loggerSupportability.log(LoggerSupportabilityActions.UPDATE_COMPONENT_INSTANCE, StatusCode.COMPLETE,
729             "Ended update Resource Instance Attributes for component {} ", componentId + " by " + userId);
730         try {
731             result = mapper.writeValueAsString(resourceInstanceAttributes);
732         } catch (JsonProcessingException e) {
733             log.error(UPDATE_RESOURCE_INSTANCE_WITH_EXCEPTION, e.getMessage(), e);
734             throw new ByActionStatusComponentException(ActionStatus.GENERAL_ERROR);
735         }
736         loggerSupportability.log(LoggerSupportabilityActions.UPDATE_COMPONENT_INSTANCE, StatusCode.COMPLETE,
737             "Ended update Resource Instance Attributes for component {} ", componentId + " by user " + userId);
738         return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), result);
739     }
740
741     @DELETE
742     @Path("/{containerComponentType}/{componentId}/resourceInstance/{componentInstanceId}/property/{propertyId}")
743     @Consumes(MediaType.APPLICATION_JSON)
744     @Produces(MediaType.APPLICATION_JSON)
745     @Operation(description = "Update resource instance", method = "DELETE", summary = "Returns deleted resource instance property", responses = {
746         @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
747         @ApiResponse(responseCode = "201", description = "Resource instance created"),
748         @ApiResponse(responseCode = "403", description = "Restricted operation"),
749         @ApiResponse(responseCode = "400", description = "Invalid content / Missing content")})
750     public Response deleteResourceInstanceProperty(@Parameter(description = "service id") @PathParam("componentId") final String componentId,
751                                                    @Parameter(description = "valid values: resources / services", schema = @Schema(allowableValues = {
752                                                        ComponentTypeEnum.RESOURCE_PARAM_NAME,
753                                                        ComponentTypeEnum.SERVICE_PARAM_NAME})) @PathParam("containerComponentType") final String containerComponentType,
754                                                    @Parameter(description = "resource instance id") @PathParam("componentInstanceId") final String componentInstanceId,
755                                                    @Parameter(description = "property id") @PathParam("propertyId") final String propertyId,
756                                                    @Parameter(description = "id of user initiating the operation") @HeaderParam(value = Constants.USER_ID_HEADER) String userId,
757                                                    @Context final HttpServletRequest request) {
758         loggerSupportability
759             .log(LoggerSupportabilityActions.UPDATE_PROPERTIES, StatusCode.STARTED, "Starting to delete Resource Instance Property for component {} ",
760                 componentId + " by " + userId);
761         String url = request.getMethod() + " " + request.getRequestURI();
762         log.debug(START_HANDLE_REQUEST_OF, url);
763         try {
764             ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(containerComponentType);
765             loggerSupportability
766                 .log(LoggerSupportabilityActions.UPDATE_PROPERTIES, StatusCode.COMPLETE, "Ended delete Resource Instance Property for component {} ",
767                     componentId + " by " + userId);
768             if (componentInstanceBusinessLogic == null) {
769                 log.debug(UNSUPPORTED_COMPONENT_TYPE, containerComponentType);
770                 return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.UNSUPPORTED_ERROR, containerComponentType));
771             }
772             Either<ComponentInstanceProperty, ResponseFormat> actionResponse = componentInstanceBusinessLogic
773                 .deletePropertyValue(componentTypeEnum, componentId, componentInstanceId, propertyId, userId);
774             if (actionResponse.isRight()) {
775                 return buildErrorResponse(actionResponse.right().value());
776             }
777             return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.NO_CONTENT), null);
778         } catch (Exception e) {
779             log.error(CREATE_AND_ASSOCIATE_RI_FAILED_WITH_EXCEPTION, e.getMessage(), e);
780             throw e;
781         }
782     }
783
784     @POST
785     @Path("/{containerComponentType}/{componentId}/resourceInstance/{componentInstanceId}/changeVersion")
786     @Consumes(MediaType.APPLICATION_JSON)
787     @Produces(MediaType.APPLICATION_JSON)
788     @Operation(description = "Update resource instance", method = "POST", summary = "Returns updated resource instance", responses = {
789         @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
790         @ApiResponse(responseCode = "201", description = "Resource instance created"),
791         @ApiResponse(responseCode = "403", description = "Restricted operation"),
792         @ApiResponse(responseCode = "400", description = "Invalid content / Missing content")})
793     public Response changeResourceInstanceVersion(@PathParam("componentId") final String componentId,
794                                                   @PathParam("componentInstanceId") final String componentInstanceId,
795                                                   @Parameter(description = "valid values: resources / services", schema = @Schema(allowableValues = {
796                                                       ComponentTypeEnum.RESOURCE_PARAM_NAME,
797                                                       ComponentTypeEnum.SERVICE_PARAM_NAME})) @PathParam("containerComponentType") final String containerComponentType,
798                                                   @Context final HttpServletRequest request) throws IOException {
799         String url = request.getMethod() + " " + request.getRequestURI();
800         log.debug(START_HANDLE_REQUEST_OF, url);
801         try (InputStream inputStream = request.getInputStream()) {
802             byte[] bytes = IOUtils.toByteArray(inputStream);
803             if (bytes == null || bytes.length == 0) {
804                 log.info(EMPTY_BODY_WAS_SENT);
805                 return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
806             }
807             String userId = request.getHeader(Constants.USER_ID_HEADER);
808             String data = new String(bytes);
809             if (componentInstanceBusinessLogic == null) {
810                 log.debug(UNSUPPORTED_COMPONENT_TYPE, containerComponentType);
811                 return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.UNSUPPORTED_ERROR, containerComponentType));
812             }
813             Either<ComponentInstance, ResponseFormat> convertResponse = convertToResourceInstance(data);
814             if (convertResponse.isRight()) {
815                 BeEcompErrorManager.getInstance().logBeSystemError(RESOURCE_INSTANCE_UPDATE_RESOURCE_INSTANCE);
816                 log.debug(FAILED_TO_CONVERT_RECEIVED_DATA_TO_BE_FORMAT);
817                 return buildErrorResponse(convertResponse.right().value());
818             }
819             ComponentInstance newResourceInstance = convertResponse.left().value();
820             ComponentInstance actionResponse = componentInstanceBusinessLogic
821                 .changeComponentInstanceVersion(containerComponentType, componentId, componentInstanceId, userId, newResourceInstance);
822             return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), actionResponse);
823         } catch (Exception e) {
824             BeEcompErrorManager.getInstance().logBeRestApiGeneralError(UPDATE_RESOURCE_INSTANCE);
825             log.debug(UPDATE_RESOURCE_INSTANCE_WITH_EXCEPTION, e);
826             throw e;
827         }
828     }
829
830     @POST
831     @Path("/{containerComponentType}/{componentId}/resourceInstance/{componentInstanceId}/groupInstance/{groupInstanceId}/property")
832     @Consumes(MediaType.APPLICATION_JSON)
833     @Produces(MediaType.APPLICATION_JSON)
834     @Operation(description = "Update resource instance property", method = "POST", summary = "Returns updated resource instance property", responses = {
835         @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
836         @ApiResponse(responseCode = "201", description = "Resource instance created"),
837         @ApiResponse(responseCode = "403", description = "Restricted operation"),
838         @ApiResponse(responseCode = "400", description = "Invalid content / Missing content")})
839     public Response updateGroupInstanceProperty(@Parameter(description = "service id") @PathParam("componentId") final String componentId,
840                                                 @Parameter(description = "valid values: resources / services", schema = @Schema(allowableValues = {
841                                                     ComponentTypeEnum.RESOURCE_PARAM_NAME,
842                                                     ComponentTypeEnum.SERVICE_PARAM_NAME})) @PathParam("containerComponentType") final String containerComponentType,
843                                                 @Parameter(description = "resource instance id") @PathParam("componentInstanceId") final String componentInstanceId,
844                                                 @Parameter(description = "group instance id") @PathParam("groupInstanceId") final String groupInstanceId,
845                                                 @Parameter(description = "id of user initiating the operation") @HeaderParam(value = Constants.USER_ID_HEADER) String userId,
846                                                 @Context final HttpServletRequest request) throws IOException {
847         String url = request.getMethod() + " " + request.getRequestURI();
848         log.debug(START_HANDLE_REQUEST_OF, url);
849         try {
850             loggerSupportability
851                 .log(LoggerSupportabilityActions.UPDATE_PROPERTIES, StatusCode.STARTED, "Starting update Group Instance Property for component {} ",
852                     componentId + " by " + userId);
853             Wrapper<String> dataWrapper = new Wrapper<>();
854             Wrapper<ResponseFormat> errorWrapper = new Wrapper<>();
855             Wrapper<ComponentInstanceProperty> propertyWrapper = new Wrapper<>();
856             validateInputStream(request, dataWrapper, errorWrapper);
857             if (errorWrapper.isEmpty()) {
858                 validateClassParse(dataWrapper.getInnerElement(), propertyWrapper, () -> ComponentInstanceProperty.class, errorWrapper);
859             }
860             if (!errorWrapper.isEmpty()) {
861                 return buildErrorResponse(errorWrapper.getInnerElement());
862             }
863             ComponentInstanceProperty property = propertyWrapper.getInnerElement();
864             log.debug(START_HANDLE_REQUEST_OF_UPDATE_RESOURCE_INSTANCE_PROPERTY_RECEIVED_PROPERTY_IS, property);
865             ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(containerComponentType);
866             if (componentInstanceBusinessLogic == null) {
867                 log.debug(UNSUPPORTED_COMPONENT_TYPE, containerComponentType);
868                 return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.UNSUPPORTED_ERROR, containerComponentType));
869             }
870             Either<ComponentInstanceProperty, ResponseFormat> actionResponse = componentInstanceBusinessLogic
871                 .createOrUpdateGroupInstancePropertyValue(componentTypeEnum, componentId, componentInstanceId, groupInstanceId, property, userId);
872             if (actionResponse.isRight()) {
873                 return buildErrorResponse(actionResponse.right().value());
874             }
875             ComponentInstanceProperty resourceInstanceProperty = actionResponse.left().value();
876             ObjectMapper mapper = new ObjectMapper();
877             String result = mapper.writeValueAsString(resourceInstanceProperty);
878             loggerSupportability
879                 .log(LoggerSupportabilityActions.UPDATE_PROPERTIES, StatusCode.COMPLETE, "Ended update Group Instance Property for component {} ",
880                     componentId + " by " + userId);
881             return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), result);
882         } catch (Exception e) {
883             log.error(CREATE_AND_ASSOCIATE_RI_FAILED_WITH_EXCEPTION, e.getMessage(), e);
884             throw e;
885         }
886     }
887
888     @GET
889     @Path("/{containerComponentType}/{componentId}/resourceInstance/{componentInstanceId}/groupInstance/{groupInstId}")
890     @Consumes(MediaType.APPLICATION_JSON)
891     @Produces(MediaType.APPLICATION_JSON)
892     @Operation(description = "Get group artifacts ", method = "GET", summary = "Returns artifacts metadata according to groupInstId", responses = {
893         @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
894         @ApiResponse(responseCode = "200", description = "group found"), @ApiResponse(responseCode = "403", description = "Restricted operation"),
895         @ApiResponse(responseCode = "404", description = "Group not found")})
896     public Response getGroupArtifactById(@PathParam("containerComponentType") final String containerComponentType,
897                                          @PathParam("componentId") final String componentId,
898                                          @PathParam("componentInstanceId") final String componentInstanceId,
899                                          @PathParam("groupInstId") final String groupInstId, @Context final HttpServletRequest request,
900                                          @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
901         String url = request.getMethod() + " " + request.getRequestURI();
902         log.debug(GET_START_HANDLE_REQUEST_OF, url);
903         try {
904             ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(containerComponentType);
905             Either<GroupDefinitionInfo, ResponseFormat> actionResponse = groupBL
906                 .getGroupInstWithArtifactsById(componentTypeEnum, componentId, componentInstanceId, groupInstId, userId, false);
907             if (actionResponse.isRight()) {
908                 log.debug("failed to get all non abstract {}", containerComponentType);
909                 return buildErrorResponse(actionResponse.right().value());
910             }
911             return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), actionResponse.left().value());
912         } catch (Exception e) {
913             BeEcompErrorManager.getInstance().logBeRestApiGeneralError(GET_GROUP_ARTIFACT_BY_ID);
914             log.debug(GET_GROUP_ARTIFACT_BY_ID_UNEXPECTED_EXCEPTION, e);
915             throw e;
916         }
917     }
918
919     // US831698
920     @GET
921     @Path("/{containerComponentType}/{containerComponentId}/componentInstances/{componentInstanceUniqueId}/properties")
922     @Consumes(MediaType.APPLICATION_JSON)
923     @Produces(MediaType.APPLICATION_JSON)
924     @Operation(description = "Get component instance properties", method = "GET", summary = "Returns component instance properties", responses = {
925         @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
926         @ApiResponse(responseCode = "200", description = "Properties found"),
927         @ApiResponse(responseCode = "403", description = "Restricted operation"),
928         @ApiResponse(responseCode = "404", description = "Component/Component Instance - not found")})
929     public Response getInstancePropertiesById(@PathParam("containerComponentType") final String containerComponentType,
930                                               @PathParam("containerComponentId") final String containerComponentId,
931                                               @PathParam("componentInstanceUniqueId") final String componentInstanceUniqueId,
932                                               @Context final HttpServletRequest request,
933                                               @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
934         String url = request.getMethod() + " " + request.getRequestURI();
935         log.debug(GET_START_HANDLE_REQUEST_OF, url);
936         List<ComponentInstanceProperty> componentInstancePropertiesById = componentInstanceBusinessLogic
937             .getComponentInstancePropertiesById(containerComponentType, containerComponentId, componentInstanceUniqueId, userId);
938         return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), componentInstancePropertiesById);
939     }
940
941     @GET
942     @Path("/{containerComponentType}/{containerComponentId}/componentInstances/{componentInstanceUniqueId}/attributes")
943     @Consumes(MediaType.APPLICATION_JSON)
944     @Produces(MediaType.APPLICATION_JSON)
945     @Operation(description = "Get component instance attributes", method = "GET", summary = "Returns component instance attributes", responses = {
946         @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
947         @ApiResponse(responseCode = "200", description = "Attributes found"),
948         @ApiResponse(responseCode = "403", description = "Restricted operation"),
949         @ApiResponse(responseCode = "404", description = "Component/Component Instance - not found")})
950     public Response getInstanceAttributesById(@PathParam("containerComponentType") final String containerComponentType,
951                                               @PathParam("containerComponentId") final String containerComponentId,
952                                               @PathParam("componentInstanceUniqueId") final String componentInstanceUniqueId,
953                                               @Context final HttpServletRequest request,
954                                               @HeaderParam(value = Constants.USER_ID_HEADER) final String userId) {
955         final String url = request.getMethod() + " " + request.getRequestURI();
956         log.debug(GET_START_HANDLE_REQUEST_OF, url);
957         final List<ComponentInstanceAttribute> componentInstanceAttributesById = componentInstanceBusinessLogic
958             .getComponentInstanceAttributesById(containerComponentType, containerComponentId, componentInstanceUniqueId, userId);
959         return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), componentInstanceAttributesById);
960     }
961
962     // US330353
963     @GET
964     @Path("/{containerComponentType}/{containerComponentId}/componentInstances/{componentInstanceUniqueId}/capability/{capabilityType}/capabilityName/{capabilityName}/ownerId/{ownerId}/properties")
965     @Consumes(MediaType.APPLICATION_JSON)
966     @Produces(MediaType.APPLICATION_JSON)
967     @Operation(description = "Get component instance capability properties", method = "GET", summary = "Returns component instance capability properties", responses = {
968         @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
969         @ApiResponse(responseCode = "200", description = "Properties found"),
970         @ApiResponse(responseCode = "403", description = "Restricted operation"),
971         @ApiResponse(responseCode = "404", description = "Component/Component Instance/Capability - not found")})
972     public Response getInstanceCapabilityPropertiesById(@PathParam("containerComponentType") final String containerComponentType,
973                                                         @PathParam("containerComponentId") final String containerComponentId,
974                                                         @PathParam("componentInstanceUniqueId") final String componentInstanceUniqueId,
975                                                         @PathParam("capabilityType") final String capabilityType,
976                                                         @PathParam("capabilityName") final String capabilityName,
977                                                         @PathParam("ownerId") final String ownerId, @Context final HttpServletRequest request,
978                                                         @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
979         String url = request.getMethod() + " " + request.getRequestURI();
980         log.debug(GET_START_HANDLE_REQUEST_OF, url);
981         try {
982             List<ComponentInstanceProperty> componentInstancePropertiesById = componentInstanceBusinessLogic
983                 .getComponentInstanceCapabilityPropertiesById(containerComponentType, containerComponentId, componentInstanceUniqueId, capabilityType,
984                     capabilityName, ownerId, userId);
985             return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), componentInstancePropertiesById);
986         } catch (Exception e) {
987             BeEcompErrorManager.getInstance().logBeRestApiGeneralError(GET_GROUP_ARTIFACT_BY_ID);
988             log.debug(GET_GROUP_ARTIFACT_BY_ID_UNEXPECTED_EXCEPTION, e);
989             throw e;
990         }
991     }
992
993     //US 331281
994     @PUT
995     @Path("/{containerComponentType}/{containerComponentId}/componentInstances/{componentInstanceUniqueId}/capability/{capabilityType}/capabilityName/{capabilityName}/ownerId/{ownerId}/properties")
996     @Consumes(MediaType.APPLICATION_JSON)
997     @Produces(MediaType.APPLICATION_JSON)
998     @Operation(description = "Update Instance Capabilty  Property", method = "PUT", summary = "Returns updated property", responses = {
999         @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
1000         @ApiResponse(responseCode = "200", description = "Resource instance capabilty property updated"),
1001         @ApiResponse(responseCode = "403", description = "Restricted operation"),
1002         @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
1003         @ApiResponse(responseCode = "404", description = "Component/Component Instance/Capability - not found")})
1004     public Response updateInstanceCapabilityProperty(@PathParam("containerComponentType") final String containerComponentType,
1005                                                      @PathParam("containerComponentId") final String containerComponentId,
1006                                                      @PathParam("componentInstanceUniqueId") final String componentInstanceUniqueId,
1007                                                      @PathParam("capabilityType") final String capabilityType,
1008                                                      @PathParam("capabilityName") final String capabilityName,
1009                                                      @PathParam("ownerId") final String ownerId,
1010                                                      @Parameter(description = "Instance capabilty property to update", required = true) String data,
1011                                                      @Context final HttpServletRequest request,
1012                                                      @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
1013         String url = request.getMethod() + " " + request.getRequestURI();
1014         log.debug("(PUT) Start handle request of {}", url);
1015         loggerSupportability.log(LoggerSupportabilityActions.UPDATE_INSTANCE_CAPABILITY_PROPERTY, StatusCode.STARTED,
1016             " Starting to update Instance Capability Property for component instance {} ", componentInstanceUniqueId + " by " + userId);
1017         try {
1018             Wrapper<ResponseFormat> errorWrapper = new Wrapper<>();
1019             List<ComponentInstanceProperty> propertiesToUpdate = new ArrayList<>();
1020             if (errorWrapper.isEmpty()) {
1021                 Either<List<ComponentInstanceProperty>, ResponseFormat> propertiesToUpdateEither = convertMultipleProperties(data);
1022                 if (propertiesToUpdateEither.isRight()) {
1023                     errorWrapper.setInnerElement(propertiesToUpdateEither.right().value());
1024                 } else {
1025                     propertiesToUpdate = propertiesToUpdateEither.left().value();
1026                 }
1027             }
1028             if (!errorWrapper.isEmpty()) {
1029                 return buildErrorResponse(errorWrapper.getInnerElement());
1030             }
1031             ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(containerComponentType);
1032             Either<List<ComponentInstanceProperty>, ResponseFormat> updateCICapProperty = componentInstanceBusinessLogic
1033                 .updateInstanceCapabilityProperties(componentTypeEnum, containerComponentId, componentInstanceUniqueId, capabilityType,
1034                     capabilityName, propertiesToUpdate, userId);
1035             if (updateCICapProperty.isRight()) {
1036                 log.debug(FAILED_TO_GET_PROPERTIES_OF_COMPONENT_INSTANCE_ID_IN_WITH_ID, componentInstanceUniqueId, containerComponentType,
1037                     containerComponentId);
1038                 return buildErrorResponse(updateCICapProperty.right().value());
1039             }
1040             loggerSupportability.log(LoggerSupportabilityActions.UPDATE_INSTANCE_CAPABILITY_PROPERTY, StatusCode.COMPLETE,
1041                 " Ended to update Instance Capability Property for component instance {} ", componentInstanceUniqueId + " by " + userId);
1042             return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), updateCICapProperty.left().value());
1043         } catch (Exception e) {
1044             BeEcompErrorManager.getInstance().logBeRestApiGeneralError(GET_GROUP_ARTIFACT_BY_ID);
1045             log.debug(GET_GROUP_ARTIFACT_BY_ID_UNEXPECTED_EXCEPTION, e);
1046             throw e;
1047         }
1048     }
1049
1050     @PUT
1051     @Path("/{containerComponentType}/{containerComponentId}/componentInstances/{componentInstanceUniqueId}/requirement/{capabilityType}/requirementName/{requirementName}")
1052     @Consumes(MediaType.APPLICATION_JSON)
1053     @Produces(MediaType.APPLICATION_JSON)
1054     @Operation(description = "Update Instance Requirement", method = "PUT", summary = "Returns updated requirement", responses = {
1055         @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
1056         @ApiResponse(responseCode = "200", description = "Resource instance requirement updated"),
1057         @ApiResponse(responseCode = "403", description = "Restricted operation"),
1058         @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
1059         @ApiResponse(responseCode = "404", description = "Component/Component Instance/Requirement - not found")})
1060     public Response updateInstanceRequirement(@PathParam("containerComponentType") final String containerComponentType,
1061                                               @PathParam("containerComponentId") final String containerComponentId,
1062                                               @PathParam("componentInstanceUniqueId") final String componentInstanceUniqueId,
1063                                               @PathParam("capabilityType") final String capabilityType,
1064                                               @PathParam("requirementName") final String requirementName,
1065                                               @Parameter(description = "Instance capabilty requirement to update", required = true) String data,
1066                                               @Context final HttpServletRequest request,
1067                                               @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
1068         String url = request.getMethod() + " " + request.getRequestURI();
1069         log.debug(START_HANDLE_REQUEST_OF, url);
1070         loggerSupportability.log(LoggerSupportabilityActions.UPDATE_INSTANCE_REQUIREMENT, StatusCode.STARTED,
1071             "Starting to update requirement {} in component instance {} by {}", requirementName, componentInstanceUniqueId, userId);
1072         try {
1073             log.debug(START_HANDLE_REQUEST_OF, url);
1074             ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(containerComponentType);
1075             if (componentTypeEnum == null) {
1076                 log.debug(UNSUPPORTED_COMPONENT_TYPE, containerComponentType);
1077                 return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.UNSUPPORTED_ERROR, containerComponentType));
1078             }
1079             Either<RequirementDefinition, ResponseFormat> mappedRequirementDataEither = getMappedRequirementData(data, new User(userId),
1080                 componentTypeEnum);
1081             if (mappedRequirementDataEither.isRight()) {
1082                 log.debug("Failed to update requirements");
1083                 return buildErrorResponse(mappedRequirementDataEither.right().value());
1084             }
1085             RequirementDefinition requirementDef = mappedRequirementDataEither.left().value();
1086             Either<RequirementDefinition, ResponseFormat> response = componentInstanceBusinessLogic
1087                 .updateInstanceRequirement(componentTypeEnum, containerComponentId, componentInstanceUniqueId, requirementDef, userId);
1088             if (response.isRight()) {
1089                 return buildErrorResponse(response.right().value());
1090             }
1091             return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), response.left().value());
1092         } catch (ComponentException e) {
1093             throw e;
1094         } catch (Exception e) {
1095             BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Update component instance requirement");
1096             log.debug("Update component instance requirement with exception", e);
1097             return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
1098         }
1099     }
1100
1101     private Either<RequirementDefinition, ResponseFormat> getMappedRequirementData(String inputJson, User user, ComponentTypeEnum componentTypeEnum) {
1102         return getComponentsUtils()
1103             .convertJsonToObjectUsingObjectMapper(inputJson, user, RequirementDefinition.class, AuditingActionEnum.GET_TOSCA_MODEL,
1104                 componentTypeEnum);
1105     }
1106
1107     @POST
1108     @Path("/{containerComponentType}/{containerComponentId}/serviceProxy")
1109     @Consumes(MediaType.APPLICATION_JSON)
1110     @Produces(MediaType.APPLICATION_JSON)
1111     @Operation(description = "Create service proxy", method = "POST", summary = "Returns created service proxy", responses = {
1112         @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
1113         @ApiResponse(responseCode = "201", description = "Service proxy created"),
1114         @ApiResponse(responseCode = "403", description = "Restricted operation"),
1115         @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
1116         @ApiResponse(responseCode = "409", description = "Service proxy already exist")})
1117     public Response createServiceProxy(@Parameter(description = "RI object to be created", required = true) String data,
1118                                        @PathParam("containerComponentId") final String containerComponentId,
1119                                        @Parameter(description = "valid values: resources / services", schema = @Schema(allowableValues = {
1120                                            ComponentTypeEnum.RESOURCE_PARAM_NAME,
1121                                            ComponentTypeEnum.SERVICE_PARAM_NAME})) @PathParam("containerComponentType") final String containerComponentType,
1122                                        @HeaderParam(value = Constants.USER_ID_HEADER) @Parameter(description = "USER_ID of modifier user", required = true) String userId,
1123                                        @Context final HttpServletRequest request) {
1124         try {
1125             ComponentInstance componentInstance = RepresentationUtils.fromRepresentation(data, ComponentInstance.class);
1126             componentInstance.setInvariantName(null);
1127             ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(containerComponentType);
1128             if (componentTypeEnum != ComponentTypeEnum.SERVICE) {
1129                 log.debug("Unsupported container component type {}", containerComponentType);
1130                 return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.UNSUPPORTED_ERROR, containerComponentType));
1131             }
1132             if (componentInstanceBusinessLogic == null) {
1133                 log.debug(UNSUPPORTED_COMPONENT_TYPE, containerComponentType);
1134                 return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.UNSUPPORTED_ERROR, containerComponentType));
1135             }
1136             Either<ComponentInstance, ResponseFormat> actionResponse = componentInstanceBusinessLogic.createServiceProxy();
1137             if (actionResponse.isRight()) {
1138                 return buildErrorResponse(actionResponse.right().value());
1139             }
1140             return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.CREATED), actionResponse.left().value());
1141         } catch (Exception e) {
1142             BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Create service proxy");
1143             log.debug("Create service proxy failed with exception", e);
1144             throw e;
1145         }
1146     }
1147
1148     @DELETE
1149     @Path("/{containerComponentType}/{containerComponentId}/serviceProxy/{serviceProxyId}")
1150     @Consumes(MediaType.APPLICATION_JSON)
1151     @Produces(MediaType.APPLICATION_JSON)
1152     @Operation(description = "Delete service proxy", method = "DELETE", summary = "Returns delete service proxy", responses = {
1153         @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
1154         @ApiResponse(responseCode = "201", description = "Service proxy deleted"),
1155         @ApiResponse(responseCode = "403", description = "Restricted operation"),
1156         @ApiResponse(responseCode = "400", description = "Invalid content / Missing content")})
1157     public Response deleteServiceProxy(@PathParam("containerComponentId") final String containerComponentId,
1158                                        @PathParam("serviceProxyId") final String serviceProxyId,
1159                                        @Parameter(description = "valid values: resources / services / products", schema = @Schema(allowableValues = {
1160                                            ComponentTypeEnum.RESOURCE_PARAM_NAME,
1161                                            ComponentTypeEnum.SERVICE_PARAM_NAME})) @PathParam("containerComponentType") final String containerComponentType,
1162                                        @Context final HttpServletRequest request) {
1163         String url = request.getMethod() + " " + request.getRequestURI();
1164         try {
1165             log.debug(START_HANDLE_REQUEST_OF, url);
1166             if (componentInstanceBusinessLogic == null) {
1167                 log.debug(UNSUPPORTED_COMPONENT_TYPE, containerComponentType);
1168                 return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.UNSUPPORTED_ERROR, containerComponentType));
1169             }
1170             Either<ComponentInstance, ResponseFormat> actionResponse = componentInstanceBusinessLogic.deleteServiceProxy();
1171             if (actionResponse.isRight()) {
1172                 return buildErrorResponse(actionResponse.right().value());
1173             } else {
1174                 return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.NO_CONTENT), null);
1175             }
1176         } catch (Exception e) {
1177             BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Delete service proxy");
1178             log.debug("Delete service proxy failed with exception", e);
1179             throw e;
1180         }
1181     }
1182
1183     @POST
1184     @Path("/{containerComponentType}/{containerComponentId}/serviceProxy/{serviceProxyId}/changeVersion/{newServiceId}")
1185     @Consumes(MediaType.APPLICATION_JSON)
1186     @Produces(MediaType.APPLICATION_JSON)
1187     @Operation(description = "Update service proxy with new version", method = "POST", summary = "Returns updated service proxy", responses = {
1188         @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
1189         @ApiResponse(responseCode = "201", description = "Service proxy created"),
1190         @ApiResponse(responseCode = "403", description = "Restricted operation"),
1191         @ApiResponse(responseCode = "400", description = "Invalid content / Missing content")})
1192     public Response changeServiceProxyVersion(@PathParam("containerComponentId") final String containerComponentId,
1193                                               @PathParam("serviceProxyId") final String serviceProxyId,
1194                                               @Parameter(description = "valid values: resources / services", schema = @Schema(allowableValues = {
1195                                                   ComponentTypeEnum.RESOURCE_PARAM_NAME,
1196                                                   ComponentTypeEnum.SERVICE_PARAM_NAME})) @PathParam("containerComponentType") final String containerComponentType,
1197                                               @Context final HttpServletRequest request) {
1198         String url = request.getMethod() + " " + request.getRequestURI();
1199         log.debug(START_HANDLE_REQUEST_OF, url);
1200         try {
1201             if (componentInstanceBusinessLogic == null) {
1202                 log.debug(UNSUPPORTED_COMPONENT_TYPE, containerComponentType);
1203                 return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.UNSUPPORTED_ERROR, containerComponentType));
1204             }
1205             Either<ComponentInstance, ResponseFormat> actionResponse = componentInstanceBusinessLogic.changeServiceProxyVersion();
1206             if (actionResponse.isRight()) {
1207                 return buildErrorResponse(actionResponse.right().value());
1208             }
1209             return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), actionResponse.left().value());
1210         } catch (Exception e) {
1211             BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Update service proxy with new version");
1212             log.debug("Update service proxy with new version failed with exception", e);
1213             throw e;
1214         }
1215     }
1216
1217     /**
1218      * REST API GET relation by Id Allows to get relation contained in specified component according to received Id
1219      *
1220      * @param containerComponentType
1221      * @param componentId
1222      * @param relationId
1223      * @param request
1224      * @param userId
1225      * @return Response
1226      */
1227     @GET
1228     @Path("/{containerComponentType}/{componentId}/relationId/{relationId}")
1229     @Consumes(MediaType.APPLICATION_JSON)
1230     @Produces(MediaType.APPLICATION_JSON)
1231     @Operation(description = "Get relation", method = "GET", summary = "Returns relation metadata according to relationId", responses = {
1232         @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
1233         @ApiResponse(responseCode = "200", description = "relation found"), @ApiResponse(responseCode = "403", description = "Restricted operation"),
1234         @ApiResponse(responseCode = "404", description = "Relation not found")})
1235     public Response getRelationById(@PathParam("containerComponentType") final String containerComponentType,
1236                                     @PathParam("componentId") final String componentId, @PathParam("relationId") final String relationId,
1237                                     @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
1238         String url = request.getMethod() + " " + request.getRequestURI();
1239         log.debug(GET_START_HANDLE_REQUEST_OF, url);
1240         try {
1241             ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(containerComponentType);
1242             if (componentTypeEnum == null) {
1243                 log.debug(UNSUPPORTED_COMPONENT_TYPE, containerComponentType);
1244                 return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.UNSUPPORTED_ERROR, containerComponentType));
1245             }
1246             Either<RequirementCapabilityRelDef, ResponseFormat> actionResponse = componentInstanceBusinessLogic
1247                 .getRelationById(componentId, relationId, userId, componentTypeEnum);
1248             if (actionResponse.isRight()) {
1249                 return buildErrorResponse(actionResponse.right().value());
1250             }
1251             return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), actionResponse.left().value());
1252         } catch (Exception e) {
1253             BeEcompErrorManager.getInstance().logBeRestApiGeneralError("getRelationById");
1254             log.debug("getRelationById unexpected exception", e);
1255             throw e;
1256         }
1257     }
1258
1259     private Either<ComponentInstance, ResponseFormat> convertToResourceInstance(String data) {
1260         Either<ComponentInstance, ResponseFormat> convertStatus = getComponentsUtils()
1261             .convertJsonToObjectUsingObjectMapper(data, new User(), ComponentInstance.class, null, ComponentTypeEnum.RESOURCE_INSTANCE);
1262         if (convertStatus.isRight()) {
1263             return Either.right(convertStatus.right().value());
1264         }
1265         ComponentInstance resourceInstanceInfo = convertStatus.left().value();
1266         return Either.left(resourceInstanceInfo);
1267     }
1268
1269     private Either<List<ComponentInstance>, ResponseFormat> convertToMultipleResourceInstance(String dataList) {
1270         Either<ComponentInstance[], ResponseFormat> convertStatus = getComponentsUtils()
1271             .convertJsonToObjectUsingObjectMapper(dataList, new User(), ComponentInstance[].class, null, ComponentTypeEnum.RESOURCE_INSTANCE);
1272         if (convertStatus.isRight()) {
1273             return Either.right(convertStatus.right().value());
1274         }
1275         return Either.left(Arrays.asList(convertStatus.left().value()));
1276     }
1277
1278     private Either<List<ComponentInstanceProperty>, ResponseFormat> convertMultipleProperties(String dataList) {
1279         if (StringUtils.isEmpty(dataList)) {
1280             return Either.right(getComponentsUtils().getResponseFormat(ActionStatus.MISSING_BODY));
1281         }
1282         Either<ComponentInstanceProperty[], ResponseFormat> convertStatus = getComponentsUtils()
1283             .convertJsonToObjectUsingObjectMapper(dataList, new User(), ComponentInstanceProperty[].class, null, ComponentTypeEnum.RESOURCE_INSTANCE);
1284         if (convertStatus.isRight()) {
1285             return Either.right(convertStatus.right().value());
1286         }
1287         return Either.left(Arrays.asList(convertStatus.left().value()));
1288     }
1289
1290     private Either<List<ComponentInstanceAttribute>, ResponseFormat> convertMultipleAttributes(final String dataList) {
1291         if (StringUtils.isEmpty(dataList)) {
1292             return Either.right(getComponentsUtils().getResponseFormat(ActionStatus.MISSING_BODY));
1293         }
1294         final Either<ComponentInstanceAttribute[], ResponseFormat> convertStatus = getComponentsUtils().
1295             convertJsonToObjectUsingObjectMapper(dataList, new User(), ComponentInstanceAttribute[].class, null, ComponentTypeEnum.RESOURCE_INSTANCE);
1296         if (convertStatus.isRight()) {
1297             return Either.right(convertStatus.right().value());
1298         }
1299         return Either.left(Arrays.asList(convertStatus.left().value()));
1300     }
1301
1302     private Either<List<ComponentInstanceInput>, ResponseFormat> convertMultipleInputs(String dataList) {
1303         if (StringUtils.isEmpty(dataList)) {
1304             return Either.right(getComponentsUtils().getResponseFormat(ActionStatus.MISSING_BODY));
1305         }
1306         Either<ComponentInstanceInput[], ResponseFormat> convertStatus = getComponentsUtils()
1307             .convertJsonToObjectUsingObjectMapper(dataList, new User(), ComponentInstanceInput[].class, null, ComponentTypeEnum.RESOURCE_INSTANCE);
1308         if (convertStatus.isRight()) {
1309             return Either.right(convertStatus.right().value());
1310         }
1311         return Either.left(Arrays.asList(convertStatus.left().value()));
1312     }
1313
1314     private RequirementCapabilityRelDef convertToRequirementCapabilityRelDef(String data) {
1315         Either<RequirementCapabilityRelDef, ActionStatus> convertStatus = convertJsonToObject(data, RequirementCapabilityRelDef.class);
1316         if (convertStatus.isRight()) {
1317             throw new ByActionStatusComponentException(convertStatus.right().value());
1318         }
1319         return convertStatus.left().value();
1320     }
1321
1322     @Override
1323     public <T> Either<T, ActionStatus> convertJsonToObject(String data, Class<T> clazz) {
1324         try {
1325             log.trace("convert json to object. json=\n {}", data);
1326             T t;
1327             t = gsonDeserializer.fromJson(data, clazz);
1328             if (t == null) {
1329                 BeEcompErrorManager.getInstance().logBeInvalidJsonInput("convertJsonToObject");
1330                 log.debug("object is null after converting from json");
1331                 return Either.right(ActionStatus.INVALID_CONTENT);
1332             }
1333             return Either.left(t);
1334         } catch (Exception e) {
1335             // INVALID JSON
1336             BeEcompErrorManager.getInstance().logBeInvalidJsonInput("convertJsonToObject");
1337             log.debug("failed to convert from json", e);
1338             return Either.right(ActionStatus.INVALID_CONTENT);
1339         }
1340     }
1341
1342     @GET
1343     @Path("/{containerComponentType}/{componentId}/paths-to-delete")
1344     @Produces(MediaType.APPLICATION_JSON)
1345     @Operation(description = "Check if forwarding path to delete on version change", method = "GET", summary = "Returns forwarding paths to delete", responses = {
1346         @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class))))})
1347     public Response changeResourceInstanceVersion(@PathParam("componentId") String componentId,
1348                                                   @QueryParam("componentInstanceId") final String oldComponentInstanceId,
1349                                                   @QueryParam("newComponentInstanceId") final String newComponentInstanceId,
1350                                                   @Parameter(description = "valid values: resources / services", schema = @Schema(allowableValues = {
1351                                                       ComponentTypeEnum.RESOURCE_PARAM_NAME,
1352                                                       ComponentTypeEnum.SERVICE_PARAM_NAME})) @PathParam("containerComponentType") final String containerComponentType,
1353                                                   @Context final HttpServletRequest request) {
1354         if (oldComponentInstanceId == null) {
1355             return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.MISSING_OLD_COMPONENT_INSTANCE));
1356         }
1357         if (newComponentInstanceId == null) {
1358             return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.MISSING_NEW_COMPONENT_INSTANCE));
1359         }
1360         String url = request.getMethod() + " " + request.getRequestURI();
1361         log.debug(START_HANDLE_REQUEST_OF, url);
1362         if (componentInstanceBusinessLogic == null) {
1363             log.debug(UNSUPPORTED_COMPONENT_TYPE, containerComponentType);
1364             return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.UNSUPPORTED_ERROR, containerComponentType));
1365         }
1366         ComponentInstance newComponentInstance;
1367         if (StringUtils.isNotEmpty(newComponentInstanceId)) {
1368             newComponentInstance = new ComponentInstance();
1369             newComponentInstance.setToscaPresentationValue(JsonPresentationFields.CI_COMPONENT_UID, newComponentInstanceId);
1370         } else {
1371             log.error("missing component id");
1372             return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.MISSING_DATA));
1373         }
1374         Either<Set<String>, ResponseFormat> actionResponse = componentInstanceBusinessLogic
1375             .forwardingPathOnVersionChange(containerComponentType, componentId, oldComponentInstanceId, newComponentInstance);
1376         if (actionResponse.isRight()) {
1377             return buildErrorResponse(actionResponse.right().value());
1378         }
1379         ForwardingPaths forwardingPaths = new ForwardingPaths();
1380         forwardingPaths.setForwardingPathToDelete(actionResponse.left().value());
1381         return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), forwardingPaths);
1382     }
1383
1384     @POST
1385     @Path("/services/{componentId}/copyComponentInstance/{componentInstanceId}")
1386     @Consumes(MediaType.APPLICATION_JSON)
1387     @Produces((MediaType.APPLICATION_JSON))
1388     @Operation(description = "Copy Component Instance", method = "POST", summary = "Returns updated service information", responses = {
1389         @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Service.class)))),
1390         @ApiResponse(responseCode = "201", description = "Copy and Paste Success"),
1391         @ApiResponse(responseCode = "403", description = "Restricted Operation"),
1392         @ApiResponse(responseCode = "400", description = "Invalid Content / Missing content")})
1393     public Response copyComponentInstance(
1394         @Parameter(description = "service unique id in pasted canvas") @PathParam("componentId") final String containerComponentId,
1395         @Parameter(description = "Data for copying", required = true) String data, @PathParam("componentInstanceId") final String componentInstanceId,
1396         @Context final HttpServletRequest request) {
1397         log.info("Start to copy component instance");
1398         String userId = request.getHeader(Constants.USER_ID_HEADER);
1399         final String CNTAINER_CMPT_TYPE = SERVICES;
1400         try {
1401             ComponentInstance inputComponentInstance = RepresentationUtils.fromRepresentation(data, ComponentInstance.class);
1402             inputComponentInstance.setInvariantName(null);
1403             ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(CNTAINER_CMPT_TYPE);
1404             if (componentInstanceBusinessLogic == null) {
1405                 log.debug(UNSUPPORTED_COMPONENT_TYPE, componentTypeEnum);
1406                 return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.UNSUPPORTED_ERROR, SERVICES));
1407             }
1408             Either<Map<String, ComponentInstance>, ResponseFormat> copyComponentInstance = componentInstanceBusinessLogic
1409                 .copyComponentInstance(inputComponentInstance, containerComponentId, componentInstanceId, userId);
1410             if (copyComponentInstance.isRight()) {
1411                 log.error("Failed to copy ComponentInstance {}", copyComponentInstance.right().value());
1412                 return buildErrorResponse(copyComponentInstance.right().value());
1413             }
1414             return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), copyComponentInstance.left().value());
1415         } catch (Exception e) {
1416             log.error("Failed to convert json to Map { }", data, e);
1417             return buildErrorResponse(
1418                 getComponentsUtils().getResponseFormat(ActionStatus.USER_DEFINED, "Failed to get the copied component instance information"));
1419         }
1420     }
1421
1422     @POST
1423     @Path("/{containerComponentType}/{componentId}/batchDeleteResourceInstances/")
1424     @Consumes(MediaType.APPLICATION_JSON)
1425     @Produces(MediaType.APPLICATION_JSON)
1426     @Operation(description = "Batch Delete ResourceInstances", method = "POST", responses = {
1427         @ApiResponse(responseCode = "203", description = "ResourceInstances deleted"),
1428         @ApiResponse(responseCode = "403", description = "Restricted Operation"),
1429         @ApiResponse(responseCode = "400", description = "Invalid Content / Missing Content")})
1430     public Response batchDeleteResourceInstances(
1431         @Parameter(description = "valid values: resources / services / products", schema = @Schema(allowableValues = {
1432             ComponentTypeEnum.RESOURCE_PARAM_NAME, ComponentTypeEnum.SERVICE_PARAM_NAME,
1433             ComponentTypeEnum.PRODUCT_PARAM_NAME})) @PathParam("containerComponentType") final String containerComponentType,
1434         @PathParam("componentId") final String componentId, @Context final HttpServletRequest request,
1435         @Parameter(description = "Component Instance Id List", required = true) final String componentInstanceIdLisStr) {
1436         try {
1437             if (componentInstanceIdLisStr == null || componentInstanceIdLisStr.isEmpty()) {
1438                 log.error("Empty JSON List was sent", componentInstanceIdLisStr);
1439                 return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
1440             }
1441             if (componentInstanceBusinessLogic == null) {
1442                 log.error(UNSUPPORTED_COMPONENT_TYPE, containerComponentType);
1443                 return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.UNSUPPORTED_ERROR, containerComponentType));
1444             }
1445             Either<List<String>, ResponseFormat> convertResponse = convertToStringList(componentInstanceIdLisStr);
1446             if (convertResponse.isRight()) {
1447                 BeEcompErrorManager.getInstance().logBeSystemError("Resource Instance - batchDeleteResourceInstances");
1448                 log.error(FAILED_TO_CONVERT_RECEIVED_DATA_TO_BE_FORMAT);
1449                 return buildErrorResponse(convertResponse.right().value());
1450             }
1451             String userId = request.getHeader(Constants.USER_ID_HEADER);
1452             List<String> componentInstanceIdList = convertResponse.left().value();
1453             log.debug("batchDeleteResourceInstances componentInstanceIdList is {}", componentInstanceIdList);
1454             Map<String, List<String>> deleteErrorMap = componentInstanceBusinessLogic
1455                 .batchDeleteComponentInstance(containerComponentType, componentId, componentInstanceIdList, userId);
1456             return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), deleteErrorMap);
1457         } catch (Exception e) {
1458             BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Batch Delete ResourceInstances");
1459             log.error("batch delete resource instances with exception", e);
1460             return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
1461         }
1462     }
1463
1464     @PUT
1465     @Path("/{containerComponentType}/{componentId}/resourceInstance/batchDissociate")
1466     @Consumes(MediaType.APPLICATION_JSON)
1467     @Produces(MediaType.APPLICATION_JSON)
1468     @Operation(description = "Batch Dissociate RI from RI", method = "PUT", summary = "Returns deleted RelationShip Info", responses = {
1469         @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
1470         @ApiResponse(responseCode = "201", description = "Relationship deleted"),
1471         @ApiResponse(responseCode = "403", description = "Missing Information"),
1472         @ApiResponse(responseCode = "400", description = "Invalid Content / Missing Content")})
1473     public Response batchDissociateRIFromRI(
1474         @Parameter(description = "allowed values are resources/services/products", schema = @Schema(allowableValues = {
1475             ComponentTypeEnum.RESOURCE_PARAM_NAME, ComponentTypeEnum.SERVICE_PARAM_NAME,
1476             ComponentTypeEnum.PRODUCT_PARAM_NAME}), required = true) @PathParam("containerComponentType") final String containerComponentType,
1477         @Parameter(description = "unique id of the container component") @PathParam("componentId") final String componentId,
1478         @HeaderParam(value = Constants.USER_ID_HEADER) String userId, @Parameter(description = "RelationshipInfo", required = true) String data,
1479         @Context final HttpServletRequest request) {
1480         try {
1481             if (data == null || data.length() == 0) {
1482                 log.info("Empty JSON list was sent");
1483                 return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
1484             }
1485             ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(containerComponentType);
1486             if (componentInstanceBusinessLogic == null) {
1487                 log.debug(UNSUPPORTED_COMPONENT_TYPE, containerComponentType);
1488                 return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.UNSUPPORTED_ERROR, containerComponentType));
1489             }
1490             Either<List<RequirementCapabilityRelDef>, ResponseFormat> regInfoWs = convertToRequirementCapabilityRelDefList(data);
1491             if (regInfoWs.isRight()) {
1492                 BeEcompErrorManager.getInstance().logBeSystemError("Resource Instance - batch dissociateRIFromRI");
1493                 log.debug("Failed to convert received data to BE format");
1494                 return buildErrorResponse(regInfoWs.right().value());
1495             }
1496             List<RequirementCapabilityRelDef> requirementDefList = regInfoWs.left().value();
1497             List<RequirementCapabilityRelDef> delOkResult = componentInstanceBusinessLogic
1498                 .batchDissociateRIFromRI(componentId, userId, requirementDefList, componentTypeEnum);
1499             return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), delOkResult);
1500         } catch (Exception e) {
1501             BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Batch Dissociate Resource Instance");
1502             log.debug("batch dissociate resource instance from service failed with exception", e);
1503             return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
1504         }
1505     }
1506
1507     private Either<List<String>, ResponseFormat> convertToStringList(String datalist) {
1508         Either<String[], ResponseFormat> convertStatus = getComponentsUtils()
1509             .convertJsonToObjectUsingObjectMapper(datalist, new User(), String[].class, null, null);
1510         if (convertStatus.isRight()) {
1511             return Either.right(convertStatus.right().value());
1512         }
1513         return Either.left(Arrays.asList(convertStatus.left().value()));
1514     }
1515
1516     private Either<List<RequirementCapabilityRelDef>, ResponseFormat> convertToRequirementCapabilityRelDefList(String data) {
1517         Either<RequirementCapabilityRelDef[], ResponseFormat> convertStatus = getComponentsUtils()
1518             .convertJsonToObjectUsingObjectMapper(data, new User(), RequirementCapabilityRelDef[].class, null, null);
1519         if (convertStatus.isRight()) {
1520             return Either.right(convertStatus.right().value());
1521         }
1522         return Either.left(Arrays.asList(convertStatus.left().value()));
1523     }
1524
1525     @POST
1526     @Path("/services/replaceVNF")
1527     @Operation(description = "Replace new VNF based on the existing VNF", method = "POST", summary = "Return whether the replace VNF is successful", responses = {
1528         @ApiResponse(responseCode = "200", description = "ECOMP component is authenticated and list of Catalog Assets Metadata is returned", content = @Content(array = @ArraySchema(schema = @Schema(implementation = ReplaceVNFInfo.class)))),
1529         @ApiResponse(responseCode = "400", description = "Missing  'X-ECOMP-InstanceID'  HTTP header - POL5001"),
1530         @ApiResponse(responseCode = "401", description = "ECOMP component  should authenticate itself  and  to  re-send  again  HTTP  request  with its Basic Authentication credentials - POL5002"),
1531         @ApiResponse(responseCode = "403", description = "ECOMP component is not authorized - POL5003"),
1532         @ApiResponse(responseCode = "404", description = "Error: Requested '%1' (uuid) resource was not found - SVC4063"),
1533         @ApiResponse(responseCode = "405", description = "Method  Not Allowed  :  Invalid HTTP method type used ( PUT,DELETE,POST will be rejected) - POL4050"),
1534         @ApiResponse(responseCode = "500", description = "The GET request failed either due to internal SDC problem. ECOMP Component should continue the attempts to get the needed information - POL5000"),
1535         @ApiResponse(responseCode = "409", description = "Service already exist")})
1536     public Response replaceVNF(@Parameter(description = "The user id", required = true) @HeaderParam(value = Constants.USER_ID_HEADER) String userId,
1537                                @Parameter(description = "X-ECOMP-RequestID header", required = false) @HeaderParam(value = Constants.X_ECOMP_REQUEST_ID_HEADER) String requestId,
1538                                @Parameter(description = "X-ECOMP-InstanceID header", required = true) @HeaderParam(value = Constants.X_ECOMP_INSTANCE_ID_HEADER) final String instanceIdHeader,
1539                                @Parameter(description = "Determines the format of the body of the response", required = false) @HeaderParam(value = Constants.ACCEPT_HEADER) String accept,
1540                                @Parameter(description = "The username and password", required = true) @HeaderParam(value = Constants.AUTHORIZATION_HEADER) String authorization,
1541                                @Context final HttpServletRequest request,
1542                                @Parameter(description = "Resource object to be created", required = true) String data) {
1543         String url = request.getMethod() + " " + request.getRequestURI();
1544         log.debug("replaceVNF: Start handle request of {}", url);
1545         User modifier = new User();
1546         modifier.setUserId(userId);
1547         log.debug("replaceVNF:modifier id is {}", userId);
1548         validateNotEmptyBody(data);
1549         Either<ReplaceVNFInfo, ResponseFormat> convertResponse = parseToReplaceVNFInfo(data, modifier);
1550         if (convertResponse.isRight()) {
1551             throw new ByResponseFormatComponentException(convertResponse.right().value());
1552         }
1553         log.debug("replaceVNF:get ReplaceVNFInfo success");
1554         String containerComponentType = SERVICES;
1555         ReplaceVNFInfo replaceVNFInfo = convertResponse.left().value();
1556         String serviceUniqueId = replaceVNFInfo.getServiceUniqueId();
1557         String abstractResourceUniqueId = replaceVNFInfo.getAbstractResourceUniqueId();
1558         ComponentInstance componentInstance = replaceVNFInfo.getRealVNFComponentInstance();
1559         log.debug("replaceVNF:get ReplaceVNFInfo,serviceUniqueId:{},abstractResourceUniqueId:{}", serviceUniqueId, abstractResourceUniqueId);
1560         try {
1561             /**
1562              * delete vnf
1563              */
1564             if (componentInstanceBusinessLogic == null) {
1565                 log.debug("replaceVNF:Unsupported component type {}", containerComponentType);
1566                 return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.UNSUPPORTED_ERROR, containerComponentType));
1567             }
1568             Either<ComponentInstance, ResponseFormat> componentInstanceEither = componentInstanceBusinessLogic
1569                 .deleteAbstractComponentInstance(containerComponentType, serviceUniqueId, abstractResourceUniqueId, userId);
1570             if (componentInstanceEither.isRight()) {
1571                 log.debug("replaceVNF:delete Abstract ComponentInstance field");
1572                 return buildErrorResponse(componentInstanceEither.right().value());
1573             }
1574             /**
1575              * add vnf
1576              */
1577             log.debug("replaceVNF,start add vnf");
1578             componentInstance.setInvariantName(null);
1579             componentInstance.setCreatedFrom(CreatedFrom.UI);
1580             Either<ComponentInstance, ResponseFormat> realComponentInstance = componentInstanceBusinessLogic
1581                 .createRealComponentInstance(containerComponentType, serviceUniqueId, userId, componentInstance);
1582             if (realComponentInstance.isRight()) {
1583                 log.debug("replaceVNF:filed to add vnf");
1584                 return buildErrorResponse(realComponentInstance.right().value());
1585             }
1586             ComponentInstance newComponentInstance = realComponentInstance.left().value();
1587             log.debug("replaceVNF:success to add vnf");
1588             return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), newComponentInstance);
1589         } catch (Exception e) {
1590             BeEcompErrorManager.getInstance().logBeRestApiGeneralError("replaceVNF");
1591             log.debug("replaceVNF with exception", e);
1592             throw e;
1593         }
1594     }
1595
1596     private Either<ReplaceVNFInfo, ResponseFormat> parseToReplaceVNFInfo(String serviceJson, User user) {
1597         log.debug("enter parseToReplaceVNFInfo,get serviceJson:{}", serviceJson);
1598         return getComponentsUtils().convertJsonToObjectUsingObjectMapper(serviceJson, user, ReplaceVNFInfo.class, AuditingActionEnum.CREATE_RESOURCE,
1599             ComponentTypeEnum.SERVICE);
1600     }
1601 }