f7ea9bb40768f92001fed5d01036cbc43c17d915
[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.google.gson.reflect.TypeToken;
23 import com.jcabi.aspects.Loggable;
24 import fj.data.Either;
25 import io.swagger.v3.oas.annotations.Operation;
26 import io.swagger.v3.oas.annotations.Parameter;
27 import io.swagger.v3.oas.annotations.media.ArraySchema;
28 import io.swagger.v3.oas.annotations.media.Content;
29 import io.swagger.v3.oas.annotations.media.Schema;
30 import io.swagger.v3.oas.annotations.responses.ApiResponse;
31 import io.swagger.v3.oas.annotations.servers.Server;
32 import io.swagger.v3.oas.annotations.tags.Tag;
33 import java.io.File;
34 import java.io.FileInputStream;
35 import java.io.IOException;
36 import java.nio.charset.StandardCharsets;
37 import java.util.List;
38 import java.util.Map;
39 import java.util.Set;
40 import java.util.function.Supplier;
41 import java.util.stream.Collectors;
42 import javax.inject.Inject;
43 import javax.servlet.http.HttpServletRequest;
44 import javax.ws.rs.Consumes;
45 import javax.ws.rs.HeaderParam;
46 import javax.ws.rs.POST;
47 import javax.ws.rs.Path;
48 import javax.ws.rs.Produces;
49 import javax.ws.rs.core.Context;
50 import javax.ws.rs.core.MediaType;
51 import javax.ws.rs.core.Response;
52 import org.apache.commons.lang3.tuple.ImmutablePair;
53 import org.glassfish.jersey.media.multipart.FormDataParam;
54 import org.jetbrains.annotations.NotNull;
55 import org.openecomp.sdc.be.components.impl.ArtifactTypeImportManager;
56 import org.openecomp.sdc.be.components.impl.CapabilityTypeImportManager;
57 import org.openecomp.sdc.be.components.impl.CategoriesImportManager;
58 import org.openecomp.sdc.be.components.impl.ComponentInstanceBusinessLogic;
59 import org.openecomp.sdc.be.components.impl.DataTypeImportManager;
60 import org.openecomp.sdc.be.components.impl.GroupTypeImportManager;
61 import org.openecomp.sdc.be.components.impl.InterfaceLifecycleTypeImportManager;
62 import org.openecomp.sdc.be.components.impl.PolicyTypeImportManager;
63 import org.openecomp.sdc.be.components.impl.RelationshipTypeImportManager;
64 import org.openecomp.sdc.be.components.impl.ResourceImportManager;
65 import org.openecomp.sdc.be.components.impl.aaf.AafPermission;
66 import org.openecomp.sdc.be.components.impl.aaf.PermissionAllowed;
67 import org.openecomp.sdc.be.components.impl.model.ToscaTypeImportData;
68 import org.openecomp.sdc.be.config.BeEcompErrorManager;
69 import org.openecomp.sdc.be.dao.api.ActionStatus;
70 import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
71 import org.openecomp.sdc.be.datatypes.tosca.ToscaDataDefinition;
72 import org.openecomp.sdc.be.impl.ComponentsUtils;
73 import org.openecomp.sdc.be.impl.ServletUtils;
74 import org.openecomp.sdc.be.model.DataTypeDefinition;
75 import org.openecomp.sdc.be.model.GroupTypeDefinition;
76 import org.openecomp.sdc.be.model.PolicyTypeDefinition;
77 import org.openecomp.sdc.be.model.RelationshipTypeDefinition;
78 import org.openecomp.sdc.be.model.User;
79 import org.openecomp.sdc.be.model.normatives.ToscaTypeMetadata;
80 import org.openecomp.sdc.common.api.Constants;
81 import org.openecomp.sdc.common.datastructure.FunctionalInterfaces.ConsumerFourParam;
82 import org.openecomp.sdc.common.datastructure.FunctionalInterfaces.ConsumerTwoParam;
83 import org.openecomp.sdc.common.datastructure.Wrapper;
84 import org.openecomp.sdc.common.log.wrappers.Logger;
85 import org.openecomp.sdc.exception.ResponseFormat;
86 import org.springframework.stereotype.Controller;
87
88 @Loggable(prepend = true, value = Loggable.DEBUG, trim = false)
89 @Path("/v1/catalog/uploadType")
90 @Consumes(MediaType.MULTIPART_FORM_DATA)
91 @Produces(MediaType.APPLICATION_JSON)
92 @Tag(name = "SDCE-2 APIs")
93 @Server(url = "/sdc2/rest")
94 @Controller
95 public class TypesUploadServlet extends AbstractValidationsServlet {
96
97     private static final String CREATE = "Create ";
98     private static final String START_HANDLE_REQUEST_OF = "Start handle request of {}";
99     private static final String CREATE_FAILED_WITH_EXCEPTION = "create {} failed with exception:";
100     private static final Logger log = Logger.getLogger(TypesUploadServlet.class);
101     private final CapabilityTypeImportManager capabilityTypeImportManager;
102     private final InterfaceLifecycleTypeImportManager interfaceLifecycleTypeImportManager;
103     private final CategoriesImportManager categoriesImportManager;
104     private final DataTypeImportManager dataTypeImportManager;
105     private final GroupTypeImportManager groupTypeImportManager;
106     private final PolicyTypeImportManager policyTypeImportManager;
107     private final RelationshipTypeImportManager relationshipTypeImportManager;
108     private final ArtifactTypeImportManager artifactTypeImportManager;
109
110     @Inject
111     public TypesUploadServlet(ComponentInstanceBusinessLogic componentInstanceBL,
112                               ComponentsUtils componentsUtils, ServletUtils servletUtils, ResourceImportManager resourceImportManager,
113                               CapabilityTypeImportManager capabilityTypeImportManager,
114                               InterfaceLifecycleTypeImportManager interfaceLifecycleTypeImportManager,
115                               CategoriesImportManager categoriesImportManager, DataTypeImportManager dataTypeImportManager,
116                               GroupTypeImportManager groupTypeImportManager, PolicyTypeImportManager policyTypeImportManager,
117                               RelationshipTypeImportManager relationshipTypeImportManager, ArtifactTypeImportManager artifactTypeImportManager) {
118         super(componentInstanceBL, componentsUtils, servletUtils, resourceImportManager);
119         this.capabilityTypeImportManager = capabilityTypeImportManager;
120         this.interfaceLifecycleTypeImportManager = interfaceLifecycleTypeImportManager;
121         this.categoriesImportManager = categoriesImportManager;
122         this.dataTypeImportManager = dataTypeImportManager;
123         this.groupTypeImportManager = groupTypeImportManager;
124         this.policyTypeImportManager = policyTypeImportManager;
125         this.relationshipTypeImportManager = relationshipTypeImportManager;
126         this.artifactTypeImportManager = artifactTypeImportManager;
127     }
128
129     @POST
130     @Path("/capability")
131     @Operation(description = "Create Capability Type from yaml", method = "POST", summary = "Returns created Capability Type", responses = {
132         @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
133         @ApiResponse(responseCode = "201", description = "Capability Type created"),
134         @ApiResponse(responseCode = "403", description = "Restricted operation"),
135         @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
136         @ApiResponse(responseCode = "409", description = "Capability Type already exist")})
137     @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
138     public Response uploadCapabilityType(@Parameter(description = "FileInputStream") @FormDataParam("capabilityTypeZip") File file,
139                                          @Context final HttpServletRequest request, @HeaderParam("USER_ID") String creator,
140                                          @Parameter(description = "model name") @FormDataParam("model") String modelName,
141                                          @Parameter(description = "includeToModelImport") @FormDataParam("includeToModelImport") boolean includeToModelDefaultImports) {
142         ConsumerFourParam<Wrapper<Response>, String, String, Boolean> createElementsMethod = (responseWrapper, ymlPayload, model, includeToModelImport) ->
143             createElementsType(responseWrapper, () -> capabilityTypeImportManager.createCapabilityTypes(ymlPayload, modelName,
144                 includeToModelDefaultImports));
145         return uploadElementTypeServletLogic(createElementsMethod, file, request, creator, NodeTypeEnum.CapabilityType.name(), modelName,
146             includeToModelDefaultImports);
147     }
148
149     @POST
150     @Path("/relationship")
151     @Operation(description = "Create Relationship Type from yaml", method = "POST", summary = "Returns created Relationship Type", responses = {
152         @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
153         @ApiResponse(responseCode = "201", description = "Relationship Type created"),
154         @ApiResponse(responseCode = "403", description = "Restricted operation"),
155         @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
156         @ApiResponse(responseCode = "409", description = "Relationship Type already exist")})
157     @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
158     public Response uploadRelationshipType(@Parameter(description = "FileInputStream") @FormDataParam("relationshipTypeZip") File file,
159                                            @Context final HttpServletRequest request, @HeaderParam("USER_ID") String creator,
160                                            @Parameter(description = "model name") @FormDataParam("model") String modelName,
161                                            @Parameter(description = "includeToModelImport") @FormDataParam("includeToModelImport") boolean includeToModelDefaultImports) {
162         return uploadElementTypeServletLogic(this::createRelationshipTypes, file, request, creator, NodeTypeEnum.RelationshipType.getName(),
163             modelName, includeToModelDefaultImports);
164     }
165
166     @POST
167     @Path("/interfaceLifecycle")
168     @Operation(description = "Create Interface Lyfecycle Type from yaml", method = "POST", summary = "Returns created Interface Lifecycle Type", responses = {
169         @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
170         @ApiResponse(responseCode = "201", description = "Interface Lifecycle Type created"),
171         @ApiResponse(responseCode = "403", description = "Restricted operation"),
172         @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
173         @ApiResponse(responseCode = "409", description = "Interface Lifecycle Type already exist")})
174     @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
175     public Response uploadInterfaceLifecycleType(@Parameter(description = "FileInputStream") @FormDataParam("interfaceLifecycleTypeZip") File file,
176                                                  @Context final HttpServletRequest request, @HeaderParam("USER_ID") String creator,
177                                                  @Parameter(description = "model name") @FormDataParam("model") String modelName,
178                                                  @Parameter(description = "includeToModelImport") @FormDataParam("includeToModelImport") boolean includeToModelDefaultImports) {
179         ConsumerTwoParam<Wrapper<Response>, String> createElementsMethod = (responseWrapper, ymlPayload) ->
180             createElementsType(responseWrapper, () -> interfaceLifecycleTypeImportManager.createLifecycleTypes(ymlPayload, modelName,
181                 includeToModelDefaultImports));
182         return uploadElementTypeServletLogic(createElementsMethod, file, request, creator, "Interface Types");
183     }
184
185     @POST
186     @Path("/artifactTypes")
187     @Operation(description = "Create Tosca Artifact types from yaml", method = "POST", summary = "Returns created Tosca artifact types", responses = {
188         @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
189         @ApiResponse(responseCode = "201", description = "Tosca Artifact types created"),
190         @ApiResponse(responseCode = "403", description = "Restricted operation"),
191         @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
192         @ApiResponse(responseCode = "409", description = "Tosca Artifact Type already exist")})
193     @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
194     public Response uploadArtifactTypes(@Parameter(description = "Zip file containing a yaml with the TOSCA artifact types definition")
195                                         @FormDataParam("artifactsZip") File file,
196                                         @Parameter(description = "model name") @FormDataParam("model") String modelName,
197                                         @Context final HttpServletRequest request, @HeaderParam("USER_ID") String creator,
198                                         @Parameter(description = "A flag to add types to the default imports")
199                                         @FormDataParam("includeToModelImport") boolean includeToModelDefaultImports) {
200         final ConsumerTwoParam<Wrapper<Response>, String> createElementsMethod = (responseWrapper, ymlPayload) ->
201             createElementsType(responseWrapper,
202                 () -> artifactTypeImportManager.createArtifactTypes(ymlPayload, modelName, includeToModelDefaultImports));
203         return uploadElementTypeServletLogic(createElementsMethod, file, request, creator, NodeTypeEnum.ArtifactType.getName());
204     }
205
206     @POST
207     @Path("/categories")
208     @Operation(description = "Create Categories from yaml", method = "POST", summary = "Returns created categories", responses = {
209         @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
210         @ApiResponse(responseCode = "201", description = "Categories created"),
211         @ApiResponse(responseCode = "403", description = "Restricted operation"),
212         @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
213         @ApiResponse(responseCode = "409", description = "Category already exist")})
214     @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
215     public Response uploadCategories(@Parameter(description = "FileInputStream") @FormDataParam("categoriesZip") File file,
216                                      @Context final HttpServletRequest request, @HeaderParam("USER_ID") String creator) {
217         ConsumerTwoParam<Wrapper<Response>, String> createElementsMethod = (responseWrapper, ymlPayload) ->
218             createElementsType(responseWrapper, () -> categoriesImportManager.createCategories(ymlPayload));
219         return uploadElementTypeServletLogic(createElementsMethod, file, request, creator, "categories");
220     }
221
222     @POST
223     @Path("/datatypes")
224     @Operation(description = "Create Data Types from zip", method = "POST", summary = "Returns created data types", responses = {
225         @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
226         @ApiResponse(responseCode = "201", description = "Data types created"),
227         @ApiResponse(responseCode = "403", description = "Restricted operation"),
228         @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
229         @ApiResponse(responseCode = "409", description = "Data types already exist")})
230     @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
231     public Response uploadDataTypes(@Parameter(description = "FileInputStream") @FormDataParam("dataTypesZip") File file,
232                                     @Context final HttpServletRequest request, @HeaderParam("USER_ID") String creator,
233                                     @Parameter(description = "model name") @FormDataParam("model") String modelName,
234                                     @Parameter(description = "includeToModelImport") @FormDataParam("includeToModelImport") boolean includeToModelDefaultImports) {
235         return uploadElementTypeServletLogic(this::createDataTypes, file, request, creator, NodeTypeEnum.DataType.getName(), modelName,
236             includeToModelDefaultImports);
237     }
238
239     @POST
240     @Path("/datatypesyaml")
241     @Operation(description = "Create Data Types from yaml", method = "POST", summary = "Returns created data types", responses = {
242         @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
243         @ApiResponse(responseCode = "201", description = "Data types created"),
244         @ApiResponse(responseCode = "403", description = "Restricted operation"),
245         @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
246         @ApiResponse(responseCode = "409", description = "Data types already exist")})
247     @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
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     @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
265     public Response uploadGroupTypes(@Parameter(description = "toscaTypeMetadata") @FormDataParam("toscaTypeMetadata") String toscaTypesMetaData,
266                                      @Parameter(description = "model name") @FormDataParam("model") String modelName,
267                                      @Parameter(description = "FileInputStream") @FormDataParam("groupTypesZip") File file,
268                                      @Context final HttpServletRequest request, @HeaderParam("USER_ID") String creator,
269                                      @Parameter(description = "includeToModelImport") @FormDataParam("includeToModelImport") boolean includeToModelDefaultImports) {
270         Map<String, ToscaTypeMetadata> typesMetadata = getTypesMetadata(toscaTypesMetaData);
271         return uploadTypesWithMetaData(this::createGroupTypes, typesMetadata, file, request, creator, NodeTypeEnum.GroupType.getName(), modelName,
272             includeToModelDefaultImports);
273     }
274
275     @POST
276     @Path("/policytypes")
277     @Operation(description = "Create PolicyTypes from yaml", method = "POST", summary = "Returns created policy types", responses = {
278         @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
279         @ApiResponse(responseCode = "201", description = "policy types created"),
280         @ApiResponse(responseCode = "403", description = "Restricted operation"),
281         @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
282         @ApiResponse(responseCode = "409", description = "policy types already exist")})
283     @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
284     public Response uploadPolicyTypes(@Parameter(description = "toscaTypeMetadata") @FormDataParam("toscaTypeMetadata") String toscaTypesMetaData,
285                                       @Parameter(description = "model name") @FormDataParam("model") String modelName,
286                                       @Parameter(description = "FileInputStream") @FormDataParam("policyTypesZip") File file,
287                                       @Context final HttpServletRequest request, @HeaderParam("USER_ID") String creator,
288                                       @Parameter(description = "includeToModelImport") @FormDataParam("includeToModelImport") boolean includeToModelDefaultImports) {
289         Map<String, ToscaTypeMetadata> typesMetadata = getTypesMetadata(toscaTypesMetaData);
290         return uploadTypesWithMetaData(this::createPolicyTypes, typesMetadata, file, request, creator, NodeTypeEnum.PolicyType.getName(), modelName,
291             includeToModelDefaultImports);
292     }
293
294     private Map<String, ToscaTypeMetadata> getTypesMetadata(String toscaTypesMetaData) {
295         return gson.fromJson(toscaTypesMetaData, new TypeToken<Map<String, ToscaTypeMetadata>>() {
296         }.getType());
297     }
298
299     private Response uploadElementTypeServletLogic(ConsumerTwoParam<Wrapper<Response>, String> createElementsMethod, File file,
300                                                    final HttpServletRequest request, String creator, String elementTypeName) {
301         init();
302         String userId = initHeaderParam(creator, request, Constants.USER_ID_HEADER);
303         try {
304             Wrapper<String> yamlStringWrapper = new Wrapper<>();
305             String url = request.getMethod() + " " + request.getRequestURI();
306             log.debug(START_HANDLE_REQUEST_OF, url);
307             Wrapper<Response> responseWrapper = doUploadTypeValidations(request, userId, file);
308             if (responseWrapper.isEmpty()) {
309                 fillZipContents(yamlStringWrapper, file);
310             }
311             if (responseWrapper.isEmpty()) {
312                 createElementsMethod.accept(responseWrapper, yamlStringWrapper.getInnerElement());
313             }
314             return responseWrapper.getInnerElement();
315         } catch (Exception e) {
316             log.debug(CREATE_FAILED_WITH_EXCEPTION, elementTypeName, e);
317             BeEcompErrorManager.getInstance().logBeRestApiGeneralError(CREATE + elementTypeName);
318             return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
319         }
320     }
321
322     private Response uploadElementTypeServletLogic(final ConsumerFourParam<Wrapper<Response>, String, String, Boolean> createElementsMethod,
323                                                    final File file, final HttpServletRequest request, final String creator,
324                                                    final String elementTypeName, final String modelName, final boolean includeToModelDefaultImports) {
325         init();
326         final String userId = initHeaderParam(creator, request, Constants.USER_ID_HEADER);
327         try {
328             final Wrapper<String> yamlStringWrapper = new Wrapper<>();
329             final String url = request.getMethod() + " " + request.getRequestURI();
330             log.debug(START_HANDLE_REQUEST_OF, url);
331             final Wrapper<Response> responseWrapper = doUploadTypeValidations(request, userId, file);
332             if (responseWrapper.isEmpty()) {
333                 fillZipContents(yamlStringWrapper, file);
334                 createElementsMethod.accept(responseWrapper, yamlStringWrapper.getInnerElement(), modelName, includeToModelDefaultImports);
335             }
336             return responseWrapper.getInnerElement();
337         } catch (final Exception e) {
338             log.debug(CREATE_FAILED_WITH_EXCEPTION, elementTypeName, e);
339             BeEcompErrorManager.getInstance().logBeRestApiGeneralError(CREATE + elementTypeName);
340             return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
341         }
342     }
343
344     private Response uploadElementTypeServletLogicYaml(final ConsumerFourParam<Wrapper<Response>, String, String, Boolean> createElementsMethod,
345                                                        final File file, final HttpServletRequest request, final String creator,
346                                                        final String elementTypeName, final String modelName,
347                                                        final boolean includeToModelDefaultImports) {
348         init();
349         final String userId = initHeaderParam(creator, request, Constants.USER_ID_HEADER);
350         try {
351             final String url = request.getMethod() + " " + request.getRequestURI();
352             log.debug(START_HANDLE_REQUEST_OF, url);
353             final Wrapper<Response> responseWrapper = doUploadTypeValidations(request, userId, file);
354             final String yamlAsString = getFileAsString(file);
355             if (responseWrapper.isEmpty()) {
356                 log.debug("received yaml: {}", yamlAsString);
357                 createElementsMethod.accept(responseWrapper, yamlAsString, modelName, includeToModelDefaultImports);
358             }
359
360             return responseWrapper.getInnerElement();
361         } catch (final Exception e) {
362             log.debug(CREATE_FAILED_WITH_EXCEPTION, elementTypeName, e);
363             BeEcompErrorManager.getInstance().logBeRestApiGeneralError(CREATE + elementTypeName);
364             return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
365         }
366     }
367
368     @NotNull
369     private String getFileAsString(File file) throws IOException {
370         try (final FileInputStream fl = new FileInputStream(file)) {
371             byte[] arr = new byte[(int) file.length()];
372             int read = fl.read(arr);
373             if (read > 0) {
374                 return new String(arr, StandardCharsets.UTF_8);
375             } else {
376                 throw new IOException(String.format("Failed to read bytes from '%s'", file.getName()));
377             }
378         }
379     }
380
381     private Wrapper<Response> doUploadTypeValidations(final HttpServletRequest request, String userId, File file) {
382         Wrapper<Response> responseWrapper = new Wrapper<>();
383         Wrapper<User> userWrapper = new Wrapper<>();
384         String url = request.getMethod() + " " + request.getRequestURI();
385         log.debug(START_HANDLE_REQUEST_OF, url);
386         validateUserExist(responseWrapper, userWrapper, userId);
387         if (responseWrapper.isEmpty()) {
388             validateUserRole(responseWrapper, userWrapper.getInnerElement());
389         }
390         if (responseWrapper.isEmpty()) {
391             validateDataNotNull(responseWrapper, file);
392         }
393         return responseWrapper;
394     }
395
396     private Response uploadTypesWithMetaData(ConsumerFourParam<Wrapper<Response>, ToscaTypeImportData, String, Boolean> createElementsMethod,
397                                              Map<String, ToscaTypeMetadata> typesMetaData, File file, final HttpServletRequest request,
398                                              String creator, String elementTypeName, String modelName, final boolean includeToModelDefaultImports) {
399         init();
400         String userId = initHeaderParam(creator, request, Constants.USER_ID_HEADER);
401         Wrapper<String> yamlStringWrapper = new Wrapper<>();
402         try {
403             Wrapper<Response> responseWrapper = doUploadTypeValidations(request, userId, file);
404             if (responseWrapper.isEmpty()) {
405                 fillZipContents(yamlStringWrapper, file);
406             }
407             if (responseWrapper.isEmpty()) {
408                 ToscaTypeImportData toscaTypeImportData = new ToscaTypeImportData(yamlStringWrapper.getInnerElement(), typesMetaData);
409                 createElementsMethod.accept(responseWrapper, toscaTypeImportData, modelName, includeToModelDefaultImports);
410             }
411             return responseWrapper.getInnerElement();
412         } catch (Exception e) {
413             log.debug(CREATE_FAILED_WITH_EXCEPTION, elementTypeName, e);
414             BeEcompErrorManager.getInstance().logBeRestApiGeneralError(CREATE + elementTypeName);
415             return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
416         }
417     }
418
419     private <T> void createElementsType(Wrapper<Response> responseWrapper, Supplier<Either<T, ResponseFormat>> elementsCreater) {
420         Either<T, ResponseFormat> eitherResult = elementsCreater.get();
421         if (eitherResult.isRight()) {
422             responseWrapper.setInnerElement(buildErrorResponse(eitherResult.right().value()));
423         } else {
424             try {
425                 Response response = buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.CREATED),
426                     RepresentationUtils.toRepresentation(eitherResult.left().value()));
427                 responseWrapper.setInnerElement(response);
428             } catch (Exception e) {
429                 responseWrapper.setInnerElement(buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR)));
430                 log.error("#createElementsType - json serialization failed with error: ", e);
431             }
432         }
433     }
434
435     // data types
436     private void createDataTypes(Wrapper<Response> responseWrapper, String dataTypesYml, final String modelName,
437                                  final boolean includeToModelDefaultImports) {
438         final Supplier<Either<List<ImmutablePair<DataTypeDefinition, Boolean>>, ResponseFormat>> generateElementTypeFromYml = () ->
439             dataTypeImportManager.createDataTypes(dataTypesYml, modelName, includeToModelDefaultImports);
440         buildStatusForElementTypeCreate(responseWrapper, generateElementTypeFromYml, ActionStatus.DATA_TYPE_ALREADY_EXIST,
441             NodeTypeEnum.DataType.name());
442     }
443
444     // group types
445     private void createGroupTypes(Wrapper<Response> responseWrapper, ToscaTypeImportData toscaTypeImportData, String modelName,
446                                   final boolean includeToModelDefaultImports) {
447         final Supplier<Either<List<ImmutablePair<GroupTypeDefinition, Boolean>>, ResponseFormat>> generateElementTypeFromYml = () ->
448             groupTypeImportManager.createGroupTypes(toscaTypeImportData, modelName, includeToModelDefaultImports);
449         buildStatusForElementTypeCreate(responseWrapper, generateElementTypeFromYml, ActionStatus.GROUP_TYPE_ALREADY_EXIST,
450             NodeTypeEnum.GroupType.name());
451     }
452
453     // policy types
454     private void createPolicyTypes(Wrapper<Response> responseWrapper, ToscaTypeImportData toscaTypeImportData, String modelName,
455                                    final boolean includeToModelDefaultImports) {
456         final Supplier<Either<List<ImmutablePair<PolicyTypeDefinition, Boolean>>, ResponseFormat>> generateElementTypeFromYml = () ->
457             policyTypeImportManager.createPolicyTypes(toscaTypeImportData, modelName, includeToModelDefaultImports);
458         buildStatusForElementTypeCreate(responseWrapper, generateElementTypeFromYml, ActionStatus.POLICY_TYPE_ALREADY_EXIST,
459             NodeTypeEnum.PolicyType.name());
460     }
461
462     // data types
463     private <T extends ToscaDataDefinition> void buildStatusForElementTypeCreate(Wrapper<Response> responseWrapper,
464                                                                                  Supplier<Either<List<ImmutablePair<T, Boolean>>, ResponseFormat>> generateElementTypeFromYml,
465                                                                                  ActionStatus alreadyExistStatus, String elementTypeName) {
466         Either<List<ImmutablePair<T, Boolean>>, ResponseFormat> eitherResult = generateElementTypeFromYml.get();
467         if (eitherResult.isRight()) {
468             responseWrapper.setInnerElement(buildErrorResponse(eitherResult.right().value()));
469         } else {
470
471             try {
472                 final List<ImmutablePair<T, Boolean>> list = eitherResult.left().value();
473                 ActionStatus status = ActionStatus.OK;
474                 if (list != null) {
475                     // Group result by the right value - true or false.
476                     // I.e., get the number of data types which are new and which are old.
477                     final Map<Boolean, List<ImmutablePair<T, Boolean>>> collect =
478                         list.stream().collect(Collectors.groupingBy(ImmutablePair<T, Boolean>::getRight));
479                     if (collect != null) {
480                         Set<Boolean> keySet = collect.keySet();
481                         if (keySet.size() == 1) {
482                             Boolean isNew = keySet.iterator().next();
483                             if (Boolean.TRUE.equals(isNew)) {
484                                 // all data types created at the first time
485                                 status = ActionStatus.CREATED;
486                             } else {
487                                 // All data types already exists
488                                 status = alreadyExistStatus;
489                             }
490                         }
491                     }
492                 }
493                 final Object representation = RepresentationUtils.toRepresentation(eitherResult.left().value());
494                 responseWrapper.setInnerElement(buildOkResponse(getComponentsUtils().getResponseFormat(status), representation));
495             } catch (IOException e) {
496                 BeEcompErrorManager.getInstance().logBeRestApiGeneralError(CREATE + elementTypeName);
497                 log.debug("failed to convert {} to json", elementTypeName, e);
498                 responseWrapper.setInnerElement(buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR)));
499             }
500         }
501     }
502
503     // relationship types
504     private void createRelationshipTypes(final Wrapper<Response> responseWrapper,
505                                          final String relationshipTypesYml,
506                                          final String modelName,
507                                          final boolean includeToModelDefaultImports) {
508         final Supplier<Either<List<ImmutablePair<RelationshipTypeDefinition, Boolean>>, ResponseFormat>> generateElementTypeFromYml = () -> relationshipTypeImportManager
509             .createRelationshipTypes(relationshipTypesYml, modelName, includeToModelDefaultImports);
510         buildStatusForElementTypeCreate(responseWrapper, generateElementTypeFromYml, ActionStatus.RELATIONSHIP_TYPE_ALREADY_EXIST,
511             NodeTypeEnum.RelationshipType.name());
512     }
513 }