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