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