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