2d2b21e4ac24c2b083a4f38c985079b2cec82f41
[sdc.git] / catalog-be / src / main / java / org / openecomp / sdc / be / servlets / RequirementServlet.java
1 /*
2  * Copyright © 2016-2018 European Support Limited
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package org.openecomp.sdc.be.servlets;
18
19 import com.jcabi.aspects.Loggable;
20 import fj.data.Either;
21 import io.swagger.v3.oas.annotations.Operation;
22 import io.swagger.v3.oas.annotations.Parameter;
23 import io.swagger.v3.oas.annotations.media.ArraySchema;
24 import io.swagger.v3.oas.annotations.media.Content;
25 import io.swagger.v3.oas.annotations.media.Schema;
26 import io.swagger.v3.oas.annotations.responses.ApiResponse;
27 import io.swagger.v3.oas.annotations.servers.Server;
28 import io.swagger.v3.oas.annotations.servers.Servers;
29 import io.swagger.v3.oas.annotations.tags.Tag;
30 import io.swagger.v3.oas.annotations.tags.Tags;
31 import org.openecomp.sdc.be.components.impl.ComponentInstanceBusinessLogic;
32 import org.openecomp.sdc.be.components.impl.RequirementBusinessLogic;
33 import org.openecomp.sdc.be.components.impl.ResourceImportManager;
34 import org.openecomp.sdc.be.components.impl.aaf.AafPermission;
35 import org.openecomp.sdc.be.components.impl.aaf.PermissionAllowed;
36 import org.openecomp.sdc.be.config.BeEcompErrorManager;
37 import org.openecomp.sdc.be.dao.api.ActionStatus;
38 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
39 import org.openecomp.sdc.be.impl.ComponentsUtils;
40 import org.openecomp.sdc.be.impl.ServletUtils;
41 import org.openecomp.sdc.be.model.RequirementDefinition;
42 import org.openecomp.sdc.be.model.User;
43 import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum;
44 import org.openecomp.sdc.be.ui.model.UiComponentDataTransfer;
45 import org.openecomp.sdc.be.user.UserBusinessLogic;
46 import org.openecomp.sdc.common.api.Constants;
47 import org.openecomp.sdc.common.log.wrappers.Logger;
48 import org.openecomp.sdc.exception.ResponseFormat;
49 import org.springframework.stereotype.Controller;
50
51 import javax.inject.Inject;
52 import javax.servlet.http.HttpServletRequest;
53 import javax.ws.rs.Consumes;
54 import javax.ws.rs.DELETE;
55 import javax.ws.rs.GET;
56 import javax.ws.rs.HeaderParam;
57 import javax.ws.rs.POST;
58 import javax.ws.rs.PUT;
59 import javax.ws.rs.Path;
60 import javax.ws.rs.PathParam;
61 import javax.ws.rs.Produces;
62 import javax.ws.rs.core.Context;
63 import javax.ws.rs.core.MediaType;
64 import javax.ws.rs.core.Response;
65 import java.util.List;
66 import java.util.Optional;
67
68 @Loggable(prepend = true, value = Loggable.DEBUG, trim = false)
69 @Path("/v1/catalog")
70 @Consumes(MediaType.APPLICATION_JSON)
71 @Produces(MediaType.APPLICATION_JSON)
72 @Tags({@Tag(name = "SDC Internal APIs")})
73 @Servers({@Server(url = "/sdc2/rest")})
74 @Controller
75 public class RequirementServlet extends AbstractValidationsServlet {
76     private static final Logger LOGGER = Logger.getLogger(RequirementServlet.class);
77     private final RequirementBusinessLogic requirementBusinessLogic;
78
79     @Inject
80     public RequirementServlet(UserBusinessLogic userBusinessLogic,
81             ComponentInstanceBusinessLogic componentInstanceBL,
82             ComponentsUtils componentsUtils, ServletUtils servletUtils,
83             ResourceImportManager resourceImportManager,
84             RequirementBusinessLogic requirementBusinessLogic) {
85         super(userBusinessLogic, componentInstanceBL, componentsUtils, servletUtils, resourceImportManager);
86         this.requirementBusinessLogic = requirementBusinessLogic;
87     }
88
89     @POST
90     @Consumes(MediaType.APPLICATION_JSON)
91     @Produces(MediaType.APPLICATION_JSON)
92     @Path("/resources/{resourceId}/requirements")
93     @Operation(description = "Create requirements on resource", method = "POST",
94             summary = "Create requirements on resource", responses = {
95             @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
96             @ApiResponse(responseCode = "201", description = "Create requirements"),
97             @ApiResponse(responseCode = "403", description = "Restricted operation"),
98             @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
99             @ApiResponse(responseCode = "409", description = "requirement already exist")})
100     @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
101     public Response createRequirementsOnResource(
102             @Parameter(description = "Requirement to create", required = true) String data,
103             @Parameter(description = "Resource Id") @PathParam("resourceId") String resourceId,
104             @Context final HttpServletRequest request,
105             @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
106         return createOrUpdate(data, "resources" , resourceId, request,
107                 userId, false, "createRequirements");
108     }
109
110
111     @PUT
112     @Consumes(MediaType.APPLICATION_JSON)
113     @Produces(MediaType.APPLICATION_JSON)
114     @Path("/resources/{resourceId}/requirements")
115     @Operation(description = "Update Requirements on resource", method = "PUT",
116             summary = "Update Requirements on resource", responses = {@ApiResponse(
117             content = @Content(array = @ArraySchema(schema = @Schema(implementation = RequirementDefinition.class)))),
118             @ApiResponse(responseCode = "201", description = "Update Requirements"),
119             @ApiResponse(responseCode = "403", description = "Restricted operation"),
120             @ApiResponse(responseCode = "400", description = "Invalid content / Missing content")})
121     @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
122     public Response updateRequirementsOnResource(
123             @Parameter(description = "Requirements to update", required = true) String data,
124             @Parameter(description = "Component Id") @PathParam("resourceId") String resourceId,
125             @Context final HttpServletRequest request,
126             @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
127         return createOrUpdate(data, "resources", resourceId, request,
128                 userId, true, "updateRequirements");
129     }
130
131     @GET
132     @Consumes(MediaType.APPLICATION_JSON)
133     @Produces(MediaType.APPLICATION_JSON)
134     @Path("/resources/{resourceId}/requirements/{requirementId}")
135     @Operation(description = "Get Requirement from resource", method = "GET", summary = "GET Requirement from resource",
136             responses = {@ApiResponse(content = @Content(
137                     array = @ArraySchema(schema = @Schema(implementation = RequirementDefinition.class)))),
138                     @ApiResponse(responseCode = "201", description = "GET requirement"),
139                     @ApiResponse(responseCode = "403", description = "Restricted operation"),
140                     @ApiResponse(responseCode = "400", description = "Invalid content / Missing content")})
141     @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
142     public Response getRequirementsFromResource(
143             @Parameter(description = "Resource Id") @PathParam("resourceId") String resourceId,
144             @Parameter(description = "Requirement Id") @PathParam("requirementId") String requirementId,
145             @Context final HttpServletRequest request,
146             @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
147
148         return get(requirementId, resourceId, request, userId);
149     }
150
151     @DELETE
152     @Consumes(MediaType.APPLICATION_JSON)
153     @Produces(MediaType.APPLICATION_JSON)
154     @Path("/resources/{resourceId}/requirements/{requirementId}")
155     @Operation(description = "Delete requirements from resource", method = "DELETE",
156             summary = "Delete requirements from resource", responses = {@ApiResponse(
157             content = @Content(array = @ArraySchema(schema = @Schema(implementation = RequirementDefinition.class)))),
158             @ApiResponse(responseCode = "201", description = "Delete requirement"),
159             @ApiResponse(responseCode = "403", description = "Restricted operation"),
160             @ApiResponse(responseCode = "400", description = "Invalid content / Missing content")})
161     @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
162     public Response deleteRequirementsFromResource(
163             @Parameter(description = "Resource Id") @PathParam("resourceId") String resourceId,
164             @Parameter(description = "requirement Id") @PathParam("requirementId") String requirementId,
165             @Context final HttpServletRequest request,
166             @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
167         return delete(requirementId, resourceId, request, userId);
168     }
169
170     @POST
171     @Consumes(MediaType.APPLICATION_JSON)
172     @Produces(MediaType.APPLICATION_JSON)
173     @Path("/services/{serviceId}/requirements")
174     @Operation(description = "Create requirements on service", method = "POST",
175             summary = "Create requirements on service", responses = {
176             @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
177             @ApiResponse(responseCode = "201", description = "Create Requirements"),
178             @ApiResponse(responseCode = "403", description = "Restricted operation"),
179             @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
180             @ApiResponse(responseCode = "409", description = "Requirement already exist")})
181     @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
182     public Response createRequirementsOnService(
183             @Parameter(description = "Requirements to create", required = true) String data,
184             @Parameter(description = "Service Id") @PathParam("serviceId") String serviceId,
185             @Context final HttpServletRequest request,
186             @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
187         return createOrUpdate(data, "services" , serviceId, request, userId,
188                 false , "createRequirements");
189     }
190
191
192     @PUT
193     @Consumes(MediaType.APPLICATION_JSON)
194     @Produces(MediaType.APPLICATION_JSON)
195     @Path("/services/{serviceId}/requirements")
196     @Operation(description = "Update requirements on service", method = "PUT",
197             summary = "Update requirements on service", responses = {@ApiResponse(
198             content = @Content(array = @ArraySchema(schema = @Schema(implementation = RequirementDefinition.class)))),
199             @ApiResponse(responseCode = "201", description = "Update requirements"),
200             @ApiResponse(responseCode = "403", description = "Restricted operation"),
201             @ApiResponse(responseCode = "400", description = "Invalid content / Missing content")})
202     @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
203     public Response updateRequirementsOnService(
204             @Parameter(description = "Requirements to update", required = true) String data,
205             @Parameter(description = "Component Id") @PathParam("serviceId") String serviceId,
206             @Context final HttpServletRequest request,
207             @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
208         return createOrUpdate(data, "services", serviceId, request, userId,
209                 true, "updateRequirements");
210     }
211
212     @GET
213     @Consumes(MediaType.APPLICATION_JSON)
214     @Produces(MediaType.APPLICATION_JSON)
215     @Path("/services/{serviceId}/requirements/{requirementId}")
216     @Operation(description = "Get requirement from service", method = "GET", summary = "GET requirement from service",
217             responses = {@ApiResponse(content = @Content(
218                     array = @ArraySchema(schema = @Schema(implementation = RequirementDefinition.class)))),
219                     @ApiResponse(responseCode = "201", description = "GET Requirements"),
220                     @ApiResponse(responseCode = "403", description = "Restricted operation"),
221                     @ApiResponse(responseCode = "400", description = "Invalid content / Missing content")})
222     @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
223     public Response getRequirementsOnService(
224             @Parameter(description = "Service Id") @PathParam("serviceId") String serviceId,
225             @Parameter(description = "Requirement Id") @PathParam("requirementId") String requirementId,
226             @Context final HttpServletRequest request,
227             @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
228
229         return get(requirementId, serviceId, request, userId);
230     }
231
232
233     @DELETE
234     @Consumes(MediaType.APPLICATION_JSON)
235     @Produces(MediaType.APPLICATION_JSON)
236     @Path("/services/{serviceId}/requirements/{requirementId}")
237     @Operation(description = "Delete requirement from service", method = "DELETE",
238             summary = "Delete requirement from service", responses = {@ApiResponse(
239             content = @Content(array = @ArraySchema(schema = @Schema(implementation = RequirementDefinition.class)))),
240             @ApiResponse(responseCode = "201", description = "Delete Requirements"),
241             @ApiResponse(responseCode = "403", description = "Restricted operation"),
242             @ApiResponse(responseCode = "400", description = "Invalid content / Missing content")})
243     @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
244     public Response deleteRequirementsOnService(
245             @Parameter(description = "Service Id") @PathParam("serviceId") String serviceId,
246             @Parameter(description = "Requirement Id") @PathParam("requirementId") String requirementId,
247             @Context final HttpServletRequest request,
248             @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
249         return delete(requirementId, serviceId, request, userId);
250     }
251
252
253     private Response createOrUpdate (String data, String componentType, String componentId,
254                                      HttpServletRequest request, String userId,
255                                      boolean isUpdate, String errorContext) {
256         String url = request.getMethod() + " " + request.getRequestURI();
257
258         User modifier = new User();
259         modifier.setUserId(userId);
260         LOGGER.debug("Start create or update request of {} with modifier id {}", url, userId);
261
262         try {
263             String componentIdLower = componentId.toLowerCase();
264
265             Either<List<RequirementDefinition>, ResponseFormat> mappedRequirementDataEither =
266                     getMappedRequirementData(data, modifier, ComponentTypeEnum.findByParamName(componentType));
267             if(mappedRequirementDataEither.isRight()) {
268                 LOGGER.error("Failed to create or update requirements");
269                 return buildErrorResponse(mappedRequirementDataEither.right().value());
270             }
271             List<RequirementDefinition> mappedRequirementData = mappedRequirementDataEither.left().value();
272             Either<List<RequirementDefinition>, ResponseFormat> actionResponse;
273             if(isUpdate) {
274                 actionResponse = requirementBusinessLogic.updateRequirements(componentIdLower, mappedRequirementData, modifier,
275                         errorContext, true);
276             } else {
277                 actionResponse = requirementBusinessLogic.createRequirements(componentIdLower, mappedRequirementData, modifier,
278                         errorContext, true);
279             }
280
281             if (actionResponse.isRight()) {
282                 LOGGER.error("Failed to create or update requirements");
283                 return buildErrorResponse(actionResponse.right().value());
284             }
285
286             return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK),
287                     actionResponse.left().value());
288         } catch (Exception e) {
289             BeEcompErrorManager.getInstance().logBeRestApiGeneralError("requirements create or update");
290             LOGGER.error("Failed to create or update requirements with an error", e);
291             return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
292         }
293     }
294
295     private Response get (String requirementIdToGet,  String componentId,
296                           HttpServletRequest request, String userId){
297         String url = request.getMethod() + " " + request.getRequestURI();
298
299         User modifier = new User();
300         modifier.setUserId(userId);
301         LOGGER.debug("Start get request of {} with modifier id {}", url, userId);
302
303         try {
304             String componentIdLower = componentId.toLowerCase();
305
306             Either<RequirementDefinition, ResponseFormat> actionResponse = requirementBusinessLogic
307                     .getRequirement(componentIdLower, requirementIdToGet, modifier, true);
308             if (actionResponse.isRight()) {
309                 LOGGER.error("failed to get requirements");
310                 return buildErrorResponse(actionResponse.right().value());
311             }
312             Object result = RepresentationUtils.toFilteredRepresentation(actionResponse.left().value());
313             return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), result);
314         } catch (Exception e) {
315             BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Get requirements");
316             LOGGER.error("get requirements failed with exception", e);
317             return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
318         }
319     }
320
321     private Response delete (String requirementId, String componentId, HttpServletRequest
322                                         request, String userId){
323         String url = request.getMethod() + " " + request.getRequestURI();
324
325         User modifier = new User();
326         modifier.setUserId(userId);
327         LOGGER.debug("Start delete request of {} with modifier id {}", url, userId);
328
329         try {
330             String componentIdLower = componentId.toLowerCase();
331
332             Either<RequirementDefinition, ResponseFormat> actionResponse = requirementBusinessLogic
333                     .deleteRequirement(componentIdLower, requirementId, modifier, true);
334             if (actionResponse.isRight()) {
335                 LOGGER.error("failed to delete requirements");
336                 return buildErrorResponse(actionResponse.right().value());
337             }
338             Object result = RepresentationUtils.toRepresentation(actionResponse.left().value());
339             return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), result);
340         } catch (Exception e) {
341             BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Delete requirements");
342             LOGGER.error("Delete requirements failed with an error", e);
343             return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
344         }
345     }
346
347     private Either<List<RequirementDefinition>, ResponseFormat> getMappedRequirementData(String inputJson, User user,
348                                                                  ComponentTypeEnum componentTypeEnum){
349         Either<UiComponentDataTransfer, ResponseFormat> mappedData = getComponentsUtils()
350                 .convertJsonToObjectUsingObjectMapper(inputJson, user, UiComponentDataTransfer.class,
351                         AuditingActionEnum.CREATE_RESOURCE, componentTypeEnum);
352         Optional<List<RequirementDefinition>> requirementDefinitionList = mappedData.left().value()
353                 .getRequirements().values().stream().findFirst();
354         return requirementDefinitionList.<Either<List<RequirementDefinition>, ResponseFormat>>
355                 map(Either::left).orElseGet(() -> Either.right(getComponentsUtils()
356                 .getResponseFormat(ActionStatus.GENERAL_ERROR)));
357     }
358 }