2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 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
11 * http://www.apache.org/licenses/LICENSE-2.0
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=========================================================
21 package org.openecomp.sdc.be.servlets;
23 import com.jcabi.aspects.Loggable;
24 import fj.data.Either;
25 import io.swagger.annotations.Api;
26 import io.swagger.annotations.ApiOperation;
27 import io.swagger.annotations.ApiParam;
28 import io.swagger.annotations.ApiResponse;
29 import io.swagger.annotations.ApiResponses;
30 import org.apache.commons.lang3.tuple.ImmutablePair;
31 import org.glassfish.jersey.media.multipart.FormDataParam;
32 import org.openecomp.sdc.be.components.impl.CapabilityTypeImportManager;
33 import org.openecomp.sdc.be.components.impl.CategoriesImportManager;
34 import org.openecomp.sdc.be.components.impl.DataTypeImportManager;
35 import org.openecomp.sdc.be.components.impl.GroupTypeImportManager;
36 import org.openecomp.sdc.be.components.impl.InterfaceLifecycleTypeImportManager;
37 import org.openecomp.sdc.be.components.impl.PolicyTypeImportManager;
38 import org.openecomp.sdc.be.config.BeEcompErrorManager;
39 import org.openecomp.sdc.be.dao.api.ActionStatus;
40 import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
41 import org.openecomp.sdc.be.model.DataTypeDefinition;
42 import org.openecomp.sdc.be.model.GroupTypeDefinition;
43 import org.openecomp.sdc.be.model.PolicyTypeDefinition;
44 import org.openecomp.sdc.be.model.User;
45 import org.openecomp.sdc.common.api.Constants;
46 import org.openecomp.sdc.common.datastructure.FunctionalInterfaces.ConsumerTwoParam;
47 import org.openecomp.sdc.common.datastructure.Wrapper;
48 import org.openecomp.sdc.exception.ResponseFormat;
49 import org.slf4j.Logger;
50 import org.slf4j.LoggerFactory;
51 import org.springframework.stereotype.Controller;
52 import javax.servlet.http.HttpServletRequest;
53 import javax.ws.rs.Consumes;
54 import javax.ws.rs.HeaderParam;
55 import javax.ws.rs.POST;
56 import javax.ws.rs.Path;
57 import javax.ws.rs.Produces;
58 import javax.ws.rs.core.Context;
59 import javax.ws.rs.core.MediaType;
60 import javax.ws.rs.core.Response;
62 import java.io.IOException;
63 import java.util.List;
66 import java.util.function.Supplier;
67 import java.util.stream.Collectors;
69 import javax.servlet.http.HttpServletRequest;
70 import javax.ws.rs.Consumes;
71 import javax.ws.rs.HeaderParam;
72 import javax.ws.rs.POST;
73 import javax.ws.rs.Path;
74 import javax.ws.rs.Produces;
75 import javax.ws.rs.core.Context;
76 import javax.ws.rs.core.MediaType;
77 import javax.ws.rs.core.Response;
79 import java.io.IOException;
80 import java.util.List;
83 import java.util.function.Supplier;
84 import java.util.stream.Collectors;
85 @Loggable(prepend = true, value = Loggable.DEBUG, trim = false)
86 @Path("/v1/catalog/uploadType")
87 @Api(value = "Catalog Types Upload")
89 public class TypesUploadServlet extends AbstractValidationsServlet {
90 private static final Logger log = LoggerFactory.getLogger(TypesUploadServlet.class);
91 private CapabilityTypeImportManager capabilityTypeImportManager;
93 private final InterfaceLifecycleTypeImportManager interfaceLifecycleTypeImportManager;
95 private final CategoriesImportManager categoriesImportManager;
97 private final DataTypeImportManager dataTypeImportManager;
99 private final GroupTypeImportManager groupTypeImportManager;
101 private final PolicyTypeImportManager policyTypeImportManager;
103 public TypesUploadServlet(CapabilityTypeImportManager capabilityTypeImportManager, InterfaceLifecycleTypeImportManager interfaceLifecycleTypeImportManager, CategoriesImportManager categoriesImportManager, DataTypeImportManager dataTypeImportManager, GroupTypeImportManager groupTypeImportManager, PolicyTypeImportManager policyTypeImportManager) {
104 this.capabilityTypeImportManager = capabilityTypeImportManager;
105 this.interfaceLifecycleTypeImportManager = interfaceLifecycleTypeImportManager;
106 this.categoriesImportManager = categoriesImportManager;
107 this.dataTypeImportManager = dataTypeImportManager;
108 this.groupTypeImportManager = groupTypeImportManager;
109 this.policyTypeImportManager = policyTypeImportManager;
114 @Consumes(MediaType.MULTIPART_FORM_DATA)
115 @Produces(MediaType.APPLICATION_JSON)
116 @ApiOperation(value = "Create Capability Type from yaml", httpMethod = "POST", notes = "Returns created Capability Type", response = Response.class)
117 @ApiResponses(value = { @ApiResponse(code = 201, message = "Capability Type created"), @ApiResponse(code = 403, message = "Restricted operation"), @ApiResponse(code = 400, message = "Invalid content / Missing content"),
118 @ApiResponse(code = 409, message = "Capability Type already exist") })
119 public Response uploadCapabilityType(@ApiParam("FileInputStream") @FormDataParam("capabilityTypeZip") File file, @Context final HttpServletRequest request, @HeaderParam("USER_ID") String creator) {
120 ConsumerTwoParam<Wrapper<Response>, String> createElementsMethod = (responseWrapper, ymlPayload) -> createElementsType(responseWrapper, () -> capabilityTypeImportManager.createCapabilityTypes(ymlPayload));
121 return uploadElementTypeServletLogic(createElementsMethod, file, request, creator, NodeTypeEnum.CapabilityType.name());
125 @Path("/interfaceLifecycle")
126 @Consumes(MediaType.MULTIPART_FORM_DATA)
127 @Produces(MediaType.APPLICATION_JSON)
128 @ApiOperation(value = "Create Interface Lyfecycle Type from yaml", httpMethod = "POST", notes = "Returns created Interface Lifecycle Type", response = Response.class)
129 @ApiResponses(value = { @ApiResponse(code = 201, message = "Interface Lifecycle Type created"), @ApiResponse(code = 403, message = "Restricted operation"), @ApiResponse(code = 400, message = "Invalid content / Missing content"),
130 @ApiResponse(code = 409, message = "Interface Lifecycle Type already exist") })
131 public Response uploadInterfaceLifecycleType(@ApiParam("FileInputStream") @FormDataParam("interfaceLifecycleTypeZip") File file, @Context final HttpServletRequest request, @HeaderParam("USER_ID") String creator) {
132 ConsumerTwoParam<Wrapper<Response>, String> createElementsMethod = (responseWrapper, ymlPayload) -> createElementsType(responseWrapper, () -> interfaceLifecycleTypeImportManager.createLifecycleTypes(ymlPayload));
133 return uploadElementTypeServletLogic(createElementsMethod, file, request, creator, "Interface Types");
138 @Consumes(MediaType.MULTIPART_FORM_DATA)
139 @Produces(MediaType.APPLICATION_JSON)
140 @ApiOperation(value = "Create Categories from yaml", httpMethod = "POST", notes = "Returns created categories", response = Response.class)
141 @ApiResponses(value = { @ApiResponse(code = 201, message = "Categories created"), @ApiResponse(code = 403, message = "Restricted operation"), @ApiResponse(code = 400, message = "Invalid content / Missing content"),
142 @ApiResponse(code = 409, message = "Category already exist") })
143 public Response uploadCategories(@ApiParam("FileInputStream") @FormDataParam("categoriesZip") File file, @Context final HttpServletRequest request, @HeaderParam("USER_ID") String creator) {
144 ConsumerTwoParam<Wrapper<Response>, String> createElementsMethod = (responseWrapper, ymlPayload) -> createElementsType(responseWrapper, () -> categoriesImportManager.createCategories(ymlPayload));
145 return uploadElementTypeServletLogic(createElementsMethod, file, request, creator, "categories");
150 @Consumes(MediaType.MULTIPART_FORM_DATA)
151 @Produces(MediaType.APPLICATION_JSON)
152 @ApiOperation(value = "Create Categories from yaml", httpMethod = "POST", notes = "Returns created data types", response = Response.class)
153 @ApiResponses(value = { @ApiResponse(code = 201, message = "Data types created"), @ApiResponse(code = 403, message = "Restricted operation"), @ApiResponse(code = 400, message = "Invalid content / Missing content"),
154 @ApiResponse(code = 409, message = "Data types already exist") })
155 public Response uploadDataTypes(@ApiParam("FileInputStream") @FormDataParam("dataTypesZip") File file, @Context final HttpServletRequest request, @HeaderParam("USER_ID") String creator) {
156 ConsumerTwoParam<Wrapper<Response>, String> createElementsMethod = (responseWrapper, ymlPayload) -> createDataTypes(responseWrapper, ymlPayload);
157 return uploadElementTypeServletLogic(createElementsMethod, file, request, creator, NodeTypeEnum.DataType.getName());
162 @Consumes(MediaType.MULTIPART_FORM_DATA)
163 @Produces(MediaType.APPLICATION_JSON)
164 @ApiOperation(value = "Create GroupTypes from yaml", httpMethod = "POST", notes = "Returns created group types", response = Response.class)
165 @ApiResponses(value = { @ApiResponse(code = 201, message = "group types created"), @ApiResponse(code = 403, message = "Restricted operation"), @ApiResponse(code = 400, message = "Invalid content / Missing content"),
166 @ApiResponse(code = 409, message = "group types already exist") })
167 public Response uploadGroupTypes(@ApiParam("FileInputStream") @FormDataParam("groupTypesZip") File file, @Context final HttpServletRequest request, @HeaderParam("USER_ID") String creator) {
168 ConsumerTwoParam<Wrapper<Response>, String> createElementsMethod = (responseWrapper, ymlPayload) -> createGroupTypes(responseWrapper, ymlPayload);
169 return uploadElementTypeServletLogic(createElementsMethod, file, request, creator, NodeTypeEnum.GroupType.getName());
173 @Path("/policytypes")
174 @Consumes(MediaType.MULTIPART_FORM_DATA)
175 @Produces(MediaType.APPLICATION_JSON)
176 @ApiOperation(value = "Create PolicyTypes from yaml", httpMethod = "POST", notes = "Returns created policy types", response = Response.class)
177 @ApiResponses(value = { @ApiResponse(code = 201, message = "policy types created"), @ApiResponse(code = 403, message = "Restricted operation"), @ApiResponse(code = 400, message = "Invalid content / Missing content"),
178 @ApiResponse(code = 409, message = "policy types already exist") })
179 public Response uploadPolicyTypes(@ApiParam("FileInputStream") @FormDataParam("policyTypesZip") File file, @Context final HttpServletRequest request, @HeaderParam("USER_ID") String creator) {
180 return uploadElementTypeServletLogic(this::createPolicyTypes, file, request, creator, NodeTypeEnum.PolicyType.getName());
183 private Response uploadElementTypeServletLogic(ConsumerTwoParam<Wrapper<Response>, String> createElementsMethod, File file, final HttpServletRequest request, String creator, String elementTypeName) {
185 String userId = initHeaderParam(creator, request, Constants.USER_ID_HEADER);
187 Wrapper<Response> responseWrapper = new Wrapper<>();
188 Wrapper<User> userWrapper = new Wrapper<>();
189 Wrapper<String> yamlStringWrapper = new Wrapper<>();
191 String url = request.getMethod() + " " + request.getRequestURI();
192 log.debug("Start handle request of {}", url);
194 validateUserExist(responseWrapper, userWrapper, userId);
196 if (responseWrapper.isEmpty()) {
197 validateUserRole(responseWrapper, userWrapper.getInnerElement());
200 if (responseWrapper.isEmpty()) {
201 validateDataNotNull(responseWrapper, file);
204 if (responseWrapper.isEmpty()) {
205 fillZipContents(yamlStringWrapper, file);
208 if (responseWrapper.isEmpty()) {
209 createElementsMethod.accept(responseWrapper, yamlStringWrapper.getInnerElement());
212 return responseWrapper.getInnerElement();
214 } catch (Exception e) {
215 log.debug("create {} failed with exception:", elementTypeName, e);
216 BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Create " + elementTypeName);
217 return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
221 private <T> void createElementsType(Wrapper<Response> responseWrapper, Supplier<Either<T, ResponseFormat>> elementsCreater) {
222 Either<T, ResponseFormat> eitherResult = elementsCreater.get();
223 if (eitherResult.isRight()) {
224 Response response = buildErrorResponse(eitherResult.right().value());
225 responseWrapper.setInnerElement(response);
228 Response response = buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.CREATED), RepresentationUtils.toRepresentation(eitherResult.left().value()));
229 responseWrapper.setInnerElement(response);
230 } catch (Exception e) {
231 Response response = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
232 responseWrapper.setInnerElement(response);
233 log.error("#createElementsType - json serialization failed with error: ", e);
239 private void createDataTypes(Wrapper<Response> responseWrapper, String dataTypesYml) {
240 final Supplier<Either<List<ImmutablePair<DataTypeDefinition, Boolean>>, ResponseFormat>> generateElementTypeFromYml = () -> dataTypeImportManager.createDataTypes(dataTypesYml);
241 buildStatusForElementTypeCreate(responseWrapper, generateElementTypeFromYml, ActionStatus.DATA_TYPE_ALREADY_EXIST, NodeTypeEnum.DataType.name());
245 private void createGroupTypes(Wrapper<Response> responseWrapper, String groupTypesYml) {
246 final Supplier<Either<List<ImmutablePair<GroupTypeDefinition, Boolean>>, ResponseFormat>> generateElementTypeFromYml = () -> groupTypeImportManager.createGroupTypes(groupTypesYml);
247 buildStatusForElementTypeCreate(responseWrapper, generateElementTypeFromYml, ActionStatus.GROUP_TYPE_ALREADY_EXIST, NodeTypeEnum.GroupType.name());
251 private void createPolicyTypes(Wrapper<Response> responseWrapper, String policyTypesYml) {
252 final Supplier<Either<List<ImmutablePair<PolicyTypeDefinition, Boolean>>, ResponseFormat>> generateElementTypeFromYml = () -> policyTypeImportManager.createPolicyTypes(policyTypesYml);
253 buildStatusForElementTypeCreate(responseWrapper, generateElementTypeFromYml, ActionStatus.POLICY_TYPE_ALREADY_EXIST, NodeTypeEnum.PolicyType.name());
257 private <ElementTypeDefinition> void buildStatusForElementTypeCreate(Wrapper<Response> responseWrapper, Supplier<Either<List<ImmutablePair<ElementTypeDefinition, Boolean>>, ResponseFormat>> generateElementTypeFromYml, ActionStatus alreadyExistStatus, String elementTypeName) {
258 Either<List<ImmutablePair<ElementTypeDefinition, Boolean>>, ResponseFormat> eitherResult = generateElementTypeFromYml.get();
260 if (eitherResult.isRight()) {
261 Response response = buildErrorResponse(eitherResult.right().value());
262 responseWrapper.setInnerElement(response);
264 Object representation;
266 List<ImmutablePair<ElementTypeDefinition, Boolean>> list = eitherResult.left().value();
267 ActionStatus status = ActionStatus.OK;
270 // Group result by the right value - true or false.
271 // I.e., get the number of data types which are new and
273 Map<Boolean, List<ImmutablePair<ElementTypeDefinition, Boolean>>> collect = list.stream().collect(Collectors.groupingBy(ImmutablePair<ElementTypeDefinition, Boolean>::getRight));
274 if (collect != null) {
275 Set<Boolean> keySet = collect.keySet();
276 if (keySet.size() == 1) {
277 Boolean isNew = keySet.iterator().next();
278 if (isNew.booleanValue()) {
279 // all data types created at the first time
280 status = ActionStatus.CREATED;
282 // All data types already exists
284 status = alreadyExistStatus;
289 representation = RepresentationUtils.toRepresentation(eitherResult.left().value());
291 Response response = buildOkResponse(getComponentsUtils().getResponseFormat(status), representation);
292 responseWrapper.setInnerElement(response);
294 } catch (IOException e) {
295 BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Create " + elementTypeName);
296 log.debug("failed to convert {} to json", elementTypeName, e);
297 Response response = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
298 responseWrapper.setInnerElement(response);