b451b33fb915e0b6c384b1ac22b7ccaad30703b4
[sdc.git] / catalog-be / src / main / java / org / openecomp / sdc / be / servlets / ComponentSubstitutionFilterServlet.java
1 /*
2  * ============LICENSE_START=======================================================
3  *  Copyright (C) 2020 Nordix Foundation
4  *  ================================================================================
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at
8  *
9  *        http://www.apache.org/licenses/LICENSE-2.0
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  *  SPDX-License-Identifier: Apache-2.0
17  *  ============LICENSE_END=========================================================
18  */
19
20 package org.openecomp.sdc.be.servlets;
21
22 import io.swagger.v3.oas.annotations.Operation;
23 import io.swagger.v3.oas.annotations.Parameter;
24 import io.swagger.v3.oas.annotations.media.ArraySchema;
25 import io.swagger.v3.oas.annotations.media.Content;
26 import io.swagger.v3.oas.annotations.media.Schema;
27 import io.swagger.v3.oas.annotations.responses.ApiResponse;
28 import java.util.List;
29 import java.util.Optional;
30 import javax.inject.Inject;
31 import javax.inject.Singleton;
32 import javax.servlet.http.HttpServletRequest;
33 import javax.ws.rs.Consumes;
34 import javax.ws.rs.DELETE;
35 import javax.ws.rs.HeaderParam;
36 import javax.ws.rs.POST;
37 import javax.ws.rs.PUT;
38 import javax.ws.rs.Path;
39 import javax.ws.rs.PathParam;
40 import javax.ws.rs.Produces;
41 import javax.ws.rs.core.Context;
42 import javax.ws.rs.core.MediaType;
43 import javax.ws.rs.core.Response;
44 import org.apache.commons.collections.CollectionUtils;
45 import org.openecomp.sdc.be.components.impl.ComponentInstanceBusinessLogic;
46 import org.openecomp.sdc.be.components.impl.ComponentSubstitutionFilterBusinessLogic;
47 import org.openecomp.sdc.be.components.impl.ResourceImportManager;
48 import org.openecomp.sdc.be.components.impl.aaf.AafPermission;
49 import org.openecomp.sdc.be.components.impl.aaf.PermissionAllowed;
50 import org.openecomp.sdc.be.components.impl.utils.NodeFilterConstraintAction;
51 import org.openecomp.sdc.be.config.BeEcompErrorManager;
52 import org.openecomp.sdc.be.dao.api.ActionStatus;
53 import org.openecomp.sdc.be.datamodel.utils.ConstraintConvertor;
54 import org.openecomp.sdc.be.datatypes.elements.SubstitutionFilterDataDefinition;
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.User;
59 import org.openecomp.sdc.be.tosca.utils.SubstitutionFilterConverter;
60 import org.openecomp.sdc.be.ui.model.UIConstraint;
61 import org.openecomp.sdc.be.ui.model.UINodeFilter;
62 import org.openecomp.sdc.be.user.UserBusinessLogic;
63 import org.openecomp.sdc.common.api.Constants;
64 import org.slf4j.Logger;
65 import org.slf4j.LoggerFactory;
66
67 @Path("/v1/catalog/{componentType}/{componentId}/resourceInstances/{componentInstanceId}/substitutionFilter")
68 @Consumes(MediaType.APPLICATION_JSON)
69 @Produces(MediaType.APPLICATION_JSON)
70 @Singleton
71 public class ComponentSubstitutionFilterServlet extends AbstractValidationsServlet {
72
73     private static final Logger LOGGER = LoggerFactory.getLogger(ComponentSubstitutionFilterServlet.class);
74     private static final String START_HANDLE_REQUEST_OF = "Start handle {} request of {}";
75     private static final String MODIFIER_ID_IS = "Modifier id is {}";
76     private static final String FAILED_TO_PARSE_COMPONENT = "Failed to parse component";
77
78     private static final String FAILED_TO_ADD_SUBSTITUTION_FILTER = "Failed to add substitution filter";
79     private static final String ADD_SUBSTITUTION_FILTER = "Add Substitution Filter";
80     private static final String ADD_SUBSTITUTION_FILTER_WITH_AN_ERROR = "Add substitution filter with an error";
81
82     private static final String FAILED_TO_UPDATE_SUBSTITUTION_FILTER = "Failed to update substitution filter";
83     private static final String SUBSTITUTION_FILTER_UPDATE = "Substitution Filter Update";
84     private static final String UPDATE_SUBSTITUTION_FILTER_WITH_AN_ERROR = "Update substitution filter with an error {}";
85
86     private static final String FAILED_TO_DELETE_SUBSTITUTION_FILTER = "Failed to delete substitution filter";
87     private static final String SUBSTITUTION_FILTER_DELETE = "Substitution Filter Delete";
88     private static final String DELETE_SUBSTITUTION_FILTER_WITH_AN_ERROR = "Delete substitution filter with an error";
89
90     private final ComponentSubstitutionFilterBusinessLogic componentSubstitutionFilterBusinessLogic;
91
92     @Inject
93     public ComponentSubstitutionFilterServlet(final UserBusinessLogic userBusinessLogic,
94                                               final ComponentInstanceBusinessLogic componentInstanceBL,
95                                               final ComponentsUtils componentsUtils,
96                                               final ServletUtils servletUtils,
97                                               final ResourceImportManager resourceImportManager,
98                                               final ComponentSubstitutionFilterBusinessLogic componentSubstitutionFilterBusinessLogic) {
99         super(userBusinessLogic, componentInstanceBL, componentsUtils, servletUtils, resourceImportManager);
100         this.componentSubstitutionFilterBusinessLogic = componentSubstitutionFilterBusinessLogic;
101     }
102
103     @POST
104     @Consumes(MediaType.APPLICATION_JSON)
105     @Produces(MediaType.APPLICATION_JSON)
106     @Path("/")
107     @Operation(description = "Add Component Substitution Filter Constraint", method = "POST",
108         summary = "Add Component Substitution Filter Constraint", responses = {
109         @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
110         @ApiResponse(responseCode = "201", description = "Add Substitution Filter Constraint"),
111         @ApiResponse(responseCode = "403", description = "Restricted operation"),
112         @ApiResponse(responseCode = "400", description = "Invalid content / Missing content")})
113     @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
114     public Response addSubstitutionFilter(
115         @Parameter(description = "UIConstraint data", required = true) String constraintData,
116         @Parameter(description = "Component Id") @PathParam("componentId") String componentId,
117         @Parameter(description = "Component Instance Id") @PathParam("componentInstanceId") String componentInstanceId,
118         @Parameter(description = "valid value: services",
119             schema = @Schema(allowableValues = {
120                 ComponentTypeEnum.SERVICE_PARAM_NAME})) @PathParam("componentType") final String componentType,
121         @Context final HttpServletRequest request,
122         @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
123
124         LOGGER.debug(START_HANDLE_REQUEST_OF, request.getMethod(), request.getRequestURI());
125         LOGGER.debug(MODIFIER_ID_IS, userId);
126         final User userModifier = componentSubstitutionFilterBusinessLogic.validateUser(userId);
127
128         final ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(componentType);
129         try {
130             final Optional<UIConstraint> convertResponse = componentsUtils
131                 .parseToConstraint(constraintData, userModifier, componentTypeEnum);
132             if (!convertResponse.isPresent()) {
133                 LOGGER.error(FAILED_TO_PARSE_COMPONENT);
134                 return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
135             }
136
137             final Optional<SubstitutionFilterDataDefinition> substitutionFilter =
138                 componentSubstitutionFilterBusinessLogic.createSubstitutionFilterIfNotExist(componentId,
139                     componentInstanceId, true, componentTypeEnum);
140             if (!substitutionFilter.isPresent()) {
141                 LOGGER.error("Failed to create substitution filter.");
142                 BeEcompErrorManager.getInstance().logBeRestApiGeneralError(ADD_SUBSTITUTION_FILTER);
143                 return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
144             }
145
146             final UIConstraint uiConstraint = convertResponse.get();
147             final String constraint = new ConstraintConvertor().convert(uiConstraint);
148
149             final Optional<SubstitutionFilterDataDefinition> actionResponse = componentSubstitutionFilterBusinessLogic
150                 .addSubstitutionFilter(componentId.toLowerCase(), componentInstanceId, NodeFilterConstraintAction.ADD,
151                     uiConstraint.getServicePropertyName(), constraint, true, componentTypeEnum);
152
153             if (!actionResponse.isPresent()) {
154                 LOGGER.error(FAILED_TO_ADD_SUBSTITUTION_FILTER);
155                 return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
156             }
157             final UINodeFilter uiFilter = new SubstitutionFilterConverter().convertToUi(actionResponse.get());
158
159             return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), uiFilter);
160
161         } catch (final Exception e) {
162             BeEcompErrorManager.getInstance().logBeRestApiGeneralError(ADD_SUBSTITUTION_FILTER);
163             LOGGER.error(ADD_SUBSTITUTION_FILTER_WITH_AN_ERROR, e);
164             return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
165         }
166     }
167
168     @PUT
169     @Consumes(MediaType.APPLICATION_JSON)
170     @Produces(MediaType.APPLICATION_JSON)
171     @Path("/")
172     @Operation(description = "Update Component Substitution Filter Constraint", method = "PUT",
173         summary = "Update Component Substitution Filter Constraint", responses = {
174         @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
175         @ApiResponse(responseCode = "201", description = "Update Substitution Filter Constraint"),
176         @ApiResponse(responseCode = "403", description = "Restricted operation"),
177         @ApiResponse(responseCode = "400", description = "Invalid content / Missing content")})
178     @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
179     public Response updateSubstitutionFilter(
180         @Parameter(description = "UIConstraint data", required = true) String constraintData,
181         @Parameter(description = "Component Id") @PathParam("componentId") String componentId,
182         @Parameter(description = "Component Instance Id") @PathParam("componentInstanceId") String componentInstanceId,
183         @Parameter(description = "valid value: services",
184             schema = @Schema(allowableValues = {
185                 ComponentTypeEnum.SERVICE_PARAM_NAME})) @PathParam("componentType") final String componentType,
186         @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
187
188         LOGGER.debug(START_HANDLE_REQUEST_OF, request.getMethod(), request.getRequestURI());
189         LOGGER.debug(MODIFIER_ID_IS, userId);
190         final User userModifier = componentSubstitutionFilterBusinessLogic.validateUser(userId);
191
192         try {
193             final ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(componentType);
194             final List<UIConstraint>  uiConstraints = componentsUtils
195                 .validateAndParseConstraint(componentTypeEnum, constraintData, userModifier);
196             if (CollectionUtils.isEmpty(uiConstraints)) {
197                 LOGGER.error("Failed to Parse Constraint data {} when executing {} ",
198                     constraintData, SUBSTITUTION_FILTER_UPDATE);
199                 return buildErrorResponse(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR,
200                     "Failed to parse constraint data"));
201             }
202
203             final List<String> constraints = new ConstraintConvertor().convertToList(uiConstraints);
204             final Optional<SubstitutionFilterDataDefinition> actionResponse = componentSubstitutionFilterBusinessLogic
205                 .updateSubstitutionFilter(componentId.toLowerCase(), componentInstanceId, constraints,
206                     true, componentTypeEnum);
207
208             if (!actionResponse.isPresent()) {
209                 LOGGER.error(FAILED_TO_UPDATE_SUBSTITUTION_FILTER);
210                 return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
211             }
212
213             return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK),
214                 new SubstitutionFilterConverter().convertToUi(actionResponse.get()));
215
216         } catch (final Exception e) {
217             BeEcompErrorManager.getInstance().logBeRestApiGeneralError(SUBSTITUTION_FILTER_UPDATE);
218             LOGGER.error(UPDATE_SUBSTITUTION_FILTER_WITH_AN_ERROR, e.getMessage(), e);
219             return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
220         }
221     }
222
223     @DELETE
224     @Consumes(MediaType.APPLICATION_JSON)
225     @Produces(MediaType.APPLICATION_JSON)
226     @Path("/{constraintIndex}")
227     @Operation(description = "Delete Component Substitution Filter Constraint", method = "Delete",
228         summary = "Delete Component Substitution Filter Constraint", responses = {
229         @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
230         @ApiResponse(responseCode = "201", description = "Delete Substitution Filter Constraint"),
231         @ApiResponse(responseCode = "403", description = "Restricted operation"),
232         @ApiResponse(responseCode = "400", description = "Invalid content / Missing content")})
233     @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
234     public Response deleteSubstitutionFilterConstraint(
235         @Parameter(description = "Component Id") @PathParam("componentId") String componentId,
236         @Parameter(description = "Component Instance Id") @PathParam("componentInstanceId") String componentInstanceId,
237         @Parameter(description = "Constraint Index") @PathParam("constraintIndex") int index,
238         @Parameter(description = "valid value: services",
239             schema = @Schema(allowableValues = {
240                 ComponentTypeEnum.SERVICE_PARAM_NAME})) @PathParam("componentType") final String componentType,
241         @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
242
243         LOGGER.debug(START_HANDLE_REQUEST_OF, request.getMethod(), request.getRequestURI());
244         LOGGER.debug(MODIFIER_ID_IS, userId);
245         componentSubstitutionFilterBusinessLogic.validateUser(userId);
246
247         try {
248             final Optional<SubstitutionFilterDataDefinition> actionResponse = componentSubstitutionFilterBusinessLogic
249                 .deleteSubstitutionFilter(componentId.toLowerCase(), componentInstanceId,
250                     NodeFilterConstraintAction.DELETE,
251                     null, index, true, ComponentTypeEnum.findByParamName(componentType));
252
253             if (!actionResponse.isPresent()) {
254                 LOGGER.debug(FAILED_TO_DELETE_SUBSTITUTION_FILTER);
255                 return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
256             }
257
258             return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK),
259                 new SubstitutionFilterConverter().convertToUi(actionResponse.get()));
260
261         } catch (final Exception e) {
262             BeEcompErrorManager.getInstance().logBeRestApiGeneralError(SUBSTITUTION_FILTER_DELETE);
263             LOGGER.debug(DELETE_SUBSTITUTION_FILTER_WITH_AN_ERROR, e);
264             return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
265
266         }
267     }
268
269 }