2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2021 Nordix Foundation. 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
11 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
18 * SPDX-License-Identifier: Apache-2.0
19 * ============LICENSE_END=========================================================
22 package org.openecomp.sdc.be.servlets;
24 import static org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum.RESOURCE;
26 import fj.data.Either;
27 import io.swagger.v3.oas.annotations.Operation;
28 import io.swagger.v3.oas.annotations.Parameter;
29 import io.swagger.v3.oas.annotations.media.ArraySchema;
30 import io.swagger.v3.oas.annotations.media.Content;
31 import io.swagger.v3.oas.annotations.media.Schema;
32 import io.swagger.v3.oas.annotations.responses.ApiResponse;
33 import io.swagger.v3.oas.annotations.servers.Server;
34 import io.swagger.v3.oas.annotations.tags.Tag;
35 import java.io.IOException;
36 import java.util.Optional;
37 import javax.servlet.http.HttpServletRequest;
38 import javax.ws.rs.Consumes;
39 import javax.ws.rs.HeaderParam;
40 import javax.ws.rs.POST;
41 import javax.ws.rs.PUT;
42 import javax.ws.rs.Path;
43 import javax.ws.rs.PathParam;
44 import javax.ws.rs.Produces;
45 import javax.ws.rs.core.Context;
46 import javax.ws.rs.core.MediaType;
47 import javax.ws.rs.core.Response;
48 import org.apache.commons.io.IOUtils;
49 import org.openecomp.sdc.be.components.impl.ComponentInstanceBusinessLogic;
50 import org.openecomp.sdc.be.components.impl.ComponentInterfaceOperationBusinessLogic;
51 import org.openecomp.sdc.be.components.impl.ResourceImportManager;
52 import org.openecomp.sdc.be.components.impl.exceptions.ComponentException;
53 import org.openecomp.sdc.be.config.BeEcompErrorManager;
54 import org.openecomp.sdc.be.dao.api.ActionStatus;
55 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
56 import org.openecomp.sdc.be.impl.ComponentsUtils;
57 import org.openecomp.sdc.be.impl.ServletUtils;
58 import org.openecomp.sdc.be.model.Component;
59 import org.openecomp.sdc.be.model.ComponentInstance;
60 import org.openecomp.sdc.be.model.InterfaceDefinition;
61 import org.openecomp.sdc.be.model.User;
62 import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum;
63 import org.openecomp.sdc.be.ui.model.UiComponentDataTransfer;
64 import org.openecomp.sdc.common.api.Constants;
65 import org.openecomp.sdc.common.datastructure.Wrapper;
66 import org.openecomp.sdc.common.util.ValidationUtils;
67 import org.openecomp.sdc.exception.ResponseFormat;
68 import org.slf4j.Logger;
69 import org.slf4j.LoggerFactory;
70 import org.springframework.beans.factory.annotation.Autowired;
71 import org.springframework.stereotype.Controller;
74 @Tag(name = "SDCE-2 APIs")
75 @Consumes(MediaType.APPLICATION_JSON)
76 @Produces(MediaType.APPLICATION_JSON)
77 @Server(url = "/sdc2/rest")
79 public class ComponentInterfaceOperationServlet extends AbstractValidationsServlet {
81 private static final Logger LOGGER = LoggerFactory.getLogger(ComponentInterfaceOperationServlet.class);
82 private static final String START_HANDLE_REQUEST_OF = "Start handle {} request of {}";
83 private static final String MODIFIER_ID_IS = "modifier id is {}";
84 private static final String FAILED_TO_UPDATE_INTERFACE_OPERATION = "failed to update Interface Operation on component instance {}";
85 private static final String UPDATE_INTERFACE_OPERATION = "Update Interface Operation on Component Instance";
86 private static final String FAILED_TO_UPDATE_INTERFACE_OPERATION_WITH_ERROR = "Failed to update Interface Operation with an error";
87 private static final String INTERFACE_OPERATION_CONTENT_INVALID = "Interface Operation content is invalid - {}";
88 private static final String UNSUPPORTED_COMPONENT_TYPE = "Unsupported component type {}";
89 private static final String INTERFACE_OPERATION_SUCCESSFULLY_UPDATED =
90 "Interface Operation successfully updated on component instance with id {}";
91 private final ComponentInterfaceOperationBusinessLogic componentInterfaceOperationBusinessLogic;
94 public ComponentInterfaceOperationServlet(final ComponentInstanceBusinessLogic componentInstanceBL,
95 final ComponentsUtils componentsUtils, final ServletUtils servletUtils,
96 final ResourceImportManager resourceImportManager,
97 final ComponentInterfaceOperationBusinessLogic componentInterfaceOperationBusinessLogic) {
98 super(componentInstanceBL, componentsUtils, servletUtils, resourceImportManager);
99 this.componentInterfaceOperationBusinessLogic = componentInterfaceOperationBusinessLogic;
103 @Path("/{componentType}/{componentId}/componentInstance/{componentInstanceId}/interfaceOperation")
104 @Consumes(MediaType.APPLICATION_JSON)
105 @Produces(MediaType.APPLICATION_JSON)
106 @Operation(description = "Update Interface Operation", method = "PUT", summary = "Update Interface Operation on ComponentInstance", responses = {
107 @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
108 @ApiResponse(responseCode = "201", description = "Update Interface Operation"),
109 @ApiResponse(responseCode = "403", description = "Restricted operation"),
110 @ApiResponse(responseCode = "400", description = "Invalid content / Missing content")})
111 public Response updateComponentInstanceInterfaceOperation(
112 @Parameter(description = "valid values: resources / services", schema = @Schema(allowableValues = {ComponentTypeEnum.RESOURCE_PARAM_NAME,
113 ComponentTypeEnum.SERVICE_PARAM_NAME})) @PathParam("componentType") String componentType,
114 @Parameter(description = "Component Id") @PathParam("componentId") String componentId,
115 @Parameter(description = "Component Instance Id") @PathParam("componentInstanceId") String componentInstanceId,
116 @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) throws IOException {
117 LOGGER.debug(START_HANDLE_REQUEST_OF, request.getMethod(), request.getRequestURI());
118 userId = ValidationUtils.sanitizeInputString(userId);
119 componentType = ValidationUtils.sanitizeInputString(componentType);
120 componentInstanceId = ValidationUtils.sanitizeInputString(componentInstanceId);
121 LOGGER.debug(MODIFIER_ID_IS, userId);
122 final User userModifier = componentInterfaceOperationBusinessLogic.validateUser(userId);
123 final ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(componentType);
124 if (componentTypeEnum == null) {
125 LOGGER.debug(UNSUPPORTED_COMPONENT_TYPE, componentType);
126 return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.UNSUPPORTED_ERROR, componentType));
128 final byte[] bytes = IOUtils.toByteArray(request.getInputStream());
129 if (bytes == null || bytes.length == 0) {
130 LOGGER.error(INTERFACE_OPERATION_CONTENT_INVALID, "content is empty");
131 return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
133 final String data = new String(bytes);
134 final Optional<InterfaceDefinition> mappedInterfaceOperationData = getMappedInterfaceData(data, userModifier, componentTypeEnum);
135 if (mappedInterfaceOperationData.isEmpty()) {
136 LOGGER.error(INTERFACE_OPERATION_CONTENT_INVALID, data);
137 return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
139 final Wrapper<ResponseFormat> errorWrapper = new Wrapper<>();
141 final Optional<ComponentInstance> actionResponse = componentInterfaceOperationBusinessLogic.updateComponentInstanceInterfaceOperation(
142 componentId, componentInstanceId, mappedInterfaceOperationData.get(), componentTypeEnum, errorWrapper, true);
143 if (actionResponse.isEmpty()) {
144 LOGGER.error(FAILED_TO_UPDATE_INTERFACE_OPERATION, componentInstanceId);
145 return buildErrorResponse(errorWrapper.getInnerElement());
147 LOGGER.debug(INTERFACE_OPERATION_SUCCESSFULLY_UPDATED, componentInstanceId);
148 return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.CREATED), actionResponse.get());
150 } catch (final Exception e) {
151 BeEcompErrorManager.getInstance().logBeRestApiGeneralError(UPDATE_INTERFACE_OPERATION);
152 LOGGER.error(FAILED_TO_UPDATE_INTERFACE_OPERATION_WITH_ERROR, e);
153 return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
158 @Path("/resources/{componentId}/interfaceOperation")
159 @Consumes(MediaType.APPLICATION_JSON)
160 @Produces(MediaType.APPLICATION_JSON)
161 @Operation(description = "Update Interface Operation", method = "PUT", summary = "Update Interface Operation on ComponentInstance", responses = {
162 @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
163 @ApiResponse(responseCode = "201", description = "Update Interface Operation"),
164 @ApiResponse(responseCode = "403", description = "Restricted operation"),
165 @ApiResponse(responseCode = "400", description = "Invalid content / Missing content")})
166 public Response updateResourceInterfaceOperation(
167 @Parameter(description = "Component Id") @PathParam("componentId") String componentId,
168 @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) throws IOException {
169 LOGGER.debug(START_HANDLE_REQUEST_OF, request.getMethod(), request.getRequestURI());
170 LOGGER.debug(MODIFIER_ID_IS, userId);
171 final User userModifier = componentInterfaceOperationBusinessLogic.validateUser(userId);
172 final byte[] bytes = IOUtils.toByteArray(request.getInputStream());
173 if (bytes == null || bytes.length == 0) {
174 LOGGER.error(INTERFACE_OPERATION_CONTENT_INVALID);
175 return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
177 final ComponentTypeEnum componentType = RESOURCE;
178 final String data = new String(bytes);
179 final Optional<InterfaceDefinition> mappedInterfaceOperationData = getMappedInterfaceData(data, userModifier, componentType);
180 if (mappedInterfaceOperationData.isEmpty()) {
181 LOGGER.error(INTERFACE_OPERATION_CONTENT_INVALID, data);
182 return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
184 final Wrapper<ResponseFormat> errorWrapper = new Wrapper<>();
186 final Optional<Component> actionResponse = componentInterfaceOperationBusinessLogic
187 .updateResourceInterfaceOperation(componentId, userId, mappedInterfaceOperationData.get(), componentType,
189 if (actionResponse.isEmpty()) {
190 LOGGER.error(FAILED_TO_UPDATE_INTERFACE_OPERATION, componentId);
191 return buildErrorResponse(errorWrapper.getInnerElement());
193 LOGGER.debug(INTERFACE_OPERATION_SUCCESSFULLY_UPDATED, componentId);
194 return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.CREATED), actionResponse.get());
196 } catch (final ComponentException e) {
197 //let it be handled by org.openecomp.sdc.be.servlets.exception.ComponentExceptionMapper
199 } catch (final Exception e) {
200 BeEcompErrorManager.getInstance().logBeRestApiGeneralError(UPDATE_INTERFACE_OPERATION);
201 LOGGER.error(FAILED_TO_UPDATE_INTERFACE_OPERATION_WITH_ERROR, e);
202 return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
207 @Path("/{componentType}/{componentId}/componentInstance/{componentInstanceId}/interfaceOperation")
208 @Consumes(MediaType.APPLICATION_JSON)
209 @Produces(MediaType.APPLICATION_JSON)
210 @Operation(description = "Create Interface Operation", method = "POST", summary = "Create Interface Operation on ComponentInstance", responses = {
211 @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
212 @ApiResponse(responseCode = "201", description = "Create Interface Operation"),
213 @ApiResponse(responseCode = "403", description = "Restricted operation"),
214 @ApiResponse(responseCode = "400", description = "Invalid content / Missing content")})
215 public Response createComponentInstanceInterfaceOperation(
216 @Parameter(description = "valid values: resources / services", schema = @Schema(allowableValues = {ComponentTypeEnum.RESOURCE_PARAM_NAME,
217 ComponentTypeEnum.SERVICE_PARAM_NAME})) @PathParam("componentType") String componentType,
218 @Parameter(description = "Component Id") @PathParam("componentId") String componentId,
219 @Parameter(description = "Component Instance Id") @PathParam("componentInstanceId") String componentInstanceId,
220 @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) throws IOException {
221 LOGGER.debug(START_HANDLE_REQUEST_OF, request.getMethod(), request.getRequestURI());
222 userId = ValidationUtils.sanitizeInputString(userId);
223 componentType = ValidationUtils.sanitizeInputString(componentType);
224 componentInstanceId = ValidationUtils.sanitizeInputString(componentInstanceId);
225 LOGGER.debug(MODIFIER_ID_IS, userId);
226 final User userModifier = componentInterfaceOperationBusinessLogic.validateUser(userId);
227 final ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(componentType);
228 if (componentTypeEnum == null) {
229 LOGGER.debug(UNSUPPORTED_COMPONENT_TYPE, componentType);
230 return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.UNSUPPORTED_ERROR, componentType));
232 final byte[] bytes = IOUtils.toByteArray(request.getInputStream());
233 if (bytes == null || bytes.length == 0) {
234 LOGGER.error(INTERFACE_OPERATION_CONTENT_INVALID, "content is empty");
235 return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
237 final String data = new String(bytes);
238 final Optional<InterfaceDefinition> mappedInterfaceOperationData = getMappedInterfaceData(data, userModifier, componentTypeEnum);
239 if (mappedInterfaceOperationData.isEmpty()) {
240 LOGGER.error(INTERFACE_OPERATION_CONTENT_INVALID, data);
241 return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
243 final Wrapper<ResponseFormat> errorWrapper = new Wrapper<>();
245 final Optional<ComponentInstance> actionResponse = componentInterfaceOperationBusinessLogic.createComponentInstanceInterfaceOperation(
246 componentId, componentInstanceId, mappedInterfaceOperationData.get(), componentTypeEnum, errorWrapper, true);
247 if (actionResponse.isEmpty()) {
248 LOGGER.error(FAILED_TO_UPDATE_INTERFACE_OPERATION, componentInstanceId);
249 return buildErrorResponse(errorWrapper.getInnerElement());
251 LOGGER.debug(INTERFACE_OPERATION_SUCCESSFULLY_UPDATED, componentInstanceId);
252 return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.CREATED), actionResponse.get());
254 } catch (final Exception e) {
255 BeEcompErrorManager.getInstance().logBeRestApiGeneralError(UPDATE_INTERFACE_OPERATION);
256 LOGGER.error(FAILED_TO_UPDATE_INTERFACE_OPERATION_WITH_ERROR, e);
257 return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
262 @Path("/{componentType}/{componentId}/resource/interfaceOperation")
263 @Consumes(MediaType.APPLICATION_JSON)
264 @Produces(MediaType.APPLICATION_JSON)
265 @Operation(description = "Create Interface Operation", method = "POST", summary = "Create Interface Operation on ComponentInstance", responses = {
266 @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
267 @ApiResponse(responseCode = "201", description = "Create Interface Operation"),
268 @ApiResponse(responseCode = "403", description = "Restricted operation"),
269 @ApiResponse(responseCode = "400", description = "Invalid content / Missing content")})
270 public Response createInterfaceOperationInResource(
271 @Parameter(description = "valid values: resources", schema = @Schema(allowableValues = {ComponentTypeEnum.RESOURCE_PARAM_NAME}))
272 @PathParam("componentType") final String componentType,
273 @Parameter(description = "Component Id") @PathParam("componentId") String componentId,
274 @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) throws IOException {
275 LOGGER.debug(START_HANDLE_REQUEST_OF, request.getMethod(), request.getRequestURI());
276 LOGGER.debug(MODIFIER_ID_IS, userId);
277 final User userModifier = componentInterfaceOperationBusinessLogic.validateUser(userId);
278 final ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(componentType);
279 if (componentTypeEnum == null) {
280 LOGGER.debug(UNSUPPORTED_COMPONENT_TYPE, componentType);
281 return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.UNSUPPORTED_ERROR, componentType));
283 final byte[] bytes = IOUtils.toByteArray(request.getInputStream());
284 if (bytes == null || bytes.length == 0) {
285 LOGGER.error(INTERFACE_OPERATION_CONTENT_INVALID);
286 return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
288 final String data = new String(bytes);
289 final Optional<InterfaceDefinition> mappedInterfaceOperationData = getMappedInterfaceData(data, userModifier, componentTypeEnum);
290 if (mappedInterfaceOperationData.isEmpty()) {
291 LOGGER.error(INTERFACE_OPERATION_CONTENT_INVALID, data);
292 return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
294 final Wrapper<ResponseFormat> errorWrapper = new Wrapper<>();
296 final Optional<Component> actionResponse = componentInterfaceOperationBusinessLogic.createInterfaceOperationInResource(
297 componentId, mappedInterfaceOperationData.get(), componentTypeEnum, errorWrapper, true);
298 if (actionResponse.isEmpty()) {
299 LOGGER.error(FAILED_TO_UPDATE_INTERFACE_OPERATION, componentId);
300 return buildErrorResponse(errorWrapper.getInnerElement());
302 LOGGER.debug(INTERFACE_OPERATION_SUCCESSFULLY_UPDATED, componentId);
303 return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.CREATED), actionResponse.get());
305 } catch (final Exception e) {
306 BeEcompErrorManager.getInstance().logBeRestApiGeneralError(UPDATE_INTERFACE_OPERATION);
307 LOGGER.error(FAILED_TO_UPDATE_INTERFACE_OPERATION_WITH_ERROR, e);
308 return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
312 private Optional<InterfaceDefinition> getMappedInterfaceData(final String inputJson, final User user, final ComponentTypeEnum componentTypeEnum) {
313 final Either<UiComponentDataTransfer, ResponseFormat> uiComponentEither = getComponentsUtils()
314 .convertJsonToObjectUsingObjectMapper(inputJson, user, UiComponentDataTransfer.class, AuditingActionEnum.UPDATE_RESOURCE_METADATA,
316 return uiComponentEither.left().value().getInterfaces().values().stream().findFirst();