Support for Test Topology Auto Design- Service Import
[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.ComponentInstanceInput;
90 import org.openecomp.sdc.be.model.ComponentInstanceProperty;
91 import org.openecomp.sdc.be.model.PropertyConstraint;
92 import org.openecomp.sdc.be.model.RequirementCapabilityRelDef;
93 import org.openecomp.sdc.be.model.RequirementDefinition;
94 import org.openecomp.sdc.be.model.Service;
95 import org.openecomp.sdc.be.model.User;
96 import org.openecomp.sdc.be.model.operations.impl.PropertyOperation.PropertyConstraintDeserialiser;
97 import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum;
98 import org.openecomp.sdc.be.user.UserBusinessLogic;
99 import org.openecomp.sdc.common.api.Constants;
100 import org.openecomp.sdc.common.datastructure.Wrapper;
101 import org.openecomp.sdc.common.log.elements.LoggerSupportability;
102 import org.openecomp.sdc.common.log.enums.LoggerSupportabilityActions;
103 import org.openecomp.sdc.common.log.enums.StatusCode;
104 import org.openecomp.sdc.common.log.wrappers.Logger;
105 import org.openecomp.sdc.exception.ResponseFormat;
106 import org.springframework.stereotype.Controller;
107
108 /**
109  * Root resource (exposed at "/" path) .json.
110  */
111 @Loggable(prepend = true, value = Loggable.DEBUG, trim = false)
112 @Path("/v1/catalog")
113 @Tag(name = "SDC Internal APIs")
114 @Server(url = "/sdc2/rest")
115 @Controller
116 public class ComponentInstanceServlet extends AbstractValidationsServlet {
117
118     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: {}";
119         private static final String GET_GROUP_ARTIFACT_BY_ID = "getGroupArtifactById";
120         private static final String GET_GROUP_ARTIFACT_BY_ID_UNEXPECTED_EXCEPTION = "getGroupArtifactById unexpected exception";
121         private static final String GET_START_HANDLE_REQUEST_OF = "(GET) Start handle request of {}";
122         private static final String START_HANDLE_REQUEST_OF_UPDATE_RESOURCE_INSTANCE_PROPERTY_RECEIVED_PROPERTY_IS = "Start handle request of updateResourceInstanceProperty. Received property is {}";
123         private static final String UPDATE_RESOURCE_INSTANCE = "Update Resource Instance";
124         private static final String RESOURCE_INSTANCE_UPDATE_RESOURCE_INSTANCE = "Resource Instance - updateResourceInstance";
125         private static final String UPDATE_RESOURCE_INSTANCE_WITH_EXCEPTION = "update resource instance with exception";
126         private static final String FAILED_TO_CONVERT_RECEIVED_DATA_TO_BE_FORMAT = "Failed to convert received data to BE format.";
127         private static final String EMPTY_BODY_WAS_SENT = "Empty body was sent.";
128         private static final String START_HANDLE_REQUEST_OF = "Start handle request of {}";
129         private static final String UNSUPPORTED_COMPONENT_TYPE = "Unsupported component type {}";
130     private static final String CREATE_AND_ASSOCIATE_RI_FAILED_WITH_EXCEPTION = "create and associate RI failed with exception: {}";
131         private static final Logger log = Logger.getLogger(ComponentInstanceServlet.class);
132     private static final Type PROPERTY_CONSTRAINT_TYPE = new TypeToken<PropertyConstraint>() {}.getType();
133     private static final Gson gsonDeserializer = new GsonBuilder().registerTypeAdapter(PROPERTY_CONSTRAINT_TYPE, new PropertyConstraintDeserialiser()).create();
134     private static final LoggerSupportability loggerSupportability = LoggerSupportability.getLogger(ComponentInstanceServlet.class.getName());
135
136     private final GroupBusinessLogic groupBL;
137     private final ComponentNodeFilterBusinessLogic nodeFilterBusinessLogic;
138
139
140     @Inject
141     public ComponentInstanceServlet(UserBusinessLogic userBusinessLogic,
142                                     GroupBusinessLogic groupBL, ComponentInstanceBusinessLogic componentInstanceBL,
143                                     ComponentsUtils componentsUtils, ServletUtils servletUtils,
144                                     ResourceImportManager resourceImportManager,
145                                     ComponentNodeFilterBusinessLogic nodeFilterBusinessLogic) {
146         super(userBusinessLogic, componentInstanceBL, componentsUtils, servletUtils, resourceImportManager);
147         this.groupBL = groupBL;
148         this.nodeFilterBusinessLogic = nodeFilterBusinessLogic;
149     }
150
151     @POST
152     @Path("/{containerComponentType}/{componentId}/resourceInstance")
153     @Consumes(MediaType.APPLICATION_JSON)
154     @Produces(MediaType.APPLICATION_JSON)
155     @Operation(description = "Create ComponentInstance", method = "POST", summary = "Returns created ComponentInstance",
156             responses = {@ApiResponse(
157                     content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
158                     @ApiResponse(responseCode = "201", description = "Component created"),
159                     @ApiResponse(responseCode = "403", description = "Restricted operation"),
160                     @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
161                     @ApiResponse(responseCode = "409", description = "Component instance already exist")})
162     @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
163     public Response createComponentInstance(@Parameter(description = "RI object to be created", required = true) String data,
164             @PathParam("componentId") final String containerComponentId,
165             @Parameter(description = "valid values: resources / services",
166                     schema = @Schema(allowableValues = {ComponentTypeEnum.RESOURCE_PARAM_NAME ,
167                             ComponentTypeEnum.SERVICE_PARAM_NAME})) @PathParam("containerComponentType") final String containerComponentType,
168             @HeaderParam(value = Constants.USER_ID_HEADER) @Parameter(description = "USER_ID of modifier user",
169                     required = true) String userId,
170             @Context final HttpServletRequest request) {
171
172         validateNotEmptyBody(data);
173         final ComponentInstance componentInstance;
174         try {
175             componentInstance = RepresentationUtils.fromRepresentation(data, ComponentInstance.class);
176             componentInstance.setInvariantName(null);
177             componentInstance.setCreatedFrom(CreatedFrom.UI);
178         } catch (final Exception e) {
179             BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Create Component Instance");
180             log.debug("create component instance failed with exception", e);
181             throw new ByActionStatusComponentException(ActionStatus.INVALID_CONTENT);
182         }
183
184         loggerSupportability.log(LoggerSupportabilityActions.CREATE_INSTANCE, StatusCode.STARTED,
185             "Starting to create component instance by {}", userId);
186         if (componentInstanceBusinessLogic == null) {
187             log.debug(UNSUPPORTED_COMPONENT_TYPE, containerComponentType);
188             return buildErrorResponse(
189                 getComponentsUtils().getResponseFormat(ActionStatus.UNSUPPORTED_ERROR, containerComponentType));
190         }
191         final ComponentInstance actionResponse = componentInstanceBusinessLogic.
192             createComponentInstance(containerComponentType, containerComponentId, userId, componentInstance);
193         loggerSupportability
194             .log(LoggerSupportabilityActions.CREATE_INSTANCE, actionResponse.getComponentMetadataForSupportLog(),
195                 StatusCode.COMPLETE, "Ending to create component instance by user {}", userId);
196         return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.CREATED), actionResponse);
197
198     }
199
200     @POST
201     @Path("/{containerComponentType}/{componentId}/resourceInstance/{componentInstanceId}")
202     @Consumes(MediaType.APPLICATION_JSON)
203     @Produces(MediaType.APPLICATION_JSON)
204     @Operation(description = "Update resource instance", method = "POST", summary = "Returns updated resource instance",
205             responses = {@ApiResponse(
206                     content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
207                     @ApiResponse(responseCode = "200", description = "Resource instance updated"),
208                     @ApiResponse(responseCode = "403", description = "Restricted operation"),
209                     @ApiResponse(responseCode = "400", description = "Invalid content / Missing content")})
210     @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
211     public Response updateComponentInstanceMetadata(@PathParam("componentId") final String componentId,
212             @PathParam("componentInstanceId") final String componentInstanceId,
213             @Parameter(description = "valid values: resources / services / products",
214                     schema = @Schema(allowableValues = {ComponentTypeEnum.RESOURCE_PARAM_NAME,
215                             ComponentTypeEnum.SERVICE_PARAM_NAME,
216                             ComponentTypeEnum.PRODUCT_PARAM_NAME})) @PathParam("containerComponentType") final String containerComponentType,
217             @Context final HttpServletRequest request) throws IOException, BusinessLogicException {
218
219         final String url = request.getMethod() + " " + request.getRequestURI();
220         log.debug(START_HANDLE_REQUEST_OF, url);
221         loggerSupportability.log(LoggerSupportabilityActions.UPDATE_COMPONENT_INSTANCE,StatusCode.STARTED,"update Component Instance Metadata");
222         final String userId = request.getHeader(Constants.USER_ID_HEADER);
223          try {
224             if (componentInstanceBusinessLogic == null) {
225                 log.debug(UNSUPPORTED_COMPONENT_TYPE, containerComponentType);
226                 return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.UNSUPPORTED_ERROR,
227                                                                                  containerComponentType));
228             }
229             componentInstanceBusinessLogic.validateUser(userId);
230             log.debug(START_HANDLE_REQUEST_OF, url);
231             final byte[] bytes = IOUtils.toByteArray(request.getInputStream());
232
233             if (bytes == null || bytes.length == 0) {
234                 log.info(EMPTY_BODY_WAS_SENT);
235                 return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
236             }
237
238             final String data = new String(bytes);
239             final ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(containerComponentType);
240             final Either<ComponentInstance, ResponseFormat> convertResponse = convertToResourceInstance(data);
241             if (convertResponse.isRight()) {
242                 BeEcompErrorManager.getInstance().logBeSystemError(RESOURCE_INSTANCE_UPDATE_RESOURCE_INSTANCE);
243                 log.debug(FAILED_TO_CONVERT_RECEIVED_DATA_TO_BE_FORMAT);
244                 return buildErrorResponse(convertResponse.right().value());
245             }
246
247
248             final ComponentInstance componentInstance = convertResponse.left().value();
249             final Either<ComponentInstance, ResponseFormat> actionResponse = componentInstanceBusinessLogic
250                 .updateComponentInstanceMetadata(containerComponentType, componentId, componentInstanceId, userId, componentInstance);
251             loggerSupportability.log(LoggerSupportabilityActions.UPDATE_COMPONENT_INSTANCE,actionResponse.left().value()
252                 .getComponentMetadataForSupportLog(),StatusCode.COMPLETE,"update Component Instance Metadata by {}", userId);
253             if (actionResponse.isRight()) {
254                 return buildErrorResponse(actionResponse.right().value());
255             }
256
257             final ComponentInstance resultValue = actionResponse.left().value();
258             if (ComponentTypeEnum.SERVICE.equals(componentTypeEnum) ||
259                 ComponentTypeEnum.RESOURCE.equals(componentTypeEnum) &&
260                     componentInstanceBusinessLogic.isVFC(componentInstance.getOriginType())) {
261
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     // US330353
1010     @GET
1011     @Path("/{containerComponentType}/{containerComponentId}/componentInstances/{componentInstanceUniqueId}/capability/{capabilityType}/capabilityName/{capabilityName}/ownerId/{ownerId}/properties")
1012     @Consumes(MediaType.APPLICATION_JSON)
1013     @Produces(MediaType.APPLICATION_JSON)
1014     @Operation(description = "Get component instance capability properties", method = "GET",
1015             summary = "Returns component instance capability properties", responses = {
1016             @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
1017             @ApiResponse(responseCode = "200", description = "Properties found"),
1018             @ApiResponse(responseCode = "403", description = "Restricted operation"),
1019             @ApiResponse(responseCode = "404", description = "Component/Component Instance/Capability - not found")})
1020     @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
1021     public Response getInstanceCapabilityPropertiesById(
1022             @PathParam("containerComponentType") final String containerComponentType,
1023             @PathParam("containerComponentId") final String containerComponentId,
1024             @PathParam("componentInstanceUniqueId") final String componentInstanceUniqueId,
1025             @PathParam("capabilityType") final String capabilityType,
1026             @PathParam("capabilityName") final String capabilityName, @PathParam("ownerId") final String ownerId,
1027             @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
1028
1029
1030         String url = request.getMethod() + " " + request.getRequestURI();
1031         log.debug(GET_START_HANDLE_REQUEST_OF, url);
1032
1033         try {
1034             List<ComponentInstanceProperty> componentInstancePropertiesById = componentInstanceBusinessLogic.getComponentInstanceCapabilityPropertiesById(containerComponentType, containerComponentId, componentInstanceUniqueId,
1035                     capabilityType, capabilityName, ownerId, userId);
1036
1037             return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), componentInstancePropertiesById);
1038         } catch (Exception e) {
1039             BeEcompErrorManager.getInstance().logBeRestApiGeneralError(GET_GROUP_ARTIFACT_BY_ID);
1040             log.debug(GET_GROUP_ARTIFACT_BY_ID_UNEXPECTED_EXCEPTION, e);
1041             throw e;
1042         }
1043
1044     }
1045
1046     //US 331281
1047     @PUT
1048     @Path("/{containerComponentType}/{containerComponentId}/componentInstances/{componentInstanceUniqueId}/capability/{capabilityType}/capabilityName/{capabilityName}/ownerId/{ownerId}/properties")
1049     @Consumes(MediaType.APPLICATION_JSON)
1050     @Produces(MediaType.APPLICATION_JSON)
1051     @Operation(description = "Update Instance Capabilty  Property", method = "PUT",
1052             summary = "Returns updated property", responses = {
1053             @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
1054             @ApiResponse(responseCode = "200", description = "Resource instance capabilty property updated"),
1055             @ApiResponse(responseCode = "403", description = "Restricted operation"),
1056             @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
1057             @ApiResponse(responseCode = "404", description = "Component/Component Instance/Capability - not found")})
1058     @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
1059     public Response updateInstanceCapabilityProperty(
1060             @PathParam("containerComponentType") final String containerComponentType,
1061             @PathParam("containerComponentId") final String containerComponentId,
1062             @PathParam("componentInstanceUniqueId") final String componentInstanceUniqueId,
1063             @PathParam("capabilityType") final String capabilityType,
1064             @PathParam("capabilityName") final String capabilityName, @PathParam("ownerId") final String ownerId,
1065             @Parameter(description = "Instance capabilty property to update", required = true) String data,
1066             @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
1067         String url = request.getMethod() + " " + request.getRequestURI();
1068         log.debug("(PUT) Start handle request of {}", url);
1069         loggerSupportability.log(LoggerSupportabilityActions.UPDATE_INSTANCE_CAPABILITY_PROPERTY, StatusCode.STARTED," Starting to update Instance Capability Property for component instance {} " , componentInstanceUniqueId + " by " + userId);
1070         try {
1071             Wrapper<ResponseFormat> errorWrapper = new Wrapper<>();
1072             List<ComponentInstanceProperty> propertiesToUpdate = new ArrayList<>();
1073             if (errorWrapper.isEmpty()) {
1074                 Either<List<ComponentInstanceProperty>, ResponseFormat> propertiesToUpdateEither = convertMultipleProperties(data);
1075                 if (propertiesToUpdateEither.isRight()) {
1076                     errorWrapper.setInnerElement(propertiesToUpdateEither.right().value());
1077                 } else {
1078                     propertiesToUpdate = propertiesToUpdateEither.left().value();
1079                 }
1080             }
1081
1082             if (!errorWrapper.isEmpty()) {
1083                 return buildErrorResponse(errorWrapper.getInnerElement());
1084             }
1085
1086             ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(containerComponentType);
1087
1088             Either<List<ComponentInstanceProperty>, ResponseFormat> updateCICapProperty = componentInstanceBusinessLogic.updateInstanceCapabilityProperties(componentTypeEnum, containerComponentId, componentInstanceUniqueId, capabilityType, capabilityName, propertiesToUpdate, userId);
1089
1090             if (updateCICapProperty.isRight()) {
1091                 log.debug(FAILED_TO_GET_PROPERTIES_OF_COMPONENT_INSTANCE_ID_IN_WITH_ID, componentInstanceUniqueId, containerComponentType, containerComponentId);
1092                 return buildErrorResponse(updateCICapProperty.right().value());
1093             }
1094             loggerSupportability.log(LoggerSupportabilityActions.UPDATE_INSTANCE_CAPABILITY_PROPERTY, StatusCode.COMPLETE," Ended to update Instance Capability Property for component instance {} " , componentInstanceUniqueId + " by " + userId);
1095             return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), updateCICapProperty.left().value());
1096         } catch (Exception e) {
1097             BeEcompErrorManager.getInstance().logBeRestApiGeneralError(GET_GROUP_ARTIFACT_BY_ID);
1098             log.debug(GET_GROUP_ARTIFACT_BY_ID_UNEXPECTED_EXCEPTION, e);
1099             throw e;
1100         }
1101     }
1102     
1103     @PUT
1104     @Path("/{containerComponentType}/{containerComponentId}/componentInstances/{componentInstanceUniqueId}/requirement/{capabilityType}/requirementName/{requirementName}")
1105     @Consumes(MediaType.APPLICATION_JSON)
1106     @Produces(MediaType.APPLICATION_JSON)
1107     @Operation(description = "Update Instance Requirement", method = "PUT",
1108             summary = "Returns updated requirement", responses = {
1109             @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
1110             @ApiResponse(responseCode = "200", description = "Resource instance requirement updated"),
1111             @ApiResponse(responseCode = "403", description = "Restricted operation"),
1112             @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
1113             @ApiResponse(responseCode = "404", description = "Component/Component Instance/Requirement - not found")})
1114     @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
1115     public Response updateInstanceRequirement(
1116             @PathParam("containerComponentType") final String containerComponentType,
1117             @PathParam("containerComponentId") final String containerComponentId,
1118             @PathParam("componentInstanceUniqueId") final String componentInstanceUniqueId,
1119             @PathParam("capabilityType") final String capabilityType,
1120             @PathParam("requirementName") final String requirementName,
1121             @Parameter(description = "Instance capabilty requirement to update", required = true) String data,
1122             @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
1123         String url = request.getMethod() + " " + request.getRequestURI();
1124         log.debug(START_HANDLE_REQUEST_OF, url);
1125         loggerSupportability.log(LoggerSupportabilityActions.UPDATE_INSTANCE_REQUIREMENT, StatusCode.STARTED,"Starting to update requirement {} in component instance {} by {}", requirementName, componentInstanceUniqueId, userId );
1126         try {
1127
1128             log.debug(START_HANDLE_REQUEST_OF, url);
1129
1130             ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(containerComponentType);
1131             if (componentInstanceBusinessLogic == null) {
1132                 log.debug(UNSUPPORTED_COMPONENT_TYPE, containerComponentType);
1133                 return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.UNSUPPORTED_ERROR, containerComponentType));
1134             }
1135             
1136             Either<RequirementDefinition, ResponseFormat>  mappedRequirementDataEither = getMappedRequirementData(data, new User(userId), componentTypeEnum);
1137             if(mappedRequirementDataEither.isRight()) {
1138                 log.debug("Failed to update requirements");
1139                 return buildErrorResponse(mappedRequirementDataEither.right().value());
1140             }
1141             RequirementDefinition requirementDef = mappedRequirementDataEither.left().value();
1142             
1143             Either<RequirementDefinition, ResponseFormat> response = componentInstanceBusinessLogic.updateInstanceRequirement(componentTypeEnum, containerComponentId, componentInstanceUniqueId, capabilityType, requirementName, requirementDef, userId);
1144             
1145             if (response.isRight()) {
1146                 return buildErrorResponse(response.right().value());
1147             }
1148             return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), response.left().value());
1149             
1150         } catch (ComponentException e) {
1151             throw e;
1152         } catch (Exception e) {
1153             BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Update component instance requirement");
1154             log.debug("Update component instance requirement with exception", e);
1155             return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
1156         }
1157     }
1158     
1159     private Either<RequirementDefinition, ResponseFormat>  getMappedRequirementData(String inputJson, User user,
1160             ComponentTypeEnum componentTypeEnum){
1161         return getComponentsUtils().convertJsonToObjectUsingObjectMapper(inputJson, user, RequirementDefinition.class, AuditingActionEnum.GET_TOSCA_MODEL, componentTypeEnum);
1162     }
1163
1164     @POST
1165     @Path("/{containerComponentType}/{containerComponentId}/serviceProxy")
1166     @Consumes(MediaType.APPLICATION_JSON)
1167     @Produces(MediaType.APPLICATION_JSON)
1168     @Operation(description = "Create service proxy", method = "POST", summary = "Returns created service proxy",
1169             responses = {@ApiResponse(
1170                     content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
1171                     @ApiResponse(responseCode = "201", description = "Service proxy created"),
1172                     @ApiResponse(responseCode = "403", description = "Restricted operation"),
1173                     @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
1174                     @ApiResponse(responseCode = "409", description = "Service proxy already exist")})
1175     @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
1176     public Response createServiceProxy(@Parameter(description = "RI object to be created", required = true) String data,
1177             @PathParam("containerComponentId") final String containerComponentId,
1178             @Parameter(description = "valid values: resources / services",
1179                     schema = @Schema(allowableValues = {ComponentTypeEnum.RESOURCE_PARAM_NAME,
1180                             ComponentTypeEnum.SERVICE_PARAM_NAME})) @PathParam("containerComponentType") final String containerComponentType,
1181             @HeaderParam(value = Constants.USER_ID_HEADER) @Parameter(description = "USER_ID of modifier user",
1182                     required = true) String userId,
1183             @Context final HttpServletRequest request) {
1184
1185         try {
1186
1187             ComponentInstance componentInstance = RepresentationUtils.fromRepresentation(data, ComponentInstance.class);
1188             componentInstance.setInvariantName(null);
1189             ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(containerComponentType);
1190             if (componentTypeEnum != ComponentTypeEnum.SERVICE) {
1191                 log.debug("Unsupported container component type {}", containerComponentType);
1192                 return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.UNSUPPORTED_ERROR, containerComponentType));
1193             }
1194             if (componentInstanceBusinessLogic == null) {
1195                 log.debug(UNSUPPORTED_COMPONENT_TYPE, containerComponentType);
1196                 return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.UNSUPPORTED_ERROR, containerComponentType));
1197             }
1198             Either<ComponentInstance, ResponseFormat> actionResponse = componentInstanceBusinessLogic.createServiceProxy();
1199
1200             if (actionResponse.isRight()) {
1201                 return buildErrorResponse(actionResponse.right().value());
1202             }
1203             return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.CREATED), actionResponse.left().value());
1204
1205         } catch (Exception e) {
1206             BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Create service proxy");
1207             log.debug("Create service proxy failed with exception", e);
1208             throw e;
1209         }
1210     }
1211
1212     @DELETE
1213     @Path("/{containerComponentType}/{containerComponentId}/serviceProxy/{serviceProxyId}")
1214     @Consumes(MediaType.APPLICATION_JSON)
1215     @Produces(MediaType.APPLICATION_JSON)
1216     @Operation(description = "Delete service proxy", method = "DELETE", summary = "Returns delete service proxy",
1217             responses = {@ApiResponse(
1218                     content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
1219                     @ApiResponse(responseCode = "201", description = "Service proxy deleted"),
1220                     @ApiResponse(responseCode = "403", description = "Restricted operation"),
1221                     @ApiResponse(responseCode = "400", description = "Invalid content / Missing content")})
1222     @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
1223     public Response deleteServiceProxy(@PathParam("containerComponentId") final String containerComponentId,
1224             @PathParam("serviceProxyId") final String serviceProxyId,
1225             @Parameter(description = "valid values: resources / services / products",
1226                     schema = @Schema(allowableValues = {ComponentTypeEnum.RESOURCE_PARAM_NAME,
1227                             ComponentTypeEnum.SERVICE_PARAM_NAME})) @PathParam("containerComponentType") final String containerComponentType,
1228             @Context final HttpServletRequest request) {
1229
1230         String url = request.getMethod() + " " + request.getRequestURI();
1231         try {
1232             log.debug(START_HANDLE_REQUEST_OF, url);
1233             if (componentInstanceBusinessLogic == null) {
1234                 log.debug(UNSUPPORTED_COMPONENT_TYPE, containerComponentType);
1235                 return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.UNSUPPORTED_ERROR, containerComponentType));
1236             }
1237             Either<ComponentInstance, ResponseFormat> actionResponse = componentInstanceBusinessLogic.deleteServiceProxy();
1238
1239             if (actionResponse.isRight()) {
1240                 return buildErrorResponse(actionResponse.right().value());
1241             } else {
1242                 return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.NO_CONTENT), null);
1243             }
1244         } catch (Exception e) {
1245             BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Delete service proxy");
1246             log.debug("Delete service proxy failed with exception", e);
1247             throw e;
1248         }
1249     }
1250
1251     @POST
1252     @Path("/{containerComponentType}/{containerComponentId}/serviceProxy/{serviceProxyId}/changeVersion/{newServiceId}")
1253     @Consumes(MediaType.APPLICATION_JSON)
1254     @Produces(MediaType.APPLICATION_JSON)
1255     @Operation(description = "Update service proxy with new version", method = "POST",
1256             summary = "Returns updated service proxy", responses = {
1257             @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
1258             @ApiResponse(responseCode = "201", description = "Service proxy created"),
1259             @ApiResponse(responseCode = "403", description = "Restricted operation"),
1260             @ApiResponse(responseCode = "400", description = "Invalid content / Missing content")})
1261     @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
1262     public Response changeServiceProxyVersion(@PathParam("containerComponentId") final String containerComponentId,
1263             @PathParam("serviceProxyId") final String serviceProxyId,
1264             @Parameter(description = "valid values: resources / services",
1265                     schema = @Schema(allowableValues = {ComponentTypeEnum.RESOURCE_PARAM_NAME,
1266                             ComponentTypeEnum.SERVICE_PARAM_NAME})) @PathParam("containerComponentType") final String containerComponentType,
1267             @Context final HttpServletRequest request) {
1268
1269
1270         String url = request.getMethod() + " " + request.getRequestURI();
1271         log.debug(START_HANDLE_REQUEST_OF, url);
1272         try {
1273             if (componentInstanceBusinessLogic == null) {
1274                 log.debug(UNSUPPORTED_COMPONENT_TYPE, containerComponentType);
1275                 return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.UNSUPPORTED_ERROR, containerComponentType));
1276             }
1277             Either<ComponentInstance, ResponseFormat> actionResponse = componentInstanceBusinessLogic.changeServiceProxyVersion();
1278
1279             if (actionResponse.isRight()) {
1280                 return buildErrorResponse(actionResponse.right().value());
1281             }
1282             return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), actionResponse.left().value());
1283
1284         } catch (Exception e) {
1285             BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Update service proxy with new version");
1286             log.debug("Update service proxy with new version failed with exception", e);
1287             throw e;
1288         }
1289     }
1290     /**
1291      * REST API GET relation by Id
1292      * Allows to get relation contained in specified component according to received Id
1293      * @param containerComponentType
1294      * @param componentId
1295      * @param relationId
1296      * @param request
1297      * @param userId
1298      * @return Response
1299      */
1300     @GET
1301     @Path("/{containerComponentType}/{componentId}/relationId/{relationId}")
1302     @Consumes(MediaType.APPLICATION_JSON)
1303     @Produces(MediaType.APPLICATION_JSON)
1304     @Operation(description = "Get relation", method = "GET",
1305             summary = "Returns relation metadata according to relationId", responses = {
1306             @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
1307             @ApiResponse(responseCode = "200", description = "relation found"),
1308             @ApiResponse(responseCode = "403", description = "Restricted operation"),
1309             @ApiResponse(responseCode = "404", description = "Relation not found")})
1310     @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
1311     public Response getRelationById(@PathParam("containerComponentType") final String containerComponentType,
1312             @PathParam("componentId") final String componentId, @PathParam("relationId") final String relationId,
1313             @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
1314
1315
1316         String url = request.getMethod() + " " + request.getRequestURI();
1317         log.debug(GET_START_HANDLE_REQUEST_OF, url);
1318         try {
1319             ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(containerComponentType);
1320             if (componentTypeEnum == null) {
1321                 log.debug(UNSUPPORTED_COMPONENT_TYPE, containerComponentType);
1322                 return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.UNSUPPORTED_ERROR, containerComponentType));
1323             }
1324
1325             Either<RequirementCapabilityRelDef, ResponseFormat> actionResponse = componentInstanceBusinessLogic.getRelationById(componentId, relationId, userId, componentTypeEnum);
1326             if (actionResponse.isRight()) {
1327                 return buildErrorResponse(actionResponse.right().value());
1328             }
1329             return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), actionResponse.left().value());
1330         } catch (Exception e) {
1331             BeEcompErrorManager.getInstance().logBeRestApiGeneralError("getRelationById");
1332             log.debug("getRelationById unexpected exception", e);
1333             throw e;
1334         }
1335     }
1336
1337     private Either<ComponentInstance, ResponseFormat> convertToResourceInstance(String data) {
1338
1339         Either<ComponentInstance, ResponseFormat> convertStatus = getComponentsUtils().convertJsonToObjectUsingObjectMapper(data, new User(), ComponentInstance.class, null, ComponentTypeEnum.RESOURCE_INSTANCE);
1340         if (convertStatus.isRight()) {
1341             return Either.right(convertStatus.right().value());
1342         }
1343         ComponentInstance resourceInstanceInfo = convertStatus.left().value();
1344
1345         return Either.left(resourceInstanceInfo);
1346     }
1347
1348     private Either<List<ComponentInstance>, ResponseFormat> convertToMultipleResourceInstance(String dataList) {
1349
1350         Either<ComponentInstance[], ResponseFormat> convertStatus = getComponentsUtils().convertJsonToObjectUsingObjectMapper(dataList, new User(), ComponentInstance[].class, null, ComponentTypeEnum.RESOURCE_INSTANCE);
1351         if (convertStatus.isRight()) {
1352             return Either.right(convertStatus.right().value());
1353         }
1354
1355         return Either.left(Arrays.asList(convertStatus.left().value()));
1356     }
1357
1358     private Either<List<ComponentInstanceProperty>, ResponseFormat> convertMultipleProperties(String dataList) {
1359         if (StringUtils.isEmpty(dataList)) {
1360             return Either.right(getComponentsUtils().getResponseFormat(ActionStatus.MISSING_BODY));
1361         }
1362         Either<ComponentInstanceProperty[], ResponseFormat> convertStatus = getComponentsUtils().convertJsonToObjectUsingObjectMapper(dataList, new User(), ComponentInstanceProperty[].class, null, ComponentTypeEnum.RESOURCE_INSTANCE);
1363         if (convertStatus.isRight()) {
1364             return Either.right(convertStatus.right().value());
1365         }
1366         return Either.left(Arrays.asList(convertStatus.left().value()));
1367     }
1368
1369     private Either<List<ComponentInstanceInput>, ResponseFormat> convertMultipleInputs(String dataList) {
1370         if (StringUtils.isEmpty(dataList)) {
1371             return Either.right(getComponentsUtils().getResponseFormat(ActionStatus.MISSING_BODY));
1372         }
1373         Either<ComponentInstanceInput[], ResponseFormat> convertStatus = getComponentsUtils().convertJsonToObjectUsingObjectMapper(dataList, new User(), ComponentInstanceInput[].class, null, ComponentTypeEnum.RESOURCE_INSTANCE);
1374         if (convertStatus.isRight()) {
1375             return Either.right(convertStatus.right().value());
1376         }
1377         return Either.left(Arrays.asList(convertStatus.left().value()));
1378     }
1379
1380
1381     private RequirementCapabilityRelDef convertToRequirementCapabilityRelDef(String data) {
1382
1383         Either<RequirementCapabilityRelDef, ActionStatus> convertStatus = convertJsonToObject(data, RequirementCapabilityRelDef.class);
1384         if (convertStatus.isRight()) {
1385             throw new ByActionStatusComponentException(convertStatus.right().value());
1386         }
1387         return convertStatus.left().value();
1388     }
1389
1390     public <T> Either<T, ActionStatus> convertJsonToObject(String data, Class<T> clazz) {
1391         try {
1392             log.trace("convert json to object. json=\n {}", data);
1393             T t;
1394             t = gsonDeserializer.fromJson(data, clazz);
1395             if (t == null) {
1396                 BeEcompErrorManager.getInstance().logBeInvalidJsonInput("convertJsonToObject");
1397                 log.debug("object is null after converting from json");
1398                 return Either.right(ActionStatus.INVALID_CONTENT);
1399             }
1400             return Either.left(t);
1401         } catch (Exception e) {
1402             // INVALID JSON
1403             BeEcompErrorManager.getInstance().logBeInvalidJsonInput("convertJsonToObject");
1404             log.debug("failed to convert from json", e);
1405             return Either.right(ActionStatus.INVALID_CONTENT);
1406         }
1407     }
1408
1409
1410     @GET
1411     @Path("/{containerComponentType}/{componentId}/paths-to-delete")
1412     @Produces(MediaType.APPLICATION_JSON)
1413     @Operation(description = "Check if forwarding path to delete on version change", method = "GET",
1414             summary = "Returns forwarding paths to delete", responses = {
1415             @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class))))})
1416     public Response changeResourceInstanceVersion( @PathParam("componentId") String componentId,
1417         @QueryParam("componentInstanceId") final String oldComponentInstanceId,
1418         @QueryParam("newComponentInstanceId") final String newComponentInstanceId,
1419         @Parameter(description = "valid values: resources / services",
1420                 schema = @Schema(allowableValues = {ComponentTypeEnum.RESOURCE_PARAM_NAME,
1421                         ComponentTypeEnum.SERVICE_PARAM_NAME}))
1422         @PathParam("containerComponentType") final String containerComponentType,
1423         @Context final HttpServletRequest request) {
1424         if (oldComponentInstanceId == null){
1425             return  buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.MISSING_OLD_COMPONENT_INSTANCE));
1426         }
1427         if (newComponentInstanceId == null){
1428             return  buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.MISSING_NEW_COMPONENT_INSTANCE));
1429         }
1430
1431
1432         String url = request.getMethod() + " " + request.getRequestURI();
1433         log.debug(START_HANDLE_REQUEST_OF, url);
1434         if (componentInstanceBusinessLogic == null) {
1435             log.debug(UNSUPPORTED_COMPONENT_TYPE, containerComponentType);
1436             return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.UNSUPPORTED_ERROR, containerComponentType));
1437         }
1438         ComponentInstance newComponentInstance;
1439         if(StringUtils.isNotEmpty(newComponentInstanceId)){
1440             newComponentInstance=new ComponentInstance();
1441             newComponentInstance.setToscaPresentationValue(JsonPresentationFields.CI_COMPONENT_UID,newComponentInstanceId);
1442         }else{
1443             log.error("missing component id");
1444             return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.MISSING_DATA));
1445         }
1446         Either<Set<String>,ResponseFormat> actionResponse= componentInstanceBusinessLogic.forwardingPathOnVersionChange(
1447             containerComponentType,componentId,oldComponentInstanceId,newComponentInstance);
1448         if (actionResponse.isRight()) {
1449             return buildErrorResponse(actionResponse.right().value());
1450         }
1451         ForwardingPaths forwardingPaths=new ForwardingPaths();
1452         forwardingPaths.setForwardingPathToDelete(actionResponse.left().value());
1453         return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), forwardingPaths);
1454
1455     }
1456
1457     @POST
1458     @Path("/services/{componentId}/copyComponentInstance/{componentInstanceId}")
1459     @Consumes(MediaType.APPLICATION_JSON)
1460     @Produces((MediaType.APPLICATION_JSON))
1461     @Operation(description = "Copy Component Instance", method = "POST",
1462             summary = "Returns updated service information", responses = {
1463             @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Service.class)))),
1464             @ApiResponse(responseCode = "201", description = "Copy and Paste Success"),
1465             @ApiResponse(responseCode = "403", description = "Restricted Operation"),
1466             @ApiResponse(responseCode = "400", description = "Invalid Content / Missing content")})
1467     public Response copyComponentInstance(
1468             @Parameter(description = "service unique id in pasted canvas") @PathParam("componentId") final String containerComponentId,
1469             @Parameter(description = "Data for copying", required = true) String data, @PathParam("componentInstanceId") final String componentInstanceId,
1470             @Context final HttpServletRequest request) {
1471         log.info("Start to copy component instance");
1472
1473         String userId = request.getHeader(Constants.USER_ID_HEADER);
1474         final String CNTAINER_CMPT_TYPE = "services";
1475
1476         try {
1477             ComponentInstance inputComponentInstance = RepresentationUtils.fromRepresentation(data, ComponentInstance.class);
1478             inputComponentInstance.setInvariantName(null);
1479             ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(CNTAINER_CMPT_TYPE);
1480             if (componentInstanceBusinessLogic == null) {
1481                 log.debug(UNSUPPORTED_COMPONENT_TYPE, componentTypeEnum);
1482                 return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.UNSUPPORTED_ERROR, "services"));
1483             }
1484             Either<Map<String, ComponentInstance>, ResponseFormat> copyComponentInstance = componentInstanceBusinessLogic.copyComponentInstance(
1485                     inputComponentInstance, containerComponentId, componentInstanceId, userId);
1486
1487             if (copyComponentInstance.isRight()) {
1488                 log.error("Failed to copy ComponentInstance {}", copyComponentInstance.right().value());
1489                 return buildErrorResponse(copyComponentInstance.right().value());
1490             }
1491
1492             return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK),
1493                     copyComponentInstance.left().value());
1494         } catch (Exception e) {
1495             log.error("Failed to convert json to Map { }", data, e);
1496             return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.USER_DEFINED,
1497                     "Failed to get the copied component instance information"));
1498         }
1499     }
1500
1501     @POST
1502     @Path("/{containerComponentType}/{componentId}/batchDeleteResourceInstances/")
1503     @Consumes(MediaType.APPLICATION_JSON)
1504     @Produces(MediaType.APPLICATION_JSON)
1505     @Operation(description = "Batch Delete ResourceInstances", method = "POST",
1506             responses = {@ApiResponse(responseCode = "203", description = "ResourceInstances deleted"),
1507                     @ApiResponse(responseCode = "403", description = "Restricted Operation"),
1508                     @ApiResponse(responseCode = "400", description = "Invalid Content / Missing Content")})
1509     public Response batchDeleteResourceInstances(
1510             @Parameter(description = "valid values: resources / services / products", schema = @Schema(allowableValues = {ComponentTypeEnum.RESOURCE_PARAM_NAME,
1511                     ComponentTypeEnum.SERVICE_PARAM_NAME,
1512                     ComponentTypeEnum.PRODUCT_PARAM_NAME}))
1513             @PathParam("containerComponentType") final String containerComponentType,
1514             @PathParam("componentId") final String componentId,
1515             @Context final HttpServletRequest request,
1516             @Parameter(description = "Component Instance Id List", required = true) final String componentInstanceIdLisStr) {
1517         try {
1518             if (componentInstanceIdLisStr == null || componentInstanceIdLisStr.isEmpty()) {
1519                 log.error("Empty JSON List was sent",componentInstanceIdLisStr);
1520                 return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
1521             }
1522
1523
1524             if (componentInstanceBusinessLogic == null) {
1525                 log.error(UNSUPPORTED_COMPONENT_TYPE, containerComponentType);
1526                 return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.UNSUPPORTED_ERROR, containerComponentType));
1527             }
1528
1529             Either<List<String>, ResponseFormat> convertResponse = convertToStringList(componentInstanceIdLisStr);
1530
1531             if (convertResponse.isRight()) {
1532                 BeEcompErrorManager.getInstance().logBeSystemError("Resource Instance - batchDeleteResourceInstances");
1533                 log.error(FAILED_TO_CONVERT_RECEIVED_DATA_TO_BE_FORMAT);
1534                 return buildErrorResponse(convertResponse.right().value());
1535             }
1536
1537             String userId = request.getHeader(Constants.USER_ID_HEADER);
1538             List<String> componentInstanceIdList = convertResponse.left().value();
1539             log.debug("batchDeleteResourceInstances componentInstanceIdList is {}", componentInstanceIdList);
1540             Map<String, List<String>> deleteErrorMap = componentInstanceBusinessLogic.batchDeleteComponentInstance(containerComponentType,
1541                     componentId, componentInstanceIdList, userId);
1542
1543             return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), deleteErrorMap);
1544         } catch (Exception e) {
1545             BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Batch Delete ResourceInstances");
1546             log.error("batch delete resource instances with exception" , e);
1547             return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
1548         }
1549
1550     }
1551
1552     @PUT
1553     @Path("/{containerComponentType}/{componentId}/resourceInstance/batchDissociate")
1554     @Consumes(MediaType.APPLICATION_JSON)
1555     @Produces(MediaType.APPLICATION_JSON)
1556     @Operation(description = "Batch Dissociate RI from RI", method = "PUT",
1557             summary = "Returns deleted RelationShip Info", responses = {
1558             @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
1559             @ApiResponse(responseCode = "201", description = "Relationship deleted"),
1560             @ApiResponse(responseCode = "403", description = "Missing Information"),
1561             @ApiResponse(responseCode = "400", description = "Invalid Content / Missing Content")})
1562     public Response batchDissociateRIFromRI(
1563             @Parameter(description = "allowed values are resources/services/products",
1564                     schema = @Schema(allowableValues = {ComponentTypeEnum.RESOURCE_PARAM_NAME,
1565                             ComponentTypeEnum.SERVICE_PARAM_NAME,
1566                             ComponentTypeEnum.PRODUCT_PARAM_NAME}),
1567                     required = true) @PathParam("containerComponentType") final String containerComponentType,
1568             @Parameter(
1569                     description = "unique id of the container component") @PathParam("componentId") final String componentId,
1570             @HeaderParam(value = Constants.USER_ID_HEADER) String userId,
1571             @Parameter(description = "RelationshipInfo", required = true) String data,
1572             @Context final HttpServletRequest request) {
1573
1574
1575         try {
1576             if (data == null || data.length() == 0) {
1577                 log.info("Empty JSON list was sent");
1578                 return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
1579             }
1580
1581             ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(containerComponentType);
1582
1583             if (componentInstanceBusinessLogic == null) {
1584                 log.debug(UNSUPPORTED_COMPONENT_TYPE, containerComponentType);
1585                 return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.UNSUPPORTED_ERROR, containerComponentType));
1586             }
1587
1588             Either<List<RequirementCapabilityRelDef>, ResponseFormat> regInfoWs = convertToRequirementCapabilityRelDefList(data);
1589
1590             if (regInfoWs.isRight()) {
1591                 BeEcompErrorManager.getInstance().logBeSystemError("Resource Instance - batch dissociateRIFromRI");
1592                 log.debug("Failed to convert received data to BE format");
1593                 return buildErrorResponse(regInfoWs.right().value());
1594             }
1595
1596             List<RequirementCapabilityRelDef> requirementDefList = regInfoWs.left().value();
1597             List<RequirementCapabilityRelDef> delOkResult = componentInstanceBusinessLogic.batchDissociateRIFromRI(
1598                     componentId, userId, requirementDefList, componentTypeEnum);
1599
1600             return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), delOkResult);
1601         } catch (Exception e) {
1602             BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Batch Dissociate Resource Instance");
1603             log.debug("batch dissociate resource instance from service failed with exception", e);
1604             return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
1605         }
1606     }
1607
1608     private Either<List<String>, ResponseFormat> convertToStringList(String datalist) {
1609         Either<String[], ResponseFormat> convertStatus = getComponentsUtils().convertJsonToObjectUsingObjectMapper(datalist, new User(), String[].class, null, null);
1610
1611         if (convertStatus.isRight()) {
1612             return Either.right(convertStatus.right().value());
1613         }
1614
1615         return Either.left(Arrays.asList(convertStatus.left().value()));
1616     }
1617
1618     private Either<List<RequirementCapabilityRelDef>, ResponseFormat> convertToRequirementCapabilityRelDefList(String data) {
1619         Either<RequirementCapabilityRelDef[], ResponseFormat> convertStatus = getComponentsUtils().convertJsonToObjectUsingObjectMapper(data, new User(), RequirementCapabilityRelDef[].class, null, null);
1620
1621         if (convertStatus.isRight()) {
1622             return Either.right(convertStatus.right().value());
1623         }
1624
1625         return Either.left(Arrays.asList(convertStatus.left().value()));
1626     }
1627
1628     @POST
1629     @Path("/services/replaceVNF")
1630     @Operation(description = "Replace new VNF based on the existing VNF", method = "POST",
1631             summary = "Return whether the replace VNF is successful", responses = {
1632             @ApiResponse(responseCode = "200", description = "ECOMP component is authenticated and list of Catalog Assets Metadata is returned",
1633                     content = @Content(array = @ArraySchema(schema = @Schema(implementation = ReplaceVNFInfo.class)))),
1634             @ApiResponse(responseCode = "400", description = "Missing  'X-ECOMP-InstanceID'  HTTP header - POL5001"),
1635             @ApiResponse(responseCode = "401",
1636                     description = "ECOMP component  should authenticate itself  and  to  re-send  again  HTTP  request  with its Basic Authentication credentials - POL5002"),
1637             @ApiResponse(responseCode = "403", description = "ECOMP component is not authorized - POL5003"),
1638             @ApiResponse(responseCode = "404",
1639                     description = "Error: Requested '%1' (uuid) resource was not found - SVC4063"),
1640             @ApiResponse(responseCode = "405",
1641                     description = "Method  Not Allowed  :  Invalid HTTP method type used ( PUT,DELETE,POST will be rejected) - POL4050"),
1642             @ApiResponse(responseCode = "500",
1643                     description = "The GET request failed either due to internal SDC problem. ECOMP Component should continue the attempts to get the needed information - POL5000"),
1644             @ApiResponse(responseCode = "409", description = "Service already exist")})
1645     @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
1646     public Response replaceVNF(
1647             @Parameter(description = "The user id",
1648                     required = true) @HeaderParam(value = Constants.USER_ID_HEADER) String userId,
1649             @Parameter(description = "X-ECOMP-RequestID header",
1650                     required = false) @HeaderParam(value = Constants.X_ECOMP_REQUEST_ID_HEADER) String requestId,
1651             @Parameter(description = "X-ECOMP-InstanceID header", required = true)
1652             @HeaderParam(value = Constants.X_ECOMP_INSTANCE_ID_HEADER) final String instanceIdHeader,
1653             @Parameter(description = "Determines the format of the body of the response",
1654                     required = false) @HeaderParam(value = Constants.ACCEPT_HEADER) String accept,
1655             @Parameter(description = "The username and password",
1656                     required = true) @HeaderParam(value = Constants.AUTHORIZATION_HEADER) String authorization,
1657             @Context final HttpServletRequest request,
1658             @Parameter(description = "Resource object to be created", required = true) String data) {
1659
1660         String url = request.getMethod() + " " + request.getRequestURI();
1661         log.debug("replaceVNF: Start handle request of {}", url);
1662         User modifier = new User();
1663         modifier.setUserId(userId);
1664         log.debug("replaceVNF:modifier id is {}", userId);
1665         validateNotEmptyBody(data);
1666
1667         Either<ReplaceVNFInfo, ResponseFormat> convertResponse = parseToReplaceVNFInfo(data, modifier);
1668         if (convertResponse.isRight()) {
1669             throw new ByResponseFormatComponentException(convertResponse.right().value());
1670         }
1671
1672         log.debug("replaceVNF:get ReplaceVNFInfo success");
1673
1674         String containerComponentType = "services";
1675         ReplaceVNFInfo replaceVNFInfo = convertResponse.left().value();
1676         String serviceUniqueId = replaceVNFInfo.getServiceUniqueId();
1677         String abstractResourceUniqueId = replaceVNFInfo.getAbstractResourceUniqueId();
1678         
1679         ComponentInstance componentInstance = replaceVNFInfo.getRealVNFComponentInstance();
1680         log.debug("replaceVNF:get ReplaceVNFInfo,serviceUniqueId:{},abstractResourceUniqueId:{}",
1681                 serviceUniqueId,abstractResourceUniqueId);
1682         try {
1683             /**
1684              * delete vnf
1685              */
1686             ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(containerComponentType);
1687             if (componentInstanceBusinessLogic == null) {
1688                 log.debug("replaceVNF:Unsupported component type {}", containerComponentType);
1689                 return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.UNSUPPORTED_ERROR, containerComponentType));
1690             }
1691             Either<ComponentInstance, ResponseFormat> componentInstanceEither = componentInstanceBusinessLogic.deleteAbstractComponentInstance(containerComponentType, serviceUniqueId, abstractResourceUniqueId, userId);
1692             if (componentInstanceEither.isRight()) {
1693                 log.debug("replaceVNF:delete Abstract ComponentInstance field");
1694                 return buildErrorResponse(componentInstanceEither.right().value());
1695             }
1696             /**
1697              * add vnf
1698              */
1699             log.debug("replaceVNF,start add vnf");
1700             componentInstance.setInvariantName(null);
1701             componentInstance.setCreatedFrom(CreatedFrom.UI);
1702
1703             Either<ComponentInstance, ResponseFormat> realComponentInstance = componentInstanceBusinessLogic.createRealComponentInstance(containerComponentType, serviceUniqueId, userId, componentInstance);
1704             if (realComponentInstance.isRight()) {
1705                 log.debug("replaceVNF:filed to add vnf");
1706                 return buildErrorResponse(realComponentInstance.right().value());
1707             }
1708             ComponentInstance newComponentInstance = realComponentInstance.left().value();
1709             log.debug("replaceVNF:success to add vnf");
1710             
1711             return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), newComponentInstance);
1712         } catch (Exception e) {
1713             BeEcompErrorManager.getInstance().logBeRestApiGeneralError("replaceVNF");
1714             log.debug("replaceVNF with exception", e);
1715             throw e;
1716         }
1717     }
1718
1719     private Either<ReplaceVNFInfo, ResponseFormat> parseToReplaceVNFInfo(String serviceJson, User user) {
1720         log.debug("enter parseToReplaceVNFInfo,get serviceJson:{}",serviceJson);
1721         return getComponentsUtils().convertJsonToObjectUsingObjectMapper(serviceJson, user, ReplaceVNFInfo.class, AuditingActionEnum.CREATE_RESOURCE, ComponentTypeEnum.SERVICE);
1722     }
1723
1724 }