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