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=========================================================
20 package org.openecomp.sdc.be.servlets;
22 import com.fasterxml.jackson.databind.ObjectMapper;
23 import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
24 import com.google.gson.reflect.TypeToken;
25 import com.jcabi.aspects.Loggable;
26 import com.networknt.schema.JsonSchemaFactory;
27 import com.networknt.schema.SpecVersion;
28 import com.networknt.schema.ValidationMessage;
29 import fj.data.Either;
30 import io.swagger.v3.oas.annotations.Operation;
31 import io.swagger.v3.oas.annotations.Parameter;
32 import io.swagger.v3.oas.annotations.media.ArraySchema;
33 import io.swagger.v3.oas.annotations.media.Content;
34 import io.swagger.v3.oas.annotations.media.Schema;
35 import io.swagger.v3.oas.annotations.responses.ApiResponse;
36 import io.swagger.v3.oas.annotations.servers.Server;
37 import io.swagger.v3.oas.annotations.tags.Tag;
38 import org.apache.commons.lang3.tuple.ImmutablePair;
39 import org.glassfish.jersey.media.multipart.FormDataParam;
40 import org.jetbrains.annotations.NotNull;
41 import org.openecomp.sdc.be.components.impl.ArtifactTypeImportManager;
42 import org.openecomp.sdc.be.components.impl.CapabilityTypeImportManager;
43 import org.openecomp.sdc.be.components.impl.CategoriesImportManager;
44 import org.openecomp.sdc.be.components.impl.ComponentInstanceBusinessLogic;
45 import org.openecomp.sdc.be.components.impl.DataTypeImportManager;
46 import org.openecomp.sdc.be.components.impl.GroupTypeImportManager;
47 import org.openecomp.sdc.be.components.impl.InterfaceLifecycleTypeImportManager;
48 import org.openecomp.sdc.be.components.impl.PolicyTypeImportManager;
49 import org.openecomp.sdc.be.components.impl.RelationshipTypeImportManager;
50 import org.openecomp.sdc.be.components.impl.ResourceImportManager;
51 import org.openecomp.sdc.be.components.impl.exceptions.ByActionStatusComponentException;
52 import org.openecomp.sdc.be.components.impl.model.ToscaTypeImportData;
53 import org.openecomp.sdc.be.config.BeEcompErrorManager;
54 import org.openecomp.sdc.be.dao.api.ActionStatus;
55 import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
56 import org.openecomp.sdc.be.datatypes.tosca.ToscaDataDefinition;
57 import org.openecomp.sdc.be.impl.ComponentsUtils;
58 import org.openecomp.sdc.be.impl.ServletUtils;
59 import org.openecomp.sdc.be.model.DataTypeDefinition;
60 import org.openecomp.sdc.be.model.GroupTypeDefinition;
61 import org.openecomp.sdc.be.model.PolicyTypeDefinition;
62 import org.openecomp.sdc.be.model.RelationshipTypeDefinition;
63 import org.openecomp.sdc.be.model.User;
64 import org.openecomp.sdc.be.model.normatives.ToscaTypeMetadata;
65 import org.openecomp.sdc.common.api.Constants;
66 import org.openecomp.sdc.common.datastructure.FunctionalInterfaces.ConsumerFourParam;
67 import org.openecomp.sdc.common.datastructure.FunctionalInterfaces.ConsumerTwoParam;
68 import org.openecomp.sdc.common.datastructure.Wrapper;
69 import org.openecomp.sdc.common.log.wrappers.Logger;
70 import org.openecomp.sdc.exception.ResponseFormat;
71 import org.springframework.stereotype.Controller;
73 import javax.inject.Inject;
74 import javax.servlet.http.HttpServletRequest;
75 import javax.ws.rs.Consumes;
76 import javax.ws.rs.HeaderParam;
77 import javax.ws.rs.POST;
78 import javax.ws.rs.Path;
79 import javax.ws.rs.Produces;
80 import javax.ws.rs.core.Context;
81 import javax.ws.rs.core.MediaType;
82 import javax.ws.rs.core.Response;
84 import java.io.FileInputStream;
85 import java.io.IOException;
86 import java.io.InputStream;
87 import java.nio.charset.StandardCharsets;
88 import java.util.HashSet;
89 import java.util.List;
92 import java.util.function.Supplier;
93 import java.util.stream.Collectors;
95 @Loggable(prepend = true, value = Loggable.DEBUG, trim = false)
96 @Path("/v1/catalog/uploadType")
97 @Consumes(MediaType.MULTIPART_FORM_DATA)
98 @Produces(MediaType.APPLICATION_JSON)
99 @Tag(name = "SDCE-2 APIs")
100 @Server(url = "/sdc2/rest")
102 public class TypesUploadServlet extends AbstractValidationsServlet {
104 private static final String CREATE = "Create ";
105 private static final String START_HANDLE_REQUEST_OF = "Start handle request of {}";
106 private static final String CREATE_FAILED_WITH_EXCEPTION = "create {} failed with exception:";
107 private static final Logger log = Logger.getLogger(TypesUploadServlet.class);
108 private final CapabilityTypeImportManager capabilityTypeImportManager;
109 private final InterfaceLifecycleTypeImportManager interfaceLifecycleTypeImportManager;
110 private final CategoriesImportManager categoriesImportManager;
111 private final DataTypeImportManager dataTypeImportManager;
112 private final GroupTypeImportManager groupTypeImportManager;
113 private final PolicyTypeImportManager policyTypeImportManager;
114 private final RelationshipTypeImportManager relationshipTypeImportManager;
115 private final ArtifactTypeImportManager artifactTypeImportManager;
118 public TypesUploadServlet(ComponentInstanceBusinessLogic componentInstanceBL,
119 ComponentsUtils componentsUtils, ServletUtils servletUtils, ResourceImportManager resourceImportManager,
120 CapabilityTypeImportManager capabilityTypeImportManager,
121 InterfaceLifecycleTypeImportManager interfaceLifecycleTypeImportManager,
122 CategoriesImportManager categoriesImportManager, DataTypeImportManager dataTypeImportManager,
123 GroupTypeImportManager groupTypeImportManager, PolicyTypeImportManager policyTypeImportManager,
124 RelationshipTypeImportManager relationshipTypeImportManager, ArtifactTypeImportManager artifactTypeImportManager) {
125 super(componentInstanceBL, componentsUtils, servletUtils, resourceImportManager);
126 this.capabilityTypeImportManager = capabilityTypeImportManager;
127 this.interfaceLifecycleTypeImportManager = interfaceLifecycleTypeImportManager;
128 this.categoriesImportManager = categoriesImportManager;
129 this.dataTypeImportManager = dataTypeImportManager;
130 this.groupTypeImportManager = groupTypeImportManager;
131 this.policyTypeImportManager = policyTypeImportManager;
132 this.relationshipTypeImportManager = relationshipTypeImportManager;
133 this.artifactTypeImportManager = artifactTypeImportManager;
138 @Operation(description = "Create Capability Type from yaml", method = "POST", summary = "Returns created Capability Type", responses = {
139 @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
140 @ApiResponse(responseCode = "201", description = "Capability Type created"),
141 @ApiResponse(responseCode = "403", description = "Restricted operation"),
142 @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
143 @ApiResponse(responseCode = "409", description = "Capability Type already exist")})
144 public Response uploadCapabilityType(@Parameter(description = "FileInputStream") @FormDataParam("capabilityTypeZip") File file,
145 @Context final HttpServletRequest request, @HeaderParam("USER_ID") String creator,
146 @Parameter(description = "model name") @FormDataParam("model") String modelName,
147 @Parameter(description = "includeToModelImport") @FormDataParam("includeToModelImport") boolean includeToModelDefaultImports) {
148 ConsumerFourParam<Wrapper<Response>, String, String, Boolean> createElementsMethod = (responseWrapper, ymlPayload, model, includeToModelImport) ->
149 createElementsType(responseWrapper, () -> capabilityTypeImportManager.createCapabilityTypes(ymlPayload, modelName,
150 includeToModelDefaultImports));
151 return uploadElementTypeServletLogic(createElementsMethod, file, request, creator, NodeTypeEnum.CapabilityType.name(), modelName,
152 includeToModelDefaultImports);
156 @Path("/relationship")
157 @Operation(description = "Create Relationship Type from yaml", method = "POST", summary = "Returns created Relationship Type", responses = {
158 @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
159 @ApiResponse(responseCode = "201", description = "Relationship Type created"),
160 @ApiResponse(responseCode = "403", description = "Restricted operation"),
161 @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
162 @ApiResponse(responseCode = "409", description = "Relationship Type already exist")})
163 public Response uploadRelationshipType(@Parameter(description = "FileInputStream") @FormDataParam("relationshipTypeZip") File file,
164 @Context final HttpServletRequest request, @HeaderParam("USER_ID") String creator,
165 @Parameter(description = "model name") @FormDataParam("model") String modelName,
166 @Parameter(description = "includeToModelImport") @FormDataParam("includeToModelImport") boolean includeToModelDefaultImports) {
167 return uploadElementTypeServletLogic(this::createRelationshipTypes, file, request, creator, NodeTypeEnum.RelationshipType.getName(),
168 modelName, includeToModelDefaultImports);
172 @Path("/interfaceLifecycle")
173 @Operation(description = "Create Interface Lyfecycle Type from yaml", method = "POST", summary = "Returns created Interface Lifecycle Type", responses = {
174 @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
175 @ApiResponse(responseCode = "201", description = "Interface Lifecycle Type created"),
176 @ApiResponse(responseCode = "403", description = "Restricted operation"),
177 @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
178 @ApiResponse(responseCode = "409", description = "Interface Lifecycle Type already exist")})
179 public Response uploadInterfaceLifecycleType(@Parameter(description = "FileInputStream") @FormDataParam("interfaceLifecycleTypeZip") File file,
180 @Context final HttpServletRequest request, @HeaderParam("USER_ID") String creator,
181 @Parameter(description = "model name") @FormDataParam("model") String modelName,
182 @Parameter(description = "includeToModelImport") @FormDataParam("includeToModelImport") boolean includeToModelDefaultImports) {
183 ConsumerTwoParam<Wrapper<Response>, String> createElementsMethod = (responseWrapper, ymlPayload) ->
184 createElementsType(responseWrapper, () -> interfaceLifecycleTypeImportManager.createLifecycleTypes(ymlPayload, modelName,
185 includeToModelDefaultImports));
186 return uploadElementTypeServletLogic(createElementsMethod, file, request, creator, "Interface Types");
190 @Path("/artifactTypes")
191 @Operation(description = "Create Tosca Artifact types from yaml", method = "POST", summary = "Returns created Tosca artifact types", responses = {
192 @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
193 @ApiResponse(responseCode = "201", description = "Tosca Artifact types created"),
194 @ApiResponse(responseCode = "403", description = "Restricted operation"),
195 @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
196 @ApiResponse(responseCode = "409", description = "Tosca Artifact Type already exist")})
197 public Response uploadArtifactTypes(@Parameter(description = "Zip file containing a yaml with the TOSCA artifact types definition")
198 @FormDataParam("artifactsZip") File file,
199 @Parameter(description = "model name") @FormDataParam("model") String modelName,
200 @Context final HttpServletRequest request, @HeaderParam("USER_ID") String creator,
201 @Parameter(description = "A flag to add types to the default imports")
202 @FormDataParam("includeToModelImport") boolean includeToModelDefaultImports) {
203 final ConsumerTwoParam<Wrapper<Response>, String> createElementsMethod = (responseWrapper, ymlPayload) ->
204 createElementsType(responseWrapper,
205 () -> artifactTypeImportManager.createArtifactTypes(ymlPayload, modelName, includeToModelDefaultImports));
206 return uploadElementTypeServletLogic(createElementsMethod, file, request, creator, NodeTypeEnum.ArtifactType.getName());
211 @Operation(description = "Create Categories from yaml", method = "POST", summary = "Returns created categories", responses = {
212 @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
213 @ApiResponse(responseCode = "201", description = "Categories created"),
214 @ApiResponse(responseCode = "403", description = "Restricted operation"),
215 @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
216 @ApiResponse(responseCode = "409", description = "Category already exist")})
217 public Response uploadCategories(@Parameter(description = "FileInputStream") @FormDataParam("categoriesZip") File file,
218 @Context final HttpServletRequest request, @HeaderParam("USER_ID") String creator) {
219 ConsumerTwoParam<Wrapper<Response>, String> createElementsMethod = (responseWrapper, ymlPayload) ->
220 createElementsType(responseWrapper, () -> categoriesImportManager.createCategories(ymlPayload));
221 return uploadElementTypeServletLogic(createElementsMethod, file, request, creator, "categories");
226 @Operation(description = "Create Data Types from zip", method = "POST", summary = "Returns created data types", responses = {
227 @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
228 @ApiResponse(responseCode = "201", description = "Data types created"),
229 @ApiResponse(responseCode = "403", description = "Restricted operation"),
230 @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
231 @ApiResponse(responseCode = "409", description = "Data types already exist")})
232 public Response uploadDataTypes(@Parameter(description = "FileInputStream") @FormDataParam("dataTypesZip") File file,
233 @Context final HttpServletRequest request, @HeaderParam("USER_ID") String creator,
234 @Parameter(description = "model name") @FormDataParam("model") String modelName,
235 @Parameter(description = "includeToModelImport") @FormDataParam("includeToModelImport") boolean includeToModelDefaultImports) {
236 return uploadElementTypeServletLogic(this::createDataTypes, file, request, creator, NodeTypeEnum.DataType.getName(), modelName,
237 includeToModelDefaultImports);
241 @Path("/datatypesyaml")
242 @Operation(description = "Create Data Types from yaml", method = "POST", summary = "Returns created data types", responses = {
243 @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
244 @ApiResponse(responseCode = "201", description = "Data types created"),
245 @ApiResponse(responseCode = "403", description = "Restricted operation"),
246 @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
247 @ApiResponse(responseCode = "409", description = "Data types already exist")})
248 public Response uploadDataTypesYaml(@Parameter(description = "FileInputStream") @FormDataParam("dataTypesYaml") File file,
249 @Context final HttpServletRequest request, @HeaderParam("USER_ID") String creator,
250 @Parameter(description = "model name") @FormDataParam("model") String modelName,
251 @Parameter(description = "includeToModelImport") @FormDataParam("includeToModelImport") boolean includeToModelDefaultImports) {
252 return uploadElementTypeServletLogicYaml(this::createDataTypes, file, request, creator, NodeTypeEnum.DataType.getName(), modelName,
253 includeToModelDefaultImports);
258 @Operation(description = "Create GroupTypes from yaml", method = "POST", summary = "Returns created group types", responses = {
259 @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
260 @ApiResponse(responseCode = "201", description = "group types created"),
261 @ApiResponse(responseCode = "403", description = "Restricted operation"),
262 @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
263 @ApiResponse(responseCode = "409", description = "group types already exist")})
264 public Response uploadGroupTypes(@Parameter(description = "toscaTypeMetadata") @FormDataParam("toscaTypeMetadata") String toscaTypesMetaData,
265 @Parameter(description = "model name") @FormDataParam("model") String modelName,
266 @Parameter(description = "FileInputStream") @FormDataParam("groupTypesZip") File file,
267 @Context final HttpServletRequest request, @HeaderParam("USER_ID") String creator,
268 @Parameter(description = "includeToModelImport") @FormDataParam("includeToModelImport") boolean includeToModelDefaultImports) {
269 Map<String, ToscaTypeMetadata> typesMetadata = getTypesMetadata(toscaTypesMetaData);
270 return uploadTypesWithMetaData(this::createGroupTypes, typesMetadata, file, request, creator, NodeTypeEnum.GroupType.getName(), modelName,
271 includeToModelDefaultImports);
275 @Path("/policytypes")
276 @Operation(description = "Create PolicyTypes from yaml", method = "POST", summary = "Returns created policy types", responses = {
277 @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
278 @ApiResponse(responseCode = "201", description = "policy types created"),
279 @ApiResponse(responseCode = "403", description = "Restricted operation"),
280 @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
281 @ApiResponse(responseCode = "409", description = "policy types already exist")})
282 public Response uploadPolicyTypes(@Parameter(description = "toscaTypeMetadata") @FormDataParam("toscaTypeMetadata") String toscaTypesMetaData,
283 @Parameter(description = "model name") @FormDataParam("model") String modelName,
284 @Parameter(description = "FileInputStream") @FormDataParam("policyTypesZip") File file,
285 @Context final HttpServletRequest request, @HeaderParam("USER_ID") String creator,
286 @Parameter(description = "includeToModelImport") @FormDataParam("includeToModelImport") boolean includeToModelDefaultImports) {
287 Map<String, ToscaTypeMetadata> typesMetadata = getTypesMetadata(toscaTypesMetaData);
288 return uploadTypesWithMetaData(this::createPolicyTypes, typesMetadata, file, request, creator, NodeTypeEnum.PolicyType.getName(), modelName,
289 includeToModelDefaultImports);
292 private Map<String, ToscaTypeMetadata> getTypesMetadata(String toscaTypesMetaData) {
293 return gson.fromJson(toscaTypesMetaData, new TypeToken<Map<String, ToscaTypeMetadata>>() {
297 private Response uploadElementTypeServletLogic(ConsumerTwoParam<Wrapper<Response>, String> createElementsMethod, File file,
298 final HttpServletRequest request, String creator, String elementTypeName) {
300 String userId = initHeaderParam(creator, request, Constants.USER_ID_HEADER);
302 Wrapper<String> yamlStringWrapper = new Wrapper<>();
303 String url = request.getMethod() + " " + request.getRequestURI();
304 log.debug(START_HANDLE_REQUEST_OF, url);
305 Wrapper<Response> responseWrapper = doUploadTypeValidations(request, userId, file);
306 if (responseWrapper.isEmpty()) {
307 fillZipContents(yamlStringWrapper, file);
309 if (responseWrapper.isEmpty()) {
310 createElementsMethod.accept(responseWrapper, yamlStringWrapper.getInnerElement());
312 return responseWrapper.getInnerElement();
313 } catch (Exception e) {
314 log.debug(CREATE_FAILED_WITH_EXCEPTION, elementTypeName, e);
315 BeEcompErrorManager.getInstance().logBeRestApiGeneralError(CREATE + elementTypeName);
316 return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
320 private Response uploadElementTypeServletLogic(final ConsumerFourParam<Wrapper<Response>, String, String, Boolean> createElementsMethod,
321 final File file, final HttpServletRequest request, final String creator,
322 final String elementTypeName, final String modelName, final boolean includeToModelDefaultImports) {
324 final String userId = initHeaderParam(creator, request, Constants.USER_ID_HEADER);
326 final Wrapper<String> yamlStringWrapper = new Wrapper<>();
327 final String url = request.getMethod() + " " + request.getRequestURI();
328 log.debug(START_HANDLE_REQUEST_OF, url);
329 final Wrapper<Response> responseWrapper = doUploadTypeValidations(request, userId, file);
330 if (responseWrapper.isEmpty()) {
331 fillZipContents(yamlStringWrapper, file);
332 createElementsMethod.accept(responseWrapper, yamlStringWrapper.getInnerElement(), modelName, includeToModelDefaultImports);
334 return responseWrapper.getInnerElement();
335 } catch (final Exception e) {
336 log.debug(CREATE_FAILED_WITH_EXCEPTION, elementTypeName, e);
337 BeEcompErrorManager.getInstance().logBeRestApiGeneralError(CREATE + elementTypeName);
338 return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
342 private Response uploadElementTypeServletLogicYaml(final ConsumerFourParam<Wrapper<Response>, String, String, Boolean> createElementsMethod,
343 final File file, final HttpServletRequest request, final String creator,
344 final String elementTypeName, final String modelName,
345 final boolean includeToModelDefaultImports) {
347 final Set<ValidationMessage> validationMessages = validateYaml(file);
348 if (!validationMessages.isEmpty()) {
349 throw new ByActionStatusComponentException(ActionStatus.YAML_IS_INVALID, validationMessages.stream().map(validationMessage -> {
350 return validationMessage.getMessage();
351 }).collect(Collectors.joining("\n")));
353 final String userId = initHeaderParam(creator, request, Constants.USER_ID_HEADER);
355 final String url = request.getMethod() + " " + request.getRequestURI();
356 log.debug(START_HANDLE_REQUEST_OF, url);
357 final Wrapper<Response> responseWrapper = doUploadTypeValidations(request, userId, file);
358 final String yamlAsString = getFileAsString(file);
359 if (responseWrapper.isEmpty()) {
360 log.debug("received yaml: {}", yamlAsString);
361 createElementsMethod.accept(responseWrapper, yamlAsString, modelName, includeToModelDefaultImports);
364 return responseWrapper.getInnerElement();
365 } catch (final Exception e) {
366 log.debug(CREATE_FAILED_WITH_EXCEPTION, elementTypeName, e);
367 BeEcompErrorManager.getInstance().logBeRestApiGeneralError(CREATE + elementTypeName);
368 return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
372 private Set<ValidationMessage> validateYaml(final File file) {
373 final ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
374 final JsonSchemaFactory factory =
375 JsonSchemaFactory.builder(JsonSchemaFactory.getInstance(SpecVersion.VersionFlag.V202012)).objectMapper(mapper).build();
377 final Set<ValidationMessage> validationMessages = new HashSet<>();
378 try (final InputStream yamlFile = new FileInputStream(file);
379 final InputStream schemaFile = Thread.currentThread().getContextClassLoader().getResourceAsStream("validateYaml/schema.json")) {
380 validationMessages.addAll(factory.getSchema(schemaFile).validate(mapper.readTree(yamlFile)));
381 } catch (final IOException e) {
382 ValidationMessage.Builder builder = new ValidationMessage.Builder();
383 builder.customMessage(e.getMessage());
384 validationMessages.add(builder.build());
387 return validationMessages;
391 private String getFileAsString(File file) throws IOException {
392 try (final FileInputStream fl = new FileInputStream(file)) {
393 byte[] arr = new byte[(int) file.length()];
394 int read = fl.read(arr);
396 return new String(arr, StandardCharsets.UTF_8);
398 throw new IOException(String.format("Failed to read bytes from '%s'", file.getName()));
403 private Wrapper<Response> doUploadTypeValidations(final HttpServletRequest request, String userId, File file) {
404 Wrapper<Response> responseWrapper = new Wrapper<>();
405 Wrapper<User> userWrapper = new Wrapper<>();
406 String url = request.getMethod() + " " + request.getRequestURI();
407 log.debug(START_HANDLE_REQUEST_OF, url);
408 validateUserExist(responseWrapper, userWrapper, userId);
409 if (responseWrapper.isEmpty()) {
410 validateUserRole(responseWrapper, userWrapper.getInnerElement());
412 if (responseWrapper.isEmpty()) {
413 validateDataNotNull(responseWrapper, file);
415 return responseWrapper;
418 private Response uploadTypesWithMetaData(ConsumerFourParam<Wrapper<Response>, ToscaTypeImportData, String, Boolean> createElementsMethod,
419 Map<String, ToscaTypeMetadata> typesMetaData, File file, final HttpServletRequest request,
420 String creator, String elementTypeName, String modelName, final boolean includeToModelDefaultImports) {
422 String userId = initHeaderParam(creator, request, Constants.USER_ID_HEADER);
423 Wrapper<String> yamlStringWrapper = new Wrapper<>();
425 Wrapper<Response> responseWrapper = doUploadTypeValidations(request, userId, file);
426 if (responseWrapper.isEmpty()) {
427 fillZipContents(yamlStringWrapper, file);
429 if (responseWrapper.isEmpty()) {
430 ToscaTypeImportData toscaTypeImportData = new ToscaTypeImportData(yamlStringWrapper.getInnerElement(), typesMetaData);
431 createElementsMethod.accept(responseWrapper, toscaTypeImportData, modelName, includeToModelDefaultImports);
433 return responseWrapper.getInnerElement();
434 } catch (Exception e) {
435 log.debug(CREATE_FAILED_WITH_EXCEPTION, elementTypeName, e);
436 BeEcompErrorManager.getInstance().logBeRestApiGeneralError(CREATE + elementTypeName);
437 return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
441 private <T> void createElementsType(Wrapper<Response> responseWrapper, Supplier<Either<T, ResponseFormat>> elementsCreater) {
442 Either<T, ResponseFormat> eitherResult = elementsCreater.get();
443 if (eitherResult.isRight()) {
444 responseWrapper.setInnerElement(buildErrorResponse(eitherResult.right().value()));
447 Response response = buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.CREATED),
448 RepresentationUtils.toRepresentation(eitherResult.left().value()));
449 responseWrapper.setInnerElement(response);
450 } catch (Exception e) {
451 responseWrapper.setInnerElement(buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR)));
452 log.error("#createElementsType - json serialization failed with error: ", e);
458 private void createDataTypes(Wrapper<Response> responseWrapper, String dataTypesYml, final String modelName,
459 final boolean includeToModelDefaultImports) {
460 final Supplier<Either<List<ImmutablePair<DataTypeDefinition, Boolean>>, ResponseFormat>> generateElementTypeFromYml = () ->
461 dataTypeImportManager.createDataTypes(dataTypesYml, modelName, includeToModelDefaultImports);
462 buildStatusForElementTypeCreate(responseWrapper, generateElementTypeFromYml, ActionStatus.DATA_TYPE_ALREADY_EXIST,
463 NodeTypeEnum.DataType.name());
467 private void createGroupTypes(Wrapper<Response> responseWrapper, ToscaTypeImportData toscaTypeImportData, String modelName,
468 final boolean includeToModelDefaultImports) {
469 final Supplier<Either<List<ImmutablePair<GroupTypeDefinition, Boolean>>, ResponseFormat>> generateElementTypeFromYml = () ->
470 groupTypeImportManager.createGroupTypes(toscaTypeImportData, modelName, includeToModelDefaultImports);
471 buildStatusForElementTypeCreate(responseWrapper, generateElementTypeFromYml, ActionStatus.GROUP_TYPE_ALREADY_EXIST,
472 NodeTypeEnum.GroupType.name());
476 private void createPolicyTypes(Wrapper<Response> responseWrapper, ToscaTypeImportData toscaTypeImportData, String modelName,
477 final boolean includeToModelDefaultImports) {
478 final Supplier<Either<List<ImmutablePair<PolicyTypeDefinition, Boolean>>, ResponseFormat>> generateElementTypeFromYml = () ->
479 policyTypeImportManager.createPolicyTypes(toscaTypeImportData, modelName, includeToModelDefaultImports);
480 buildStatusForElementTypeCreate(responseWrapper, generateElementTypeFromYml, ActionStatus.POLICY_TYPE_ALREADY_EXIST,
481 NodeTypeEnum.PolicyType.name());
485 private <T extends ToscaDataDefinition> void buildStatusForElementTypeCreate(Wrapper<Response> responseWrapper,
486 Supplier<Either<List<ImmutablePair<T, Boolean>>, ResponseFormat>> generateElementTypeFromYml,
487 ActionStatus alreadyExistStatus, String elementTypeName) {
488 Either<List<ImmutablePair<T, Boolean>>, ResponseFormat> eitherResult = generateElementTypeFromYml.get();
489 if (eitherResult.isRight()) {
490 responseWrapper.setInnerElement(buildErrorResponse(eitherResult.right().value()));
494 final List<ImmutablePair<T, Boolean>> list = eitherResult.left().value();
495 ActionStatus status = ActionStatus.OK;
497 // Group result by the right value - true or false.
498 // I.e., get the number of data types which are new and which are old.
499 final Map<Boolean, List<ImmutablePair<T, Boolean>>> collect =
500 list.stream().collect(Collectors.groupingBy(ImmutablePair<T, Boolean>::getRight));
501 if (collect != null) {
502 Set<Boolean> keySet = collect.keySet();
503 if (keySet.size() == 1) {
504 Boolean isNew = keySet.iterator().next();
505 if (Boolean.TRUE.equals(isNew)) {
506 // all data types created at the first time
507 status = ActionStatus.CREATED;
509 // All data types already exists
510 status = alreadyExistStatus;
515 final Object representation = RepresentationUtils.toRepresentation(eitherResult.left().value());
516 responseWrapper.setInnerElement(buildOkResponse(getComponentsUtils().getResponseFormat(status), representation));
517 } catch (IOException e) {
518 BeEcompErrorManager.getInstance().logBeRestApiGeneralError(CREATE + elementTypeName);
519 log.debug("failed to convert {} to json", elementTypeName, e);
520 responseWrapper.setInnerElement(buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR)));
525 // relationship types
526 private void createRelationshipTypes(final Wrapper<Response> responseWrapper,
527 final String relationshipTypesYml,
528 final String modelName,
529 final boolean includeToModelDefaultImports) {
530 final Supplier<Either<List<ImmutablePair<RelationshipTypeDefinition, Boolean>>, ResponseFormat>> generateElementTypeFromYml = () -> relationshipTypeImportManager
531 .createRelationshipTypes(relationshipTypesYml, modelName, includeToModelDefaultImports);
532 buildStatusForElementTypeCreate(responseWrapper, generateElementTypeFromYml, ActionStatus.RELATIONSHIP_TYPE_ALREADY_EXIST,
533 NodeTypeEnum.RelationshipType.name());