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