Remove legacy certificate handling
[sdc.git] / catalog-be / src / main / java / org / openecomp / sdc / be / servlets / TypesUploadServlet.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * SDC
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
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
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=========================================================
19  */
20 package org.openecomp.sdc.be.servlets;
21
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;
72
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;
83 import java.io.File;
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;
90 import java.util.Map;
91 import java.util.Set;
92 import java.util.function.Supplier;
93 import java.util.stream.Collectors;
94
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")
101 @Controller
102 public class TypesUploadServlet extends AbstractValidationsServlet {
103
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;
116
117     @Inject
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;
134     }
135
136     @POST
137     @Path("/capability")
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);
153     }
154
155     @POST
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);
169     }
170
171     @POST
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");
187     }
188
189     @POST
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());
207     }
208
209     @POST
210     @Path("/categories")
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");
222     }
223
224     @POST
225     @Path("/datatypes")
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);
238     }
239
240     @POST
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);
254     }
255
256     @POST
257     @Path("/grouptypes")
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);
272     }
273
274     @POST
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);
290     }
291
292     private Map<String, ToscaTypeMetadata> getTypesMetadata(String toscaTypesMetaData) {
293         return gson.fromJson(toscaTypesMetaData, new TypeToken<Map<String, ToscaTypeMetadata>>() {
294         }.getType());
295     }
296
297     private Response uploadElementTypeServletLogic(ConsumerTwoParam<Wrapper<Response>, String> createElementsMethod, File file,
298                                                    final HttpServletRequest request, String creator, String elementTypeName) {
299         init();
300         String userId = initHeaderParam(creator, request, Constants.USER_ID_HEADER);
301         try {
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);
308             }
309             if (responseWrapper.isEmpty()) {
310                 createElementsMethod.accept(responseWrapper, yamlStringWrapper.getInnerElement());
311             }
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));
317         }
318     }
319
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) {
323         init();
324         final String userId = initHeaderParam(creator, request, Constants.USER_ID_HEADER);
325         try {
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);
333             }
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));
339         }
340     }
341
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) {
346         init();
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")));
352         }
353         final String userId = initHeaderParam(creator, request, Constants.USER_ID_HEADER);
354         try {
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);
362             }
363
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));
369         }
370     }
371
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();
376
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());
385         }
386
387         return validationMessages;
388     }
389
390     @NotNull
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);
395             if (read > 0) {
396                 return new String(arr, StandardCharsets.UTF_8);
397             } else {
398                 throw new IOException(String.format("Failed to read bytes from '%s'", file.getName()));
399             }
400         }
401     }
402
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());
411         }
412         if (responseWrapper.isEmpty()) {
413             validateDataNotNull(responseWrapper, file);
414         }
415         return responseWrapper;
416     }
417
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) {
421         init();
422         String userId = initHeaderParam(creator, request, Constants.USER_ID_HEADER);
423         Wrapper<String> yamlStringWrapper = new Wrapper<>();
424         try {
425             Wrapper<Response> responseWrapper = doUploadTypeValidations(request, userId, file);
426             if (responseWrapper.isEmpty()) {
427                 fillZipContents(yamlStringWrapper, file);
428             }
429             if (responseWrapper.isEmpty()) {
430                 ToscaTypeImportData toscaTypeImportData = new ToscaTypeImportData(yamlStringWrapper.getInnerElement(), typesMetaData);
431                 createElementsMethod.accept(responseWrapper, toscaTypeImportData, modelName, includeToModelDefaultImports);
432             }
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));
438         }
439     }
440
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()));
445         } else {
446             try {
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);
453             }
454         }
455     }
456
457     // data types
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());
464     }
465
466     // group types
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());
473     }
474
475     // policy types
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());
482     }
483
484     // data types
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()));
491         } else {
492
493             try {
494                 final List<ImmutablePair<T, Boolean>> list = eitherResult.left().value();
495                 ActionStatus status = ActionStatus.OK;
496                 if (list != null) {
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;
508                             } else {
509                                 // All data types already exists
510                                 status = alreadyExistStatus;
511                             }
512                         }
513                     }
514                 }
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)));
521             }
522         }
523     }
524
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());
534     }
535 }