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.aaf.AafPermission;
52 import org.openecomp.sdc.be.components.impl.aaf.PermissionAllowed;
53 import org.openecomp.sdc.be.components.impl.exceptions.ByActionStatusComponentException;
54 import org.openecomp.sdc.be.components.impl.model.ToscaTypeImportData;
55 import org.openecomp.sdc.be.config.BeEcompErrorManager;
56 import org.openecomp.sdc.be.dao.api.ActionStatus;
57 import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
58 import org.openecomp.sdc.be.datatypes.tosca.ToscaDataDefinition;
59 import org.openecomp.sdc.be.impl.ComponentsUtils;
60 import org.openecomp.sdc.be.impl.ServletUtils;
61 import org.openecomp.sdc.be.model.DataTypeDefinition;
62 import org.openecomp.sdc.be.model.GroupTypeDefinition;
63 import org.openecomp.sdc.be.model.PolicyTypeDefinition;
64 import org.openecomp.sdc.be.model.RelationshipTypeDefinition;
65 import org.openecomp.sdc.be.model.User;
66 import org.openecomp.sdc.be.model.normatives.ToscaTypeMetadata;
67 import org.openecomp.sdc.common.api.Constants;
68 import org.openecomp.sdc.common.datastructure.FunctionalInterfaces.ConsumerFourParam;
69 import org.openecomp.sdc.common.datastructure.FunctionalInterfaces.ConsumerTwoParam;
70 import org.openecomp.sdc.common.datastructure.Wrapper;
71 import org.openecomp.sdc.common.log.wrappers.Logger;
72 import org.openecomp.sdc.exception.ResponseFormat;
73 import org.springframework.stereotype.Controller;
75 import javax.inject.Inject;
76 import javax.servlet.http.HttpServletRequest;
77 import javax.ws.rs.Consumes;
78 import javax.ws.rs.HeaderParam;
79 import javax.ws.rs.POST;
80 import javax.ws.rs.Path;
81 import javax.ws.rs.Produces;
82 import javax.ws.rs.core.Context;
83 import javax.ws.rs.core.MediaType;
84 import javax.ws.rs.core.Response;
86 import java.io.FileInputStream;
87 import java.io.IOException;
88 import java.io.InputStream;
89 import java.nio.charset.StandardCharsets;
90 import java.util.HashSet;
91 import java.util.List;
94 import java.util.function.Supplier;
95 import java.util.stream.Collectors;
97 @Loggable(prepend = true, value = Loggable.DEBUG, trim = false)
98 @Path("/v1/catalog/uploadType")
99 @Consumes(MediaType.MULTIPART_FORM_DATA)
100 @Produces(MediaType.APPLICATION_JSON)
101 @Tag(name = "SDCE-2 APIs")
102 @Server(url = "/sdc2/rest")
104 public class TypesUploadServlet extends AbstractValidationsServlet {
106 private static final String CREATE = "Create ";
107 private static final String START_HANDLE_REQUEST_OF = "Start handle request of {}";
108 private static final String CREATE_FAILED_WITH_EXCEPTION = "create {} failed with exception:";
109 private static final Logger log = Logger.getLogger(TypesUploadServlet.class);
110 private final CapabilityTypeImportManager capabilityTypeImportManager;
111 private final InterfaceLifecycleTypeImportManager interfaceLifecycleTypeImportManager;
112 private final CategoriesImportManager categoriesImportManager;
113 private final DataTypeImportManager dataTypeImportManager;
114 private final GroupTypeImportManager groupTypeImportManager;
115 private final PolicyTypeImportManager policyTypeImportManager;
116 private final RelationshipTypeImportManager relationshipTypeImportManager;
117 private final ArtifactTypeImportManager artifactTypeImportManager;
120 public TypesUploadServlet(ComponentInstanceBusinessLogic componentInstanceBL,
121 ComponentsUtils componentsUtils, ServletUtils servletUtils, ResourceImportManager resourceImportManager,
122 CapabilityTypeImportManager capabilityTypeImportManager,
123 InterfaceLifecycleTypeImportManager interfaceLifecycleTypeImportManager,
124 CategoriesImportManager categoriesImportManager, DataTypeImportManager dataTypeImportManager,
125 GroupTypeImportManager groupTypeImportManager, PolicyTypeImportManager policyTypeImportManager,
126 RelationshipTypeImportManager relationshipTypeImportManager, ArtifactTypeImportManager artifactTypeImportManager) {
127 super(componentInstanceBL, componentsUtils, servletUtils, resourceImportManager);
128 this.capabilityTypeImportManager = capabilityTypeImportManager;
129 this.interfaceLifecycleTypeImportManager = interfaceLifecycleTypeImportManager;
130 this.categoriesImportManager = categoriesImportManager;
131 this.dataTypeImportManager = dataTypeImportManager;
132 this.groupTypeImportManager = groupTypeImportManager;
133 this.policyTypeImportManager = policyTypeImportManager;
134 this.relationshipTypeImportManager = relationshipTypeImportManager;
135 this.artifactTypeImportManager = artifactTypeImportManager;
140 @Operation(description = "Create Capability Type from yaml", method = "POST", summary = "Returns created Capability Type", responses = {
141 @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
142 @ApiResponse(responseCode = "201", description = "Capability Type created"),
143 @ApiResponse(responseCode = "403", description = "Restricted operation"),
144 @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
145 @ApiResponse(responseCode = "409", description = "Capability Type already exist")})
146 @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
147 public Response uploadCapabilityType(@Parameter(description = "FileInputStream") @FormDataParam("capabilityTypeZip") File file,
148 @Context final HttpServletRequest request, @HeaderParam("USER_ID") String creator,
149 @Parameter(description = "model name") @FormDataParam("model") String modelName,
150 @Parameter(description = "includeToModelImport") @FormDataParam("includeToModelImport") boolean includeToModelDefaultImports) {
151 ConsumerFourParam<Wrapper<Response>, String, String, Boolean> createElementsMethod = (responseWrapper, ymlPayload, model, includeToModelImport) ->
152 createElementsType(responseWrapper, () -> capabilityTypeImportManager.createCapabilityTypes(ymlPayload, modelName,
153 includeToModelDefaultImports));
154 return uploadElementTypeServletLogic(createElementsMethod, file, request, creator, NodeTypeEnum.CapabilityType.name(), modelName,
155 includeToModelDefaultImports);
159 @Path("/relationship")
160 @Operation(description = "Create Relationship Type from yaml", method = "POST", summary = "Returns created Relationship Type", responses = {
161 @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
162 @ApiResponse(responseCode = "201", description = "Relationship Type created"),
163 @ApiResponse(responseCode = "403", description = "Restricted operation"),
164 @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
165 @ApiResponse(responseCode = "409", description = "Relationship Type already exist")})
166 @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
167 public Response uploadRelationshipType(@Parameter(description = "FileInputStream") @FormDataParam("relationshipTypeZip") File file,
168 @Context final HttpServletRequest request, @HeaderParam("USER_ID") String creator,
169 @Parameter(description = "model name") @FormDataParam("model") String modelName,
170 @Parameter(description = "includeToModelImport") @FormDataParam("includeToModelImport") boolean includeToModelDefaultImports) {
171 return uploadElementTypeServletLogic(this::createRelationshipTypes, file, request, creator, NodeTypeEnum.RelationshipType.getName(),
172 modelName, includeToModelDefaultImports);
176 @Path("/interfaceLifecycle")
177 @Operation(description = "Create Interface Lyfecycle Type from yaml", method = "POST", summary = "Returns created Interface Lifecycle Type", responses = {
178 @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
179 @ApiResponse(responseCode = "201", description = "Interface Lifecycle Type created"),
180 @ApiResponse(responseCode = "403", description = "Restricted operation"),
181 @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
182 @ApiResponse(responseCode = "409", description = "Interface Lifecycle Type already exist")})
183 @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
184 public Response uploadInterfaceLifecycleType(@Parameter(description = "FileInputStream") @FormDataParam("interfaceLifecycleTypeZip") File file,
185 @Context final HttpServletRequest request, @HeaderParam("USER_ID") String creator,
186 @Parameter(description = "model name") @FormDataParam("model") String modelName,
187 @Parameter(description = "includeToModelImport") @FormDataParam("includeToModelImport") boolean includeToModelDefaultImports) {
188 ConsumerTwoParam<Wrapper<Response>, String> createElementsMethod = (responseWrapper, ymlPayload) ->
189 createElementsType(responseWrapper, () -> interfaceLifecycleTypeImportManager.createLifecycleTypes(ymlPayload, modelName,
190 includeToModelDefaultImports));
191 return uploadElementTypeServletLogic(createElementsMethod, file, request, creator, "Interface Types");
195 @Path("/artifactTypes")
196 @Operation(description = "Create Tosca Artifact types from yaml", method = "POST", summary = "Returns created Tosca artifact types", responses = {
197 @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
198 @ApiResponse(responseCode = "201", description = "Tosca Artifact types created"),
199 @ApiResponse(responseCode = "403", description = "Restricted operation"),
200 @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
201 @ApiResponse(responseCode = "409", description = "Tosca Artifact Type already exist")})
202 @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
203 public Response uploadArtifactTypes(@Parameter(description = "Zip file containing a yaml with the TOSCA artifact types definition")
204 @FormDataParam("artifactsZip") File file,
205 @Parameter(description = "model name") @FormDataParam("model") String modelName,
206 @Context final HttpServletRequest request, @HeaderParam("USER_ID") String creator,
207 @Parameter(description = "A flag to add types to the default imports")
208 @FormDataParam("includeToModelImport") boolean includeToModelDefaultImports) {
209 final ConsumerTwoParam<Wrapper<Response>, String> createElementsMethod = (responseWrapper, ymlPayload) ->
210 createElementsType(responseWrapper,
211 () -> artifactTypeImportManager.createArtifactTypes(ymlPayload, modelName, includeToModelDefaultImports));
212 return uploadElementTypeServletLogic(createElementsMethod, file, request, creator, NodeTypeEnum.ArtifactType.getName());
217 @Operation(description = "Create Categories from yaml", method = "POST", summary = "Returns created categories", responses = {
218 @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
219 @ApiResponse(responseCode = "201", description = "Categories created"),
220 @ApiResponse(responseCode = "403", description = "Restricted operation"),
221 @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
222 @ApiResponse(responseCode = "409", description = "Category already exist")})
223 @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
224 public Response uploadCategories(@Parameter(description = "FileInputStream") @FormDataParam("categoriesZip") File file,
225 @Context final HttpServletRequest request, @HeaderParam("USER_ID") String creator) {
226 ConsumerTwoParam<Wrapper<Response>, String> createElementsMethod = (responseWrapper, ymlPayload) ->
227 createElementsType(responseWrapper, () -> categoriesImportManager.createCategories(ymlPayload));
228 return uploadElementTypeServletLogic(createElementsMethod, file, request, creator, "categories");
233 @Operation(description = "Create Data Types from zip", method = "POST", summary = "Returns created data types", responses = {
234 @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
235 @ApiResponse(responseCode = "201", description = "Data types created"),
236 @ApiResponse(responseCode = "403", description = "Restricted operation"),
237 @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
238 @ApiResponse(responseCode = "409", description = "Data types already exist")})
239 @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
240 public Response uploadDataTypes(@Parameter(description = "FileInputStream") @FormDataParam("dataTypesZip") File file,
241 @Context final HttpServletRequest request, @HeaderParam("USER_ID") String creator,
242 @Parameter(description = "model name") @FormDataParam("model") String modelName,
243 @Parameter(description = "includeToModelImport") @FormDataParam("includeToModelImport") boolean includeToModelDefaultImports) {
244 return uploadElementTypeServletLogic(this::createDataTypes, file, request, creator, NodeTypeEnum.DataType.getName(), modelName,
245 includeToModelDefaultImports);
249 @Path("/datatypesyaml")
250 @Operation(description = "Create Data Types from yaml", method = "POST", summary = "Returns created data types", responses = {
251 @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
252 @ApiResponse(responseCode = "201", description = "Data types created"),
253 @ApiResponse(responseCode = "403", description = "Restricted operation"),
254 @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
255 @ApiResponse(responseCode = "409", description = "Data types already exist")})
256 @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
257 public Response uploadDataTypesYaml(@Parameter(description = "FileInputStream") @FormDataParam("dataTypesYaml") File file,
258 @Context final HttpServletRequest request, @HeaderParam("USER_ID") String creator,
259 @Parameter(description = "model name") @FormDataParam("model") String modelName,
260 @Parameter(description = "includeToModelImport") @FormDataParam("includeToModelImport") boolean includeToModelDefaultImports) {
261 return uploadElementTypeServletLogicYaml(this::createDataTypes, file, request, creator, NodeTypeEnum.DataType.getName(), modelName,
262 includeToModelDefaultImports);
267 @Operation(description = "Create GroupTypes from yaml", method = "POST", summary = "Returns created group types", responses = {
268 @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
269 @ApiResponse(responseCode = "201", description = "group types created"),
270 @ApiResponse(responseCode = "403", description = "Restricted operation"),
271 @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
272 @ApiResponse(responseCode = "409", description = "group types already exist")})
273 @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
274 public Response uploadGroupTypes(@Parameter(description = "toscaTypeMetadata") @FormDataParam("toscaTypeMetadata") String toscaTypesMetaData,
275 @Parameter(description = "model name") @FormDataParam("model") String modelName,
276 @Parameter(description = "FileInputStream") @FormDataParam("groupTypesZip") File file,
277 @Context final HttpServletRequest request, @HeaderParam("USER_ID") String creator,
278 @Parameter(description = "includeToModelImport") @FormDataParam("includeToModelImport") boolean includeToModelDefaultImports) {
279 Map<String, ToscaTypeMetadata> typesMetadata = getTypesMetadata(toscaTypesMetaData);
280 return uploadTypesWithMetaData(this::createGroupTypes, typesMetadata, file, request, creator, NodeTypeEnum.GroupType.getName(), modelName,
281 includeToModelDefaultImports);
285 @Path("/policytypes")
286 @Operation(description = "Create PolicyTypes from yaml", method = "POST", summary = "Returns created policy types", responses = {
287 @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
288 @ApiResponse(responseCode = "201", description = "policy types created"),
289 @ApiResponse(responseCode = "403", description = "Restricted operation"),
290 @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
291 @ApiResponse(responseCode = "409", description = "policy types already exist")})
292 @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
293 public Response uploadPolicyTypes(@Parameter(description = "toscaTypeMetadata") @FormDataParam("toscaTypeMetadata") String toscaTypesMetaData,
294 @Parameter(description = "model name") @FormDataParam("model") String modelName,
295 @Parameter(description = "FileInputStream") @FormDataParam("policyTypesZip") File file,
296 @Context final HttpServletRequest request, @HeaderParam("USER_ID") String creator,
297 @Parameter(description = "includeToModelImport") @FormDataParam("includeToModelImport") boolean includeToModelDefaultImports) {
298 Map<String, ToscaTypeMetadata> typesMetadata = getTypesMetadata(toscaTypesMetaData);
299 return uploadTypesWithMetaData(this::createPolicyTypes, typesMetadata, file, request, creator, NodeTypeEnum.PolicyType.getName(), modelName,
300 includeToModelDefaultImports);
303 private Map<String, ToscaTypeMetadata> getTypesMetadata(String toscaTypesMetaData) {
304 return gson.fromJson(toscaTypesMetaData, new TypeToken<Map<String, ToscaTypeMetadata>>() {
308 private Response uploadElementTypeServletLogic(ConsumerTwoParam<Wrapper<Response>, String> createElementsMethod, File file,
309 final HttpServletRequest request, String creator, String elementTypeName) {
311 String userId = initHeaderParam(creator, request, Constants.USER_ID_HEADER);
313 Wrapper<String> yamlStringWrapper = new Wrapper<>();
314 String url = request.getMethod() + " " + request.getRequestURI();
315 log.debug(START_HANDLE_REQUEST_OF, url);
316 Wrapper<Response> responseWrapper = doUploadTypeValidations(request, userId, file);
317 if (responseWrapper.isEmpty()) {
318 fillZipContents(yamlStringWrapper, file);
320 if (responseWrapper.isEmpty()) {
321 createElementsMethod.accept(responseWrapper, yamlStringWrapper.getInnerElement());
323 return responseWrapper.getInnerElement();
324 } catch (Exception e) {
325 log.debug(CREATE_FAILED_WITH_EXCEPTION, elementTypeName, e);
326 BeEcompErrorManager.getInstance().logBeRestApiGeneralError(CREATE + elementTypeName);
327 return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
331 private Response uploadElementTypeServletLogic(final ConsumerFourParam<Wrapper<Response>, String, String, Boolean> createElementsMethod,
332 final File file, final HttpServletRequest request, final String creator,
333 final String elementTypeName, final String modelName, final boolean includeToModelDefaultImports) {
335 final String userId = initHeaderParam(creator, request, Constants.USER_ID_HEADER);
337 final Wrapper<String> yamlStringWrapper = new Wrapper<>();
338 final String url = request.getMethod() + " " + request.getRequestURI();
339 log.debug(START_HANDLE_REQUEST_OF, url);
340 final Wrapper<Response> responseWrapper = doUploadTypeValidations(request, userId, file);
341 if (responseWrapper.isEmpty()) {
342 fillZipContents(yamlStringWrapper, file);
343 createElementsMethod.accept(responseWrapper, yamlStringWrapper.getInnerElement(), modelName, includeToModelDefaultImports);
345 return responseWrapper.getInnerElement();
346 } catch (final Exception e) {
347 log.debug(CREATE_FAILED_WITH_EXCEPTION, elementTypeName, e);
348 BeEcompErrorManager.getInstance().logBeRestApiGeneralError(CREATE + elementTypeName);
349 return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
353 private Response uploadElementTypeServletLogicYaml(final ConsumerFourParam<Wrapper<Response>, String, String, Boolean> createElementsMethod,
354 final File file, final HttpServletRequest request, final String creator,
355 final String elementTypeName, final String modelName,
356 final boolean includeToModelDefaultImports) {
358 final Set<ValidationMessage> validationMessages = validateYaml(file);
359 if (!validationMessages.isEmpty()) {
360 throw new ByActionStatusComponentException(ActionStatus.YAML_IS_INVALID, validationMessages.stream().map(validationMessage -> {
361 return validationMessage.getMessage();
362 }).collect(Collectors.joining("\n")));
364 final String userId = initHeaderParam(creator, request, Constants.USER_ID_HEADER);
366 final String url = request.getMethod() + " " + request.getRequestURI();
367 log.debug(START_HANDLE_REQUEST_OF, url);
368 final Wrapper<Response> responseWrapper = doUploadTypeValidations(request, userId, file);
369 final String yamlAsString = getFileAsString(file);
370 if (responseWrapper.isEmpty()) {
371 log.debug("received yaml: {}", yamlAsString);
372 createElementsMethod.accept(responseWrapper, yamlAsString, modelName, includeToModelDefaultImports);
375 return responseWrapper.getInnerElement();
376 } catch (final Exception e) {
377 log.debug(CREATE_FAILED_WITH_EXCEPTION, elementTypeName, e);
378 BeEcompErrorManager.getInstance().logBeRestApiGeneralError(CREATE + elementTypeName);
379 return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
383 private Set<ValidationMessage> validateYaml(final File file) {
384 final ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
385 final JsonSchemaFactory factory =
386 JsonSchemaFactory.builder(JsonSchemaFactory.getInstance(SpecVersion.VersionFlag.V202012)).objectMapper(mapper).build();
388 final Set<ValidationMessage> validationMessages = new HashSet<>();
389 try (final InputStream yamlFile = new FileInputStream(file);
390 final InputStream schemaFile = Thread.currentThread().getContextClassLoader().getResourceAsStream("validateYaml/schema.json")) {
391 validationMessages.addAll(factory.getSchema(schemaFile).validate(mapper.readTree(yamlFile)));
392 } catch (final IOException e) {
393 ValidationMessage.Builder builder = new ValidationMessage.Builder();
394 builder.customMessage(e.getMessage());
395 validationMessages.add(builder.build());
398 return validationMessages;
402 private String getFileAsString(File file) throws IOException {
403 try (final FileInputStream fl = new FileInputStream(file)) {
404 byte[] arr = new byte[(int) file.length()];
405 int read = fl.read(arr);
407 return new String(arr, StandardCharsets.UTF_8);
409 throw new IOException(String.format("Failed to read bytes from '%s'", file.getName()));
414 private Wrapper<Response> doUploadTypeValidations(final HttpServletRequest request, String userId, File file) {
415 Wrapper<Response> responseWrapper = new Wrapper<>();
416 Wrapper<User> userWrapper = new Wrapper<>();
417 String url = request.getMethod() + " " + request.getRequestURI();
418 log.debug(START_HANDLE_REQUEST_OF, url);
419 validateUserExist(responseWrapper, userWrapper, userId);
420 if (responseWrapper.isEmpty()) {
421 validateUserRole(responseWrapper, userWrapper.getInnerElement());
423 if (responseWrapper.isEmpty()) {
424 validateDataNotNull(responseWrapper, file);
426 return responseWrapper;
429 private Response uploadTypesWithMetaData(ConsumerFourParam<Wrapper<Response>, ToscaTypeImportData, String, Boolean> createElementsMethod,
430 Map<String, ToscaTypeMetadata> typesMetaData, File file, final HttpServletRequest request,
431 String creator, String elementTypeName, String modelName, final boolean includeToModelDefaultImports) {
433 String userId = initHeaderParam(creator, request, Constants.USER_ID_HEADER);
434 Wrapper<String> yamlStringWrapper = new Wrapper<>();
436 Wrapper<Response> responseWrapper = doUploadTypeValidations(request, userId, file);
437 if (responseWrapper.isEmpty()) {
438 fillZipContents(yamlStringWrapper, file);
440 if (responseWrapper.isEmpty()) {
441 ToscaTypeImportData toscaTypeImportData = new ToscaTypeImportData(yamlStringWrapper.getInnerElement(), typesMetaData);
442 createElementsMethod.accept(responseWrapper, toscaTypeImportData, modelName, includeToModelDefaultImports);
444 return responseWrapper.getInnerElement();
445 } catch (Exception e) {
446 log.debug(CREATE_FAILED_WITH_EXCEPTION, elementTypeName, e);
447 BeEcompErrorManager.getInstance().logBeRestApiGeneralError(CREATE + elementTypeName);
448 return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
452 private <T> void createElementsType(Wrapper<Response> responseWrapper, Supplier<Either<T, ResponseFormat>> elementsCreater) {
453 Either<T, ResponseFormat> eitherResult = elementsCreater.get();
454 if (eitherResult.isRight()) {
455 responseWrapper.setInnerElement(buildErrorResponse(eitherResult.right().value()));
458 Response response = buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.CREATED),
459 RepresentationUtils.toRepresentation(eitherResult.left().value()));
460 responseWrapper.setInnerElement(response);
461 } catch (Exception e) {
462 responseWrapper.setInnerElement(buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR)));
463 log.error("#createElementsType - json serialization failed with error: ", e);
469 private void createDataTypes(Wrapper<Response> responseWrapper, String dataTypesYml, final String modelName,
470 final boolean includeToModelDefaultImports) {
471 final Supplier<Either<List<ImmutablePair<DataTypeDefinition, Boolean>>, ResponseFormat>> generateElementTypeFromYml = () ->
472 dataTypeImportManager.createDataTypes(dataTypesYml, modelName, includeToModelDefaultImports);
473 buildStatusForElementTypeCreate(responseWrapper, generateElementTypeFromYml, ActionStatus.DATA_TYPE_ALREADY_EXIST,
474 NodeTypeEnum.DataType.name());
478 private void createGroupTypes(Wrapper<Response> responseWrapper, ToscaTypeImportData toscaTypeImportData, String modelName,
479 final boolean includeToModelDefaultImports) {
480 final Supplier<Either<List<ImmutablePair<GroupTypeDefinition, Boolean>>, ResponseFormat>> generateElementTypeFromYml = () ->
481 groupTypeImportManager.createGroupTypes(toscaTypeImportData, modelName, includeToModelDefaultImports);
482 buildStatusForElementTypeCreate(responseWrapper, generateElementTypeFromYml, ActionStatus.GROUP_TYPE_ALREADY_EXIST,
483 NodeTypeEnum.GroupType.name());
487 private void createPolicyTypes(Wrapper<Response> responseWrapper, ToscaTypeImportData toscaTypeImportData, String modelName,
488 final boolean includeToModelDefaultImports) {
489 final Supplier<Either<List<ImmutablePair<PolicyTypeDefinition, Boolean>>, ResponseFormat>> generateElementTypeFromYml = () ->
490 policyTypeImportManager.createPolicyTypes(toscaTypeImportData, modelName, includeToModelDefaultImports);
491 buildStatusForElementTypeCreate(responseWrapper, generateElementTypeFromYml, ActionStatus.POLICY_TYPE_ALREADY_EXIST,
492 NodeTypeEnum.PolicyType.name());
496 private <T extends ToscaDataDefinition> void buildStatusForElementTypeCreate(Wrapper<Response> responseWrapper,
497 Supplier<Either<List<ImmutablePair<T, Boolean>>, ResponseFormat>> generateElementTypeFromYml,
498 ActionStatus alreadyExistStatus, String elementTypeName) {
499 Either<List<ImmutablePair<T, Boolean>>, ResponseFormat> eitherResult = generateElementTypeFromYml.get();
500 if (eitherResult.isRight()) {
501 responseWrapper.setInnerElement(buildErrorResponse(eitherResult.right().value()));
505 final List<ImmutablePair<T, Boolean>> list = eitherResult.left().value();
506 ActionStatus status = ActionStatus.OK;
508 // Group result by the right value - true or false.
509 // I.e., get the number of data types which are new and which are old.
510 final Map<Boolean, List<ImmutablePair<T, Boolean>>> collect =
511 list.stream().collect(Collectors.groupingBy(ImmutablePair<T, Boolean>::getRight));
512 if (collect != null) {
513 Set<Boolean> keySet = collect.keySet();
514 if (keySet.size() == 1) {
515 Boolean isNew = keySet.iterator().next();
516 if (Boolean.TRUE.equals(isNew)) {
517 // all data types created at the first time
518 status = ActionStatus.CREATED;
520 // All data types already exists
521 status = alreadyExistStatus;
526 final Object representation = RepresentationUtils.toRepresentation(eitherResult.left().value());
527 responseWrapper.setInnerElement(buildOkResponse(getComponentsUtils().getResponseFormat(status), representation));
528 } catch (IOException e) {
529 BeEcompErrorManager.getInstance().logBeRestApiGeneralError(CREATE + elementTypeName);
530 log.debug("failed to convert {} to json", elementTypeName, e);
531 responseWrapper.setInnerElement(buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR)));
536 // relationship types
537 private void createRelationshipTypes(final Wrapper<Response> responseWrapper,
538 final String relationshipTypesYml,
539 final String modelName,
540 final boolean includeToModelDefaultImports) {
541 final Supplier<Either<List<ImmutablePair<RelationshipTypeDefinition, Boolean>>, ResponseFormat>> generateElementTypeFromYml = () -> relationshipTypeImportManager
542 .createRelationshipTypes(relationshipTypesYml, modelName, includeToModelDefaultImports);
543 buildStatusForElementTypeCreate(responseWrapper, generateElementTypeFromYml, ActionStatus.RELATIONSHIP_TYPE_ALREADY_EXIST,
544 NodeTypeEnum.RelationshipType.name());