Catalog alignment
[sdc.git] / catalog-be / src / main / java / org / openecomp / sdc / be / servlets / ServiceFilterServlet.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * SDC
4  * ================================================================================
5  * Copyright (C) 2019 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 fj.data.Either;
24 import io.swagger.v3.oas.annotations.OpenAPIDefinition;
25 import io.swagger.v3.oas.annotations.Operation;
26 import io.swagger.v3.oas.annotations.Parameter;
27 import io.swagger.v3.oas.annotations.info.Info;
28 import io.swagger.v3.oas.annotations.media.ArraySchema;
29 import io.swagger.v3.oas.annotations.media.Content;
30 import io.swagger.v3.oas.annotations.media.Schema;
31 import io.swagger.v3.oas.annotations.responses.ApiResponse;
32 import io.swagger.v3.oas.annotations.responses.ApiResponses;
33 import org.codehaus.jackson.map.ObjectMapper;
34 import org.openecomp.sdc.be.components.impl.ComponentInstanceBusinessLogic;
35 import org.openecomp.sdc.be.components.impl.ResourceImportManager;
36 import org.openecomp.sdc.be.components.impl.ServiceBusinessLogic;
37 import org.openecomp.sdc.be.components.impl.aaf.AafPermission;
38 import org.openecomp.sdc.be.components.impl.aaf.PermissionAllowed;
39 import org.openecomp.sdc.be.components.impl.utils.NodeFilterConstraintAction;
40 import org.openecomp.sdc.be.config.BeEcompErrorManager;
41 import org.openecomp.sdc.be.dao.api.ActionStatus;
42 import org.openecomp.sdc.be.datamodel.utils.ConstraintConvertor;
43 import org.openecomp.sdc.be.datatypes.elements.CINodeFilterDataDefinition;
44 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
45 import org.openecomp.sdc.be.impl.ComponentsUtils;
46 import org.openecomp.sdc.be.impl.ServletUtils;
47 import org.openecomp.sdc.be.model.User;
48 import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum;
49 import org.openecomp.sdc.be.tosca.utils.NodeFilterConverter;
50 import org.openecomp.sdc.be.ui.model.UIConstraint;
51 import org.openecomp.sdc.be.ui.model.UINodeFilter;
52 import org.openecomp.sdc.be.user.UserBusinessLogic;
53 import org.openecomp.sdc.common.api.Constants;
54 import org.openecomp.sdc.exception.ResponseFormat;
55 import org.slf4j.Logger;
56 import org.slf4j.LoggerFactory;
57
58 import javax.inject.Inject;
59 import javax.inject.Singleton;
60 import javax.servlet.ServletContext;
61 import javax.servlet.http.HttpServletRequest;
62 import javax.servlet.http.HttpSession;
63 import javax.ws.rs.Consumes;
64 import javax.ws.rs.DELETE;
65 import javax.ws.rs.HeaderParam;
66 import javax.ws.rs.POST;
67 import javax.ws.rs.PUT;
68 import javax.ws.rs.Path;
69 import javax.ws.rs.PathParam;
70 import javax.ws.rs.Produces;
71 import javax.ws.rs.core.Context;
72 import javax.ws.rs.core.MediaType;
73 import javax.ws.rs.core.Response;
74 import java.util.List;
75 import java.util.Map;
76 import java.util.stream.Collectors;
77
78 @Path("/v1/catalog/services/{serviceId}/resourceInstances/{resourceInstanceId}/nodeFilter")
79 @Consumes(MediaType.APPLICATION_JSON)
80 @Produces(MediaType.APPLICATION_JSON)
81 @OpenAPIDefinition(info = @Info(title = "Service Filter", description = "Service Filter Servlet"))
82 @Singleton
83 public class ServiceFilterServlet extends AbstractValidationsServlet {
84
85     private static final Logger log = LoggerFactory.getLogger(ServiceFilterServlet.class);
86     private static final String START_HANDLE_REQUEST_OF = "Start handle request of {}";
87     private static final String MODIFIER_ID_IS = "modifier id is {}";
88     private static final String FAILED_TO_UPDATE_OR_CREATE_NODE_FILTER = "failed to update or create node filter";
89     private static final String FAILED_TO_PARSE_SERVICE = "failed to parse service";
90     private static final String NODE_FILTER_CREATION_OR_UPDATE = "Node Filter Creation or update";
91     private static final String CREATE_OR_UPDATE_NODE_FILTER_WITH_AN_ERROR =
92             "create or update node filter with an error";
93     private final ServiceBusinessLogic serviceBusinessLogic;
94
95     @Inject
96     public ServiceFilterServlet(UserBusinessLogic userBusinessLogic,
97         ComponentInstanceBusinessLogic componentInstanceBL,
98         ComponentsUtils componentsUtils, ServletUtils servletUtils,
99         ResourceImportManager resourceImportManager,
100         ServiceBusinessLogic serviceBusinessLogic) {
101         super(userBusinessLogic, componentInstanceBL, componentsUtils, servletUtils, resourceImportManager);
102         this.serviceBusinessLogic = serviceBusinessLogic;
103     }
104
105     @POST
106     @Consumes(MediaType.APPLICATION_JSON)
107     @Produces(MediaType.APPLICATION_JSON)
108     @Path("/")
109     @Operation(description = "Add Service Filter Constraint", method = "POST", summary = "Add Service Filter Constraint",
110             responses = @ApiResponse(
111                     content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))))
112     @ApiResponses(value = {@ApiResponse(responseCode = "201", description = "Create Service Filter"),
113             @ApiResponse(responseCode = "403", description = "Restricted operation"),
114             @ApiResponse(responseCode = "400", description = "Invalid content / Missing content")})
115     @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
116     public Response addServiceFilterConstraint(@Parameter(description = "Service data", required = true) String data,
117             @Parameter(description = "Service Id") @PathParam("serviceId") String serviceId,
118             @Parameter(description = "Resource Instance Id") @PathParam("resourceInstanceId") String ciId,
119             @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
120
121         String url = request.getMethod() + " " + request.getRequestURI();
122         log.debug(START_HANDLE_REQUEST_OF, url);
123         final HttpSession session = request.getSession();
124         ServletContext context = session.getServletContext();
125         User modifier = new User();
126         modifier.setUserId(userId);
127         log.debug(MODIFIER_ID_IS, userId);
128
129         Response response;
130
131         try {
132             String serviceIdLower = serviceId.toLowerCase();
133
134             Either<UIConstraint, ResponseFormat> convertResponse = parseToConstraint(data, modifier);
135             if (convertResponse.isRight()) {
136                 log.debug(FAILED_TO_PARSE_SERVICE);
137                 response = buildErrorResponse(convertResponse.right().value());
138                 return response;
139             }
140             UIConstraint uiConstraint = convertResponse.left().value();
141             if (uiConstraint == null) {
142                 log.debug(FAILED_TO_PARSE_SERVICE);
143                 response = buildErrorResponse(convertResponse.right().value());
144                 return response;
145             }
146             Either<CINodeFilterDataDefinition, ResponseFormat> actionResponse;
147             String constraint = new ConstraintConvertor().convert(uiConstraint);
148             actionResponse = serviceBusinessLogic
149                                      .addOrDeleteServiceFilter(serviceIdLower, ciId, NodeFilterConstraintAction.ADD, uiConstraint.getServicePropertyName(),
150                                              constraint, -1, modifier, true);
151
152             if (actionResponse.isRight()) {
153                 log.debug(FAILED_TO_UPDATE_OR_CREATE_NODE_FILTER);
154                 response = buildErrorResponse(actionResponse.right().value());
155                 return response;
156             }
157
158             CINodeFilterDataDefinition value = actionResponse.left().value();
159             UINodeFilter nodeFilter = new NodeFilterConverter().convertToUi(value);
160             return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), nodeFilter);
161
162         } catch (Exception e) {
163             BeEcompErrorManager.getInstance().logBeRestApiGeneralError(NODE_FILTER_CREATION_OR_UPDATE);
164             log.debug(CREATE_OR_UPDATE_NODE_FILTER_WITH_AN_ERROR, e);
165             response = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
166             return response;
167
168         }
169     }
170
171     @PUT
172     @Consumes(MediaType.APPLICATION_JSON)
173     @Produces(MediaType.APPLICATION_JSON)
174     @Path("/")
175     @Operation(description = "Update Service Filter Constraint", method = "PUT",
176             summary = "Update Service Filter Constraint", responses = @ApiResponse(
177                     content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))))
178     @ApiResponses(value = {@ApiResponse(responseCode = "201", description = "Create Service Filter"),
179             @ApiResponse(responseCode = "403", description = "Restricted operation"),
180             @ApiResponse(responseCode = "400", description = "Invalid content / Missing content")})
181     @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
182     public Response updateServiceFilterConstraint(@Parameter(description = "Service data", required = true) String data,
183             @Parameter(description = "Service Id") @PathParam("serviceId") String serviceId,
184             @Parameter(description = "Resource Instance Id") @PathParam("resourceInstanceId") String ciId,
185             @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
186         ServletContext context = request.getSession().getServletContext();
187         String url = request.getMethod() + " " + request.getRequestURI();
188         log.debug(START_HANDLE_REQUEST_OF, url);
189
190         User modifier = new User();
191         modifier.setUserId(userId);
192         log.debug(MODIFIER_ID_IS, userId);
193
194         Response response;
195
196         try {
197             String serviceIdLower = serviceId.toLowerCase();
198
199             Either<List, ResponseFormat> convertResponse = parseToConstraints(data, modifier);
200             if (convertResponse.isRight()) {
201                 log.debug(FAILED_TO_PARSE_SERVICE);
202                 response = buildErrorResponse(convertResponse.right().value());
203                 return response;
204             }
205             List<Map<String,String>> uiConstraintsMaps = (List<Map<String,String>>) convertResponse.left().value();
206             if (uiConstraintsMaps == null) {
207                 log.debug("failed to parse data");
208                 response = buildErrorResponse(convertResponse.right().value());
209                 return response;
210             }
211             final ObjectMapper objectMapper = new ObjectMapper();
212             List<UIConstraint> uiConstraints = uiConstraintsMaps.stream().map(dataMap -> objectMapper.convertValue(dataMap, UIConstraint.class)).collect(
213                     Collectors.toList());
214             if (uiConstraints == null) {
215                 log.debug("failed to parse data");
216                 response = buildErrorResponse(convertResponse.right().value());
217                 return response;
218             }
219             Either<CINodeFilterDataDefinition, ResponseFormat> actionResponse;
220             List<String> constraints = new ConstraintConvertor().convertToList(uiConstraints);
221             actionResponse = serviceBusinessLogic.updateServiceFilter(serviceIdLower, ciId, constraints, modifier, true);
222
223             if (actionResponse.isRight()) {
224                 log.debug(FAILED_TO_UPDATE_OR_CREATE_NODE_FILTER);
225                 response = buildErrorResponse(actionResponse.right().value());
226                 return response;
227             }
228
229             CINodeFilterDataDefinition value = actionResponse.left().value();
230             return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK),
231                     new NodeFilterConverter().convertToUi(value));
232
233         } catch (Exception e) {
234             BeEcompErrorManager.getInstance().logBeRestApiGeneralError(NODE_FILTER_CREATION_OR_UPDATE);
235             log.debug(CREATE_OR_UPDATE_NODE_FILTER_WITH_AN_ERROR, e);
236             response = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
237             return response;
238
239         }
240     }
241
242     @DELETE
243     @Consumes(MediaType.APPLICATION_JSON)
244     @Produces(MediaType.APPLICATION_JSON)
245     @Path("/{constraintIndex}")
246     @Operation(description = "Delete Service Filter Constraint", method = "Delete",
247             summary = "Delete Service Filter Constraint", responses = @ApiResponse(
248                     content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))))
249     @ApiResponses(value = {@ApiResponse(responseCode = "201", description = "Delete Service Filter Constraint"),
250             @ApiResponse(responseCode = "403", description = "Restricted operation"),
251             @ApiResponse(responseCode = "400", description = "Invalid content / Missing content")})
252     @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
253     public Response deleteServiceFilterConstraint(
254             @Parameter(description = "Service Id") @PathParam("serviceId") String serviceId,
255             @Parameter(description = "Resource Instance Id") @PathParam("resourceInstanceId") String ciId,
256             @Parameter(description = "Constraint Index") @PathParam("constraintIndex") int index,
257             @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
258         String url = request.getMethod() + " " + request.getRequestURI();
259         log.debug(START_HANDLE_REQUEST_OF, url);
260
261         User modifier = new User();
262         modifier.setUserId(userId);
263         log.debug(MODIFIER_ID_IS, userId);
264
265         Response response;
266
267         try {
268             String serviceIdLower = serviceId.toLowerCase();
269
270             Either<CINodeFilterDataDefinition, ResponseFormat> actionResponse;
271             actionResponse = serviceBusinessLogic
272                                      .addOrDeleteServiceFilter(serviceIdLower, ciId, NodeFilterConstraintAction.DELETE,
273                                              null, null,  index, modifier, true);
274
275             if (actionResponse.isRight()) {
276
277                 log.debug(FAILED_TO_UPDATE_OR_CREATE_NODE_FILTER);
278                 response = buildErrorResponse(actionResponse.right().value());
279                 return response;
280             }
281
282             final CINodeFilterDataDefinition value = actionResponse.left().value();
283             return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK),
284                     new NodeFilterConverter().convertToUi(value));
285
286         } catch (Exception e) {
287             BeEcompErrorManager.getInstance().logBeRestApiGeneralError(NODE_FILTER_CREATION_OR_UPDATE);
288             log.debug(CREATE_OR_UPDATE_NODE_FILTER_WITH_AN_ERROR, e);
289             response = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
290             return response;
291
292         }
293     }
294
295     private Either<UIConstraint, ResponseFormat> parseToConstraint(String serviceJson, User user) {
296         return getComponentsUtils().convertJsonToObjectUsingObjectMapper(serviceJson, user, UIConstraint.class,
297                 AuditingActionEnum.CREATE_RESOURCE, ComponentTypeEnum.SERVICE);
298     }
299
300     private Either<List, ResponseFormat> parseToConstraints(String serviceJson, User user) {
301         return getComponentsUtils().convertJsonToObjectUsingObjectMapper(serviceJson, user, List.class,
302                 AuditingActionEnum.CREATE_RESOURCE, ComponentTypeEnum.SERVICE);
303     }
304 }