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