Sync Integ to Master
[sdc.git] / catalog-be / src / main / java / org / openecomp / sdc / be / servlets / PolicyServlet.java
1 package org.openecomp.sdc.be.servlets;
2
3 import com.jcabi.aspects.Loggable;
4 import io.swagger.annotations.Api;
5 import io.swagger.annotations.ApiOperation;
6 import io.swagger.annotations.ApiParam;
7 import io.swagger.annotations.ApiResponse;
8 import io.swagger.annotations.ApiResponses;
9 import org.apache.commons.lang3.StringUtils;
10 import org.openecomp.sdc.be.components.impl.PolicyBusinessLogic;
11 import org.openecomp.sdc.be.components.impl.ResourceImportManager;
12 import org.openecomp.sdc.be.config.BeEcompErrorManager;
13 import org.openecomp.sdc.be.dao.api.ActionStatus;
14 import org.openecomp.sdc.be.datatypes.elements.PolicyTargetType;
15 import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
16 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
17 import org.openecomp.sdc.be.impl.ComponentsUtils;
18 import org.openecomp.sdc.be.impl.ServletUtils;
19 import org.openecomp.sdc.be.model.PolicyDefinition;
20 import org.openecomp.sdc.common.api.Constants;
21 import org.openecomp.sdc.common.datastructure.Wrapper;
22 import org.slf4j.Logger;
23 import org.slf4j.LoggerFactory;
24 import org.springframework.stereotype.Controller;
25
26 import javax.servlet.http.HttpServletRequest;
27 import javax.ws.rs.*;
28 import javax.ws.rs.core.Context;
29 import javax.ws.rs.core.MediaType;
30 import javax.ws.rs.core.Response;
31
32
33 import org.openecomp.sdc.be.model.PolicyTargetDTO;
34
35 import java.util.HashMap;
36 import java.util.List;
37 import java.util.Map;
38 import java.util.stream.Collectors;
39
40 /**
41  * Provides REST API to create, retrieve, update, delete a policy
42  */
43 @Loggable(prepend = true, value = Loggable.DEBUG, trim = false)
44 @Path("/v1/catalog")
45 @Api(value = "Policy Servlet")
46 @Controller
47 @Consumes(MediaType.APPLICATION_JSON)
48 @Produces(MediaType.APPLICATION_JSON)
49 public class PolicyServlet extends AbstractValidationsServlet {
50
51     private static final Logger log = LoggerFactory.getLogger(PolicyServlet.class);
52     private final PolicyBusinessLogic policyBusinessLogic;
53
54     public PolicyServlet(PolicyBusinessLogic policyBusinessLogic, ServletUtils servletUtils, ResourceImportManager resourceImportManager, ComponentsUtils componentsUtils) {
55         this.policyBusinessLogic = policyBusinessLogic;
56         this.servletUtils = servletUtils;
57         this.resourceImportManager = resourceImportManager;
58         this.componentsUtils = componentsUtils;
59     }
60
61     @POST
62     @Path("/{containerComponentType}/{componentId}/policies/{policyTypeName}")
63     @ApiOperation(value = "Create Policy", httpMethod = "POST", notes = "Returns created Policy", response = Response.class)
64     @ApiResponses(value = {@ApiResponse(code = 201, message = "Policy created"), @ApiResponse(code = 403, message = "Restricted operation"), @ApiResponse(code = 400, message = "Invalid content / Missing content"),
65             @ApiResponse(code = 409, message = "Policy already exist"),  @ApiResponse(code = 404, message = "Component not found")})
66     public Response createPolicy(@PathParam("componentId") final String containerComponentId,
67                                  @ApiParam(value = "valid values: resources / services", allowableValues = ComponentTypeEnum.RESOURCE_PARAM_NAME + "," + ComponentTypeEnum.SERVICE_PARAM_NAME) @PathParam("containerComponentType") final String containerComponentType,
68                                  @PathParam("policyTypeName") final String policyTypeName,
69                                  @HeaderParam(value = Constants.USER_ID_HEADER) @ApiParam(value = "USER_ID of modifier user", required = true) String userId,
70                                  @Context final HttpServletRequest request) {
71         init(log);
72
73         Wrapper<Response> responseWrapper = new Wrapper<>();
74         try {
75             Wrapper<ComponentTypeEnum> componentTypeWrapper = validateComponentTypeAndUserId(containerComponentType, userId, responseWrapper);
76             if (responseWrapper.isEmpty()) {
77                 responseWrapper.setInnerElement(policyBusinessLogic.createPolicy(componentTypeWrapper.getInnerElement(), containerComponentId, policyTypeName, userId, true)
78                         .either(l -> buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.CREATED), l),
79                                 this::buildErrorResponse));
80             }
81         } catch (Exception e) {
82             BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Create Policy");
83             log.error("Failed to create policy. The exception {} occurred. ", e);
84             responseWrapper.setInnerElement(buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR)));
85         }
86         return responseWrapper.getInnerElement();
87     }
88
89     @PUT
90     @Path("/{containerComponentType}/{componentId}/policies/{policyId}")
91     @ApiOperation(value = "Update Policy metadata", httpMethod = "PUT", notes = "Returns updated Policy", response = Response.class)
92     @ApiResponses(value = {@ApiResponse(code = 200, message = "Policy updated"), @ApiResponse(code = 403, message = "Restricted operation"), @ApiResponse(code = 400, message = "Invalid content / Missing content"),
93             @ApiResponse(code = 404, message = "component / policy Not found")})
94     public Response updatePolicy(@PathParam("componentId") final String containerComponentId,
95                                  @ApiParam(value = "valid values: resources / services", allowableValues = ComponentTypeEnum.RESOURCE_PARAM_NAME + "," + ComponentTypeEnum.SERVICE_PARAM_NAME) @PathParam("containerComponentType") final String containerComponentType,
96                                  @PathParam("policyId") final String policyId, @HeaderParam(value = Constants.USER_ID_HEADER) @ApiParam(value = "USER_ID of modifier user", required = true) String userId,
97                                  @ApiParam(value = "PolicyDefinition", required = true) String policyData, @Context final HttpServletRequest request) {
98         init(log);
99
100         Wrapper<Response> responseWrapper = new Wrapper<>();
101         try {
102             Wrapper<ComponentTypeEnum> componentTypeWrapper = validateComponentTypeAndUserId(containerComponentType, userId, responseWrapper);
103             Wrapper<PolicyDefinition> policyWrapper = new Wrapper<>();
104             if (responseWrapper.isEmpty()) {
105                 convertJsonToObjectOfClass(policyData, policyWrapper, PolicyDefinition.class, responseWrapper);
106                 if (policyWrapper.isEmpty()) {
107                     responseWrapper.setInnerElement(buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT)));
108                 }
109             }
110             if (!policyWrapper.isEmpty()) {
111                 policyWrapper.getInnerElement().setUniqueId(policyId);
112                 responseWrapper.setInnerElement(policyBusinessLogic.updatePolicy(componentTypeWrapper.getInnerElement(), containerComponentId, policyWrapper.getInnerElement(), userId, true)
113                         .either(this::buildOkResponse,
114                                 this::buildErrorResponse));
115             }
116
117         } catch (Exception e) {
118             BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Update Policy");
119             log.error("Failed to update policy. The exception {} occurred. ", e);
120             responseWrapper.setInnerElement(buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR)));
121         }
122         return responseWrapper.getInnerElement();
123     }
124
125     @GET
126     @Path("/{containerComponentType}/{componentId}/policies/{policyId}")
127     @ApiOperation(value = "Get Policy", httpMethod = "GET", notes = "Returns Policy", response = Response.class)
128     @ApiResponses(value = {@ApiResponse(code = 200, message = "Policy was found"), @ApiResponse(code = 403, message = "Restricted operation"), @ApiResponse(code = 400, message = "Invalid content / Missing content"),
129             @ApiResponse(code = 404, message = "component / policy Not found")})
130     public Response getPolicy(@PathParam("componentId") final String containerComponentId,
131                               @ApiParam(value = "valid values: resources / services", allowableValues = ComponentTypeEnum.RESOURCE_PARAM_NAME + "," + ComponentTypeEnum.SERVICE_PARAM_NAME) @PathParam("containerComponentType") final String containerComponentType,
132                               @PathParam("policyId") final String policyId, @HeaderParam(value = Constants.USER_ID_HEADER) @ApiParam(value = "USER_ID of modifier user", required = true) String userId,
133                               @Context final HttpServletRequest request) {
134         init(log);
135
136         Wrapper<Response> responseWrapper = new Wrapper<>();
137         try {
138             Wrapper<ComponentTypeEnum> componentTypeWrapper = validateComponentTypeAndUserId(containerComponentType, userId, responseWrapper);
139             if (responseWrapper.isEmpty()) {
140                 responseWrapper.setInnerElement(policyBusinessLogic.getPolicy(componentTypeWrapper.getInnerElement(), containerComponentId, policyId, userId)
141                         .either(this::buildOkResponse,
142                                 this::buildErrorResponse));
143             }
144
145         } catch (Exception e) {
146             BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Get Policy");
147             log.error("Failed to retrieve policy. The exception {} occurred. ", e);
148             responseWrapper.setInnerElement(buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR)));
149         }
150         return responseWrapper.getInnerElement();
151     }
152
153     @DELETE
154     @Path("/{containerComponentType}/{componentId}/policies/{policyId}")
155     @ApiOperation(value = "Delete Policy", httpMethod = "DELETE", notes = "No body", response = Response.class)
156     @ApiResponses(value = {@ApiResponse(code = 204, message = "Policy was deleted"), @ApiResponse(code = 403, message = "Restricted operation"), @ApiResponse(code = 400, message = "Invalid content / Missing content"),
157             @ApiResponse(code = 404, message = "component / policy Not found")})
158     public Response deletePolicy(@PathParam("componentId") final String containerComponentId,
159                                  @ApiParam(value = "valid values: resources / services", allowableValues = ComponentTypeEnum.RESOURCE_PARAM_NAME + "," + ComponentTypeEnum.SERVICE_PARAM_NAME) @PathParam("containerComponentType") final String containerComponentType,
160                                  @PathParam("policyId") final String policyId, @HeaderParam(value = Constants.USER_ID_HEADER) @ApiParam(value = "USER_ID of modifier user", required = true) String userId,
161                                  @Context final HttpServletRequest request) {
162         init(log);
163
164         Wrapper<Response> responseWrapper = new Wrapper<>();
165         try {
166             Wrapper<ComponentTypeEnum> componentTypeWrapper = validateComponentTypeAndUserId(containerComponentType, userId, responseWrapper);
167             if (responseWrapper.isEmpty()) {
168                 responseWrapper.setInnerElement(policyBusinessLogic.deletePolicy(componentTypeWrapper.getInnerElement(), containerComponentId, policyId, userId, true)
169                         .either(l -> buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.NO_CONTENT), null),
170                                 this::buildErrorResponse));
171             }
172
173         } catch (Exception e) {
174             BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Delete Policy");
175             log.error("Failed to delete policy. The exception {} occurred. ", e);
176             responseWrapper.setInnerElement(buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR)));
177         }
178         return responseWrapper.getInnerElement();
179     }
180
181     @GET
182     @Path("/{containerComponentType}/{componentId}/policies/{policyId}/properties")
183     @ApiOperation(value = "Get component policy properties", httpMethod = "GET", notes = "Returns component policy properties", response = PropertyDataDefinition.class, responseContainer="List")
184     @ApiResponses(value = {@ApiResponse(code = 200, message = "Properties found"),@ApiResponse(code = 400, message = "invalid content - Error: containerComponentType is invalid"), @ApiResponse(code = 403, message = "Restricted operation"), @ApiResponse(code = 404, message = "Componentorpolicy  not found"),
185     @ApiResponse(code = 500, message = "The GET request failed due to internal SDC problem.") })public Response getPolicyProperties(@ApiParam(value = "the id of the component which is the container of the policy") @PathParam("componentId") final String containerComponentId,
186                                         @ApiParam(value = "valid values: resources / services", allowableValues = ComponentTypeEnum.RESOURCE_PARAM_NAME + "," + ComponentTypeEnum.SERVICE_PARAM_NAME) @PathParam("containerComponentType") final String containerComponentType,
187                                         @ApiParam(value = "the id of the policy which its properties are to return") @PathParam("policyId") final String policyId,
188                                         @ApiParam(value = "the userid", required = true)@HeaderParam(value = Constants.USER_ID_HEADER) String userId,
189                                         @Context final HttpServletRequest request) {
190         init(log);
191         try {
192             return convertToComponentType(containerComponentType)
193                     .left()
194                     .bind(cmptType -> policyBusinessLogic.getPolicyProperties(cmptType, containerComponentId, policyId, userId))
195                     .either(this::buildOkResponse,
196                             this::buildErrorResponse);
197         } catch (Exception e) {
198             BeEcompErrorManager.getInstance().logBeRestApiGeneralError("get Policy properties");
199             log.debug("#getPolicyProperties - get Policy properties has failed.", e);
200             return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
201         }
202
203
204     }
205
206     @PUT
207     @Path("/{containerComponentType}/{componentId}/policies/{policyId}/properties")
208     @ApiOperation(value = "Update Policy properties", httpMethod = "PUT", notes = "Returns updated Policy", response = Response.class)
209     @ApiResponses(value = {@ApiResponse(code = 200, message = "Policy properties updated"), @ApiResponse(code = 403, message = "Restricted operation"), @ApiResponse(code = 400, message = "Invalid content / Missing content"),
210             @ApiResponse(code = 404, message = "component / policy Not found")})
211     public Response updatePolicyProperties(@PathParam("componentId") final String containerComponentId,
212                                            @ApiParam(value = "valid values: resources / services", allowableValues = ComponentTypeEnum.RESOURCE_PARAM_NAME + "," + ComponentTypeEnum.SERVICE_PARAM_NAME) @PathParam("containerComponentType") final String containerComponentType,
213                                            @PathParam("policyId") final String policyId, @HeaderParam(value = Constants.USER_ID_HEADER) @ApiParam(value = "USER_ID of modifier user", required = true) String userId,
214                                            @ApiParam(value = "PolicyDefinition", required = true) String policyData, @Context final HttpServletRequest request) {
215         init(log);
216         Wrapper<Response> responseWrapper = new Wrapper<>();
217         try {
218             Wrapper<ComponentTypeEnum> componentTypeWrapper = validateComponentTypeAndUserId(containerComponentType, userId, responseWrapper);
219             Wrapper<PropertyDataDefinition[]> propertiesWrapper = new Wrapper<>();
220             if (responseWrapper.isEmpty()) {
221                 convertJsonToObjectOfClass(policyData, propertiesWrapper, PropertyDataDefinition[].class, responseWrapper);
222                 if (propertiesWrapper.isEmpty()) {
223                     responseWrapper.setInnerElement(buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT)));
224                 }
225             }
226             if (!propertiesWrapper.isEmpty()) {
227                 responseWrapper.setInnerElement(
228                         policyBusinessLogic.updatePolicyProperties(componentTypeWrapper.getInnerElement(), containerComponentId, policyId, propertiesWrapper.getInnerElement(), userId, true)
229                                 .either(this::buildOkResponse, this::buildErrorResponse));
230             }
231         } catch (Exception e) {
232             BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Update Policy");
233             log.error("Failed to update policy. The exception {} occurred. ", e);
234             responseWrapper.setInnerElement(buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR)));
235         }
236         return responseWrapper.getInnerElement();
237     }
238
239     private Wrapper<ComponentTypeEnum> validateComponentTypeAndUserId(final String containerComponentType, String userId, Wrapper<Response> responseWrapper) {
240         Wrapper<ComponentTypeEnum> componentTypeWrapper = new Wrapper<>();
241         if (StringUtils.isEmpty(userId)) {
242             log.error("Missing userId HTTP header. ");
243             responseWrapper.setInnerElement(buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.MISSING_USER_ID)));
244         }
245         if (responseWrapper.isEmpty()) {
246             validateComponentType(responseWrapper, componentTypeWrapper, containerComponentType);
247         }
248         return componentTypeWrapper;
249     }
250
251         @PUT
252         @Path("/{containerComponentType}/{componentId}/policies/{policyId}/targets")
253         @Consumes(MediaType.APPLICATION_JSON)
254         @Produces(MediaType.APPLICATION_JSON)
255         @ApiOperation(value = "update policy targets", httpMethod = "PUT", notes = "Returns updated Policy", response = Response.class)
256         @ApiResponses(value = {@ApiResponse(code = 201, message = "Policy target updated"), @ApiResponse(code = 403, message = "Restricted operation"), @ApiResponse(code = 400, message = "Invalid content / Missing content")})
257         public Response updatePolicyTargets(@PathParam("componentId") final String containerComponentId,
258                                                                                 @ApiParam(value = "valid values: resources / services", allowableValues = ComponentTypeEnum.RESOURCE_PARAM_NAME + "," + ComponentTypeEnum.SERVICE_PARAM_NAME) @PathParam("containerComponentType") final String containerComponentType,
259                                                                                 @PathParam("policyId") final String policyId,
260                                                                                 @HeaderParam(value = Constants.USER_ID_HEADER) @ApiParam(value = "USER_ID of modifier user", required = true) String userId,
261                                                                                 @Context final HttpServletRequest request,
262                                                                                 List<PolicyTargetDTO> requestJson) {
263                 try {
264
265             Map<PolicyTargetType, List<String>> policyTarget = convertTargetDTOToBLTarget(requestJson);
266             if(policyTarget == null){
267                 return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.POLICY_TARGET_TYPE_DOES_NOT_EXIST, StringUtils.join(requestJson.stream().map(PolicyTargetDTO::getType).collect(Collectors.toList())), ","));
268             }
269
270             return convertToComponentType(containerComponentType)
271                     .left()
272                     .bind(cmptType -> policyBusinessLogic.updatePolicyTargets(cmptType, containerComponentId, policyId, policyTarget, userId))
273                     .either(this::buildOkResponse,
274                             this::buildErrorResponse);
275
276         } catch (Exception e) {
277             BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Create Policy");
278             log.debug("Policy creation has been failed with the exception{}. ", e);
279             return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
280         }
281     }
282
283
284     private Map<PolicyTargetType, List<String>> convertTargetDTOToBLTarget(List<PolicyTargetDTO> targetDTOList) {
285         Map<PolicyTargetType, List<String>> policyTarget = new HashMap<>();
286         for (PolicyTargetDTO currentTarget : targetDTOList) {
287             if(!addTargetsByType(policyTarget, currentTarget.getType(), currentTarget.getUniqueIds())){
288                 return null;
289             }
290         }
291         return policyTarget;
292     }
293     public boolean addTargetsByType(Map<PolicyTargetType, List<String>> policyTarget, String type, List<String> uniqueIds) {
294         PolicyTargetType targetTypeEnum = PolicyTargetType.getByNameIgnoreCase(type);
295         if(targetTypeEnum != null){
296             policyTarget.put(targetTypeEnum, validateUniquenessOfIds(uniqueIds));
297             return true;
298         }
299         else{
300             return false;
301         }
302     }
303
304     private List<String> validateUniquenessOfIds(List<String> uniqueIds) {
305         return uniqueIds.stream().distinct().collect(Collectors.toList());
306     }
307 }