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