Support for adding artifact types 87/125087/5
authoraribeiro <anderson.ribeiro@est.tech>
Tue, 19 Oct 2021 08:11:16 +0000 (09:11 +0100)
committerAndr� Schmid <andre.schmid@est.tech>
Tue, 2 Nov 2021 18:11:49 +0000 (18:11 +0000)
Issue-ID: SDC-3763
Change-Id: Ideb63cbb3eb4e383adebaa11de49e91414a2c9a7
Signed-off-by: aribeiro <anderson.ribeiro@est.tech>
24 files changed:
catalog-be/src/main/docker/backend/chef-repo/cookbooks/sdc-catalog-be/files/default/error-configuration.yaml
catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ArtifactTypeImportManager.java [new file with mode: 0644]
catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ArtifactsBusinessLogic.java
catalog-be/src/main/java/org/openecomp/sdc/be/impl/ComponentsUtils.java
catalog-be/src/main/java/org/openecomp/sdc/be/servlets/TypesFetchServlet.java
catalog-be/src/main/java/org/openecomp/sdc/be/servlets/TypesUploadServlet.java
catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ArtifactBusinessLogicTest.java
catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ArtifactTypeImportManagerTest.java [new file with mode: 0644]
catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ArtifactsBusinessLogicTest.java
catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ResourceBusinessLogicTest.java
catalog-be/src/test/java/org/openecomp/sdc/be/servlets/TypesFetchServletTest.java
catalog-be/src/test/java/org/openecomp/sdc/be/servlets/TypesUploadServletTest.java
catalog-be/src/test/resources/types/artifactTypes.yml [new file with mode: 0644]
catalog-be/src/test/resources/types/artifactTypes.zip [new file with mode: 0644]
catalog-dao/src/main/java/org/openecomp/sdc/be/dao/api/ActionStatus.java
catalog-dao/src/main/java/org/openecomp/sdc/be/dao/graph/GraphElementFactory.java
catalog-dao/src/main/java/org/openecomp/sdc/be/resources/data/ArtifactTypeData.java [new file with mode: 0644]
catalog-model/src/main/java/org/openecomp/sdc/be/model/ArtifactTypeDefinition.java [new file with mode: 0644]
catalog-model/src/main/java/org/openecomp/sdc/be/model/normatives/ElementTypeEnum.java
catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/api/IArtifactTypeOperation.java [new file with mode: 0644]
catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/ArtifactTypeOperation.java [new file with mode: 0644]
catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/UniqueIdBuilder.java
common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/ArtifactTypeDataDefinition.java [new file with mode: 0644]
common-be/src/main/java/org/openecomp/sdc/be/datatypes/enums/NodeTypeEnum.java

index cfde6b4..af517c5 100644 (file)
@@ -2617,4 +2617,20 @@ errors:
         code: 400,
         message: "Invalid node_types TOSCA yaml",
         messageId: "SVC4161"
+    }
+
+    #---------SVC4162-----------------------------
+    # %1 - The janusgraph status
+    FAILED_CREATE_ARTIFACTS_TYPES: {
+        code: 500,
+        message: "Failed to create artifact types with status '%1'.",
+        messageId: "SVC4162"
+    }
+
+    #---------SVC4163-----------------------------
+    # %1 - The janusgraph status
+    ARTIFACT_TYPE_ALREADY_EXIST: {
+        code: 409,
+        message: "Artifact type '%1' already exist.",
+        messageId: "SVC4163"
     }
\ No newline at end of file
diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ArtifactTypeImportManager.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ArtifactTypeImportManager.java
new file mode 100644 (file)
index 0000000..e6ff100
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2021 Nordix Foundation
+ *  ================================================================================
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *  SPDX-License-Identifier: Apache-2.0
+ *  ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.sdc.be.components.impl;
+
+import fj.data.Either;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import org.apache.commons.lang3.StringUtils;
+import org.openecomp.sdc.be.dao.api.ActionStatus;
+import org.openecomp.sdc.be.impl.ComponentsUtils;
+import org.openecomp.sdc.be.model.ArtifactTypeDefinition;
+import org.openecomp.sdc.be.model.normatives.ElementTypeEnum;
+import org.openecomp.sdc.be.model.operations.impl.ArtifactTypeOperation;
+import org.openecomp.sdc.be.utils.TypeUtils;
+import org.openecomp.sdc.exception.ResponseFormat;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+@Component("artifactTypeImportManager")
+public class ArtifactTypeImportManager {
+
+    private final ArtifactTypeOperation artifactTypeOperation;
+    private final ComponentsUtils componentsUtils;
+    private final CommonImportManager commonImportManager;;
+
+    @Autowired
+    public ArtifactTypeImportManager(final ArtifactTypeOperation artifactTypeOperation, final ComponentsUtils componentsUtils,
+                                     final CommonImportManager commonImportManager) {
+        this.artifactTypeOperation = artifactTypeOperation;
+        this.componentsUtils = componentsUtils;
+        this.commonImportManager = commonImportManager;
+    }
+
+    public Either<List<ArtifactTypeDefinition>, ResponseFormat> createArtifactTypes(final String artifactTypesYml,
+                                                                                    final String modelName,
+                                                                                    final boolean includeToModelDefaultImports) {
+        if (StringUtils.isNotEmpty(modelName)) {
+            artifactTypeOperation.validateModel(modelName);
+        }
+        final Either<List<ArtifactTypeDefinition>, ActionStatus> artifactTypes = createArtifactTypeFromYml(artifactTypesYml, modelName);
+        if (artifactTypes.isRight()) {
+            return Either.right(componentsUtils.getResponseFormat(artifactTypes.right().value()));
+        }
+        final List<ArtifactTypeDefinition> elementTypes = createArtifactTypesByDao(artifactTypes.left().value());
+        if (includeToModelDefaultImports) {
+            commonImportManager.addTypesToDefaultImports(ElementTypeEnum.ARTIFACT_TYPE, artifactTypesYml, modelName);
+        }
+        return Either.left(elementTypes);
+    }
+
+    private Either<List<ArtifactTypeDefinition>, ActionStatus> createArtifactTypeFromYml(
+            final String artifactTypesYml, final String modelName) {
+        final Either<List<ArtifactTypeDefinition>, ActionStatus> artifactTypes =
+                commonImportManager.createElementTypesFromYml(artifactTypesYml, this::createArtifactTypeDefinition);
+        if (artifactTypes.isLeft()) {
+            artifactTypes.left().value().forEach(artifactType -> artifactType.setModel(modelName));
+            return artifactTypes;
+        }
+        return artifactTypes;
+    }
+
+    private List<ArtifactTypeDefinition> createArtifactTypesByDao(
+            final List<ArtifactTypeDefinition> artifactTypes) {
+        final List<ArtifactTypeDefinition> createdTypes = new ArrayList<>();
+        artifactTypes.forEach(type -> createdTypes.add(artifactTypeOperation.createArtifactType(type)));
+        return createdTypes;
+    }
+
+    private ArtifactTypeDefinition createArtifactTypeDefinition(final String type,
+            final Map<String, Object> toscaJson) {
+        final ArtifactTypeDefinition artifactType = new ArtifactTypeDefinition();
+        artifactType.setType(type);
+        if (toscaJson != null) {
+            commonImportManager.setField(toscaJson, TypeUtils.ToscaTagNamesEnum.DESCRIPTION.getElementName(),
+                    artifactType::setDescription);
+            commonImportManager.setField(toscaJson, TypeUtils.ToscaTagNamesEnum.DERIVED_FROM.getElementName(),
+                    artifactType::setDerivedFrom);
+            CommonImportManager.setProperties(toscaJson, artifactType::setProperties);
+        }
+        return artifactType;
+    }
+}
index a566d6c..7b21484 100644 (file)
@@ -88,6 +88,7 @@ import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
 import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum;
 import org.openecomp.sdc.be.info.ArtifactTemplateInfo;
 import org.openecomp.sdc.be.model.ArtifactDefinition;
+import org.openecomp.sdc.be.model.ArtifactTypeDefinition;
 import org.openecomp.sdc.be.model.Component;
 import org.openecomp.sdc.be.model.ComponentInstance;
 import org.openecomp.sdc.be.model.ComponentParametersView;
@@ -113,6 +114,7 @@ import org.openecomp.sdc.be.model.operations.api.IGroupTypeOperation;
 import org.openecomp.sdc.be.model.operations.api.IHeatParametersOperation;
 import org.openecomp.sdc.be.model.operations.api.IInterfaceLifecycleOperation;
 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
+import org.openecomp.sdc.be.model.operations.impl.ArtifactTypeOperation;
 import org.openecomp.sdc.be.model.operations.impl.DaoStatusConverter;
 import org.openecomp.sdc.be.model.operations.impl.InterfaceLifecycleOperation;
 import org.openecomp.sdc.be.model.operations.impl.UniqueIdBuilder;
@@ -179,6 +181,7 @@ public class ArtifactsBusinessLogic extends BaseBusinessLogic {
     private IElementOperation elementOperation;
     @javax.annotation.Resource
     private IHeatParametersOperation heatParametersOperation;
+    private final ArtifactTypeOperation artifactTypeOperation;
     private ArtifactCassandraDao artifactCassandraDao;
     private ToscaExportHandler toscaExportUtils;
     private CsarUtils csarUtils;
@@ -193,7 +196,8 @@ public class ArtifactsBusinessLogic extends BaseBusinessLogic {
                                   ArtifactsResolver artifactsResolver, IElementOperation elementDao, IGroupOperation groupOperation,
                                   IGroupInstanceOperation groupInstanceOperation, IGroupTypeOperation groupTypeOperation,
                                   InterfaceOperation interfaceOperation, InterfaceLifecycleOperation interfaceLifecycleTypeOperation,
-                                  ArtifactsOperations artifactToscaOperation) {
+                                  ArtifactsOperations artifactToscaOperation,
+                                  ArtifactTypeOperation artifactTypeOperation) {
         super(elementDao, groupOperation, groupInstanceOperation, groupTypeOperation, interfaceOperation, interfaceLifecycleTypeOperation,
             artifactToscaOperation);
         this.artifactCassandraDao = artifactCassandraDao;
@@ -202,6 +206,7 @@ public class ArtifactsBusinessLogic extends BaseBusinessLogic {
         this.lifecycleBusinessLogic = lifecycleBusinessLogic;
         this.userBusinessLogic = userBusinessLogic;
         this.artifactsResolver = artifactsResolver;
+        this.artifactTypeOperation = artifactTypeOperation;
     }
 
     public static <R> Either<Boolean, R> ifTrue(boolean predicate, Supplier<Either<Boolean, R>> ifTrue) {
@@ -4263,4 +4268,11 @@ public class ArtifactsBusinessLogic extends BaseBusinessLogic {
             return operation == CREATE || operation == LINK;
         }
     }
+
+    public Map<String, ArtifactTypeDefinition> getAllToscaArtifacts(final String modelName) {
+        if (StringUtils.isNotEmpty(modelName)) {
+            artifactTypeOperation.validateModel(modelName);
+        }
+        return artifactTypeOperation.getAllArtifactTypes(modelName);
+    }
 }
index af05825..5c2facc 100644 (file)
@@ -1564,4 +1564,31 @@ public class ComponentsUtils {
         return allDataTypes.left().value();
     }
 
+    public ActionStatus convertFromStorageResponseForArtifactType(final StorageOperationStatus storageResponse) {
+        ActionStatus responseEnum;
+        switch (storageResponse) {
+            case OK:
+                responseEnum = ActionStatus.OK;
+                break;
+            case CONNECTION_FAILURE:
+            case GRAPH_IS_LOCK:
+                responseEnum = ActionStatus.GENERAL_ERROR;
+                break;
+            case BAD_REQUEST:
+                responseEnum = ActionStatus.INVALID_CONTENT;
+                break;
+            case ENTITY_ALREADY_EXISTS:
+                responseEnum = ActionStatus.ARTIFACT_TYPE_ALREADY_EXIST;
+                break;
+            case SCHEMA_VIOLATION:
+                responseEnum = ActionStatus.ARTIFACT_TYPE_ALREADY_EXIST;
+                break;
+            default:
+                responseEnum = ActionStatus.GENERAL_ERROR;
+                break;
+        }
+        log.debug(CONVERT_STORAGE_RESPONSE_TO_ACTION_RESPONSE, storageResponse, responseEnum);
+        return responseEnum;
+    }
+
 }
index 0973984..7a229c8 100644 (file)
  */
 package org.openecomp.sdc.be.servlets;
 
+import com.jcabi.aspects.Loggable;
+import fj.data.Either;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.media.ArraySchema;
+import io.swagger.v3.oas.annotations.media.Content;
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.responses.ApiResponse;
+import io.swagger.v3.oas.annotations.servers.Server;
+import io.swagger.v3.oas.annotations.servers.Servers;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.tags.Tags;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.stream.Collectors;
-
 import javax.inject.Inject;
 import javax.servlet.ServletContext;
 import javax.servlet.http.HttpServletRequest;
@@ -36,8 +47,8 @@ import javax.ws.rs.QueryParam;
 import javax.ws.rs.core.Context;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
-
 import org.apache.commons.collections4.ListUtils;
+import org.openecomp.sdc.be.components.impl.ArtifactsBusinessLogic;
 import org.openecomp.sdc.be.components.impl.CapabilitiesBusinessLogic;
 import org.openecomp.sdc.be.components.impl.ComponentBusinessLogic;
 import org.openecomp.sdc.be.components.impl.ComponentInstanceBusinessLogic;
@@ -53,6 +64,7 @@ import org.openecomp.sdc.be.dao.api.ActionStatus;
 import org.openecomp.sdc.be.datamodel.api.HighestFilterEnum;
 import org.openecomp.sdc.be.datatypes.components.ResourceMetadataDataDefinition;
 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
+import org.openecomp.sdc.be.exception.BusinessException;
 import org.openecomp.sdc.be.impl.ComponentsUtils;
 import org.openecomp.sdc.be.impl.ServletUtils;
 import org.openecomp.sdc.be.model.CapabilityTypeDefinition;
@@ -64,25 +76,12 @@ import org.openecomp.sdc.be.model.User;
 import org.openecomp.sdc.be.user.UserBusinessLogic;
 import org.openecomp.sdc.common.api.Constants;
 import org.openecomp.sdc.common.datastructure.Wrapper;
+import org.openecomp.sdc.common.log.enums.EcompLoggerErrorCode;
 import org.openecomp.sdc.common.log.wrappers.Logger;
 import org.openecomp.sdc.common.util.ValidationUtils;
 import org.openecomp.sdc.exception.ResponseFormat;
 import org.springframework.stereotype.Controller;
 
-import com.jcabi.aspects.Loggable;
-
-import fj.data.Either;
-import io.swagger.v3.oas.annotations.Operation;
-import io.swagger.v3.oas.annotations.Parameter;
-import io.swagger.v3.oas.annotations.media.ArraySchema;
-import io.swagger.v3.oas.annotations.media.Content;
-import io.swagger.v3.oas.annotations.media.Schema;
-import io.swagger.v3.oas.annotations.responses.ApiResponse;
-import io.swagger.v3.oas.annotations.servers.Server;
-import io.swagger.v3.oas.annotations.servers.Servers;
-import io.swagger.v3.oas.annotations.tags.Tag;
-import io.swagger.v3.oas.annotations.tags.Tags;
-
 @Loggable(prepend = true, value = Loggable.DEBUG, trim = false)
 @Path("/v1/catalog")
 @Tags({@Tag(name = "SDCE-2 APIs")})
@@ -97,18 +96,21 @@ public class TypesFetchServlet extends AbstractValidationsServlet {
     private final CapabilitiesBusinessLogic capabilitiesBusinessLogic;
     private final InterfaceOperationBusinessLogic interfaceOperationBusinessLogic;
     private final ResourceBusinessLogic resourceBusinessLogic;
+    private final ArtifactsBusinessLogic artifactsBusinessLogic;
 
     @Inject
     public TypesFetchServlet(UserBusinessLogic userBusinessLogic, ComponentInstanceBusinessLogic componentInstanceBL, ComponentsUtils componentsUtils,
                              ServletUtils servletUtils, ResourceImportManager resourceImportManager, PropertyBusinessLogic propertyBusinessLogic,
                              RelationshipTypeBusinessLogic relationshipTypeBusinessLogic, CapabilitiesBusinessLogic capabilitiesBusinessLogic,
-                             InterfaceOperationBusinessLogic interfaceOperationBusinessLogic, ResourceBusinessLogic resourceBusinessLogic) {
+                             InterfaceOperationBusinessLogic interfaceOperationBusinessLogic, ResourceBusinessLogic resourceBusinessLogic,
+                             ArtifactsBusinessLogic artifactsBusinessLogic) {
         super(userBusinessLogic, componentInstanceBL, componentsUtils, servletUtils, resourceImportManager);
         this.propertyBusinessLogic = propertyBusinessLogic;
         this.relationshipTypeBusinessLogic = relationshipTypeBusinessLogic;
         this.capabilitiesBusinessLogic = capabilitiesBusinessLogic;
         this.interfaceOperationBusinessLogic = interfaceOperationBusinessLogic;
         this.resourceBusinessLogic = resourceBusinessLogic;
+        this.artifactsBusinessLogic = artifactsBusinessLogic;
     }
 
     @GET
@@ -313,6 +315,31 @@ public class TypesFetchServlet extends AbstractValidationsServlet {
         }
     }
 
+    @GET
+    @Path("/artifactTypes")
+    @Operation(description = "Get Tosca ArtifactTypes", method = "GET", summary = "Returns tosca artifact types", responses = {
+        @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
+        @ApiResponse(responseCode = "200", description = "Listing successful"),
+        @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
+        @ApiResponse(responseCode = "403", description = "Restricted operation"),
+        @ApiResponse(responseCode = "404", description = "Tosca Artifact Types not found")})
+    @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
+    public Response getAllToscaArtifactTypes(@Parameter(description = "Model name") @QueryParam("model") String model,
+                                             @Context final HttpServletRequest request, @HeaderParam("USER_ID") String creator) {
+        try {
+            return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), artifactsBusinessLogic.getAllToscaArtifacts(model));
+        } catch (final BusinessException e) {
+            throw e;
+        } catch (final Exception e) {
+            final var errorMsg = "Unexpected error while listing the Tosca Artifact types";
+            BeEcompErrorManager.getInstance().logBeRestApiGeneralError(errorMsg);
+            log.error(EcompLoggerErrorCode.UNKNOWN_ERROR, this.getClass().getName(), errorMsg, e);
+            return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
+        }
+
+    }
+
+
     private Either<Map<String, Component>, Response> getComponent(ComponentBusinessLogic resourceBL, boolean isAbstract, String userId) {
         Either<List<Component>, ResponseFormat> actionResponse;
         List<Component> componentList;
index 06738a8..fbd4801 100644 (file)
@@ -49,6 +49,7 @@ import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 import org.apache.commons.lang3.tuple.ImmutablePair;
 import org.glassfish.jersey.media.multipart.FormDataParam;
+import org.openecomp.sdc.be.components.impl.ArtifactTypeImportManager;
 import org.openecomp.sdc.be.components.impl.CapabilityTypeImportManager;
 import org.openecomp.sdc.be.components.impl.CategoriesImportManager;
 import org.openecomp.sdc.be.components.impl.ComponentInstanceBusinessLogic;
@@ -102,6 +103,7 @@ public class TypesUploadServlet extends AbstractValidationsServlet {
     private final GroupTypeImportManager groupTypeImportManager;
     private final PolicyTypeImportManager policyTypeImportManager;
     private final RelationshipTypeImportManager relationshipTypeImportManager;
+    private final ArtifactTypeImportManager artifactTypeImportManager;
 
     @Inject
     public TypesUploadServlet(UserBusinessLogic userBusinessLogic, ComponentInstanceBusinessLogic componentInstanceBL,
@@ -110,7 +112,7 @@ public class TypesUploadServlet extends AbstractValidationsServlet {
                               InterfaceLifecycleTypeImportManager interfaceLifecycleTypeImportManager,
                               CategoriesImportManager categoriesImportManager, DataTypeImportManager dataTypeImportManager,
                               GroupTypeImportManager groupTypeImportManager, PolicyTypeImportManager policyTypeImportManager,
-                              RelationshipTypeImportManager relationshipTypeImportManager) {
+                              RelationshipTypeImportManager relationshipTypeImportManager, ArtifactTypeImportManager artifactTypeImportManager) {
         super(userBusinessLogic, componentInstanceBL, componentsUtils, servletUtils, resourceImportManager);
         this.capabilityTypeImportManager = capabilityTypeImportManager;
         this.interfaceLifecycleTypeImportManager = interfaceLifecycleTypeImportManager;
@@ -119,6 +121,7 @@ public class TypesUploadServlet extends AbstractValidationsServlet {
         this.groupTypeImportManager = groupTypeImportManager;
         this.policyTypeImportManager = policyTypeImportManager;
         this.relationshipTypeImportManager = relationshipTypeImportManager;
+        this.artifactTypeImportManager = artifactTypeImportManager;
     }
 
     @POST
@@ -177,6 +180,26 @@ public class TypesUploadServlet extends AbstractValidationsServlet {
         return uploadElementTypeServletLogic(createElementsMethod, file, request, creator, "Interface Types");
     }
 
+    @POST
+    @Path("/artifactTypes")
+    @Operation(description = "Create Tosca Artifact types from yaml", method = "POST", summary = "Returns created Tosca artifact types", responses = {
+        @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
+        @ApiResponse(responseCode = "201", description = "Tosca Artifact types created"),
+        @ApiResponse(responseCode = "403", description = "Restricted operation"),
+        @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
+        @ApiResponse(responseCode = "409", description = "Tosca Artifact Type already exist")})
+    @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
+    public Response uploadArtifactTypes(@Parameter(description = "Zip file containing a yaml with the TOSCA artifact types definition")
+                                            @FormDataParam("artifactsZip") File file,
+                                        @Parameter(description = "model name") @FormDataParam("model") String modelName,
+                                        @Context final HttpServletRequest request, @HeaderParam("USER_ID") String creator,
+                                        @Parameter(description = "A flag to add types to the default imports")
+                                            @FormDataParam("includeToModelImport") boolean includeToModelDefaultImports) {
+        final ConsumerTwoParam<Wrapper<Response>, String> createElementsMethod = (responseWrapper, ymlPayload) ->
+            createElementsType(responseWrapper, () -> artifactTypeImportManager.createArtifactTypes(ymlPayload, modelName, includeToModelDefaultImports));
+        return uploadElementTypeServletLogic(createElementsMethod, file, request, creator, NodeTypeEnum.ArtifactType.getName());
+    }
+
     @POST
     @Path("/categories")
     @Operation(description = "Create Categories from yaml", method = "POST", summary = "Returns created categories", responses = {
index f1a1aaa..616d9e4 100644 (file)
 
 package org.openecomp.sdc.be.components.impl;
 
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.openecomp.sdc.be.components.impl.ArtifactsBusinessLogic.HEAT_ENV_NAME;
+import static org.openecomp.sdc.be.components.impl.ArtifactsBusinessLogic.HEAT_VF_ENV_NAME;
+
 import com.fasterxml.jackson.annotation.JsonInclude;
 import com.fasterxml.jackson.databind.DeserializationFeature;
 import com.fasterxml.jackson.databind.ObjectMapper;
@@ -28,6 +39,12 @@ import com.google.gson.Gson;
 import com.google.gson.GsonBuilder;
 import com.google.gson.JsonElement;
 import fj.data.Either;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 import java.util.Optional;
 import org.junit.Before;
 import org.junit.Test;
@@ -38,10 +55,10 @@ import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
 import org.mockito.junit.MockitoJUnitRunner;
 import org.openecomp.sdc.be.components.ArtifactsResolver;
-import org.openecomp.sdc.be.config.ArtifactConfigManager;
 import org.openecomp.sdc.be.components.lifecycle.LifecycleBusinessLogic;
 import org.openecomp.sdc.be.components.utils.ArtifactBuilder;
 import org.openecomp.sdc.be.components.utils.ObjectGenerator;
+import org.openecomp.sdc.be.config.ArtifactConfigManager;
 import org.openecomp.sdc.be.config.ArtifactConfiguration;
 import org.openecomp.sdc.be.config.ComponentType;
 import org.openecomp.sdc.be.dao.api.ActionStatus;
@@ -65,6 +82,7 @@ import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ToscaOperationFacade
 import org.openecomp.sdc.be.model.operations.api.IGraphLockOperation;
 import org.openecomp.sdc.be.model.operations.api.IInterfaceLifecycleOperation;
 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
+import org.openecomp.sdc.be.model.operations.impl.ArtifactTypeOperation;
 import org.openecomp.sdc.be.resources.data.DAOArtifactData;
 import org.openecomp.sdc.be.servlets.RepresentationUtils;
 import org.openecomp.sdc.be.tosca.CsarUtils;
@@ -74,24 +92,6 @@ import org.openecomp.sdc.common.api.ArtifactGroupTypeEnum;
 import org.openecomp.sdc.common.api.ArtifactTypeEnum;
 import org.openecomp.sdc.exception.ResponseFormat;
 
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyBoolean;
-import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-import static org.openecomp.sdc.be.components.impl.ArtifactsBusinessLogic.HEAT_ENV_NAME;
-import static org.openecomp.sdc.be.components.impl.ArtifactsBusinessLogic.HEAT_VF_ENV_NAME;
-
 @RunWith(MockitoJUnitRunner.class)
 public class ArtifactBusinessLogicTest extends BaseBusinessLogicMock{
 
@@ -122,10 +122,6 @@ public class ArtifactBusinessLogicTest extends BaseBusinessLogicMock{
     JanusGraphDao janusGraphDao;
     @Mock
     private IInterfaceLifecycleOperation interfaceLifecycleOperation;
-
-    // public static final InformationDeployedArtifactsBusinessLogic
-    // informationDeployedArtifactsBusinessLogic =
-    // Mockito.mock(InformationDeployedArtifactsBusinessLogic.class);
     @Mock
     private ToscaExportHandler toscaExportHandler;
     @Mock
@@ -134,13 +130,15 @@ public class ArtifactBusinessLogicTest extends BaseBusinessLogicMock{
     private LifecycleBusinessLogic lifecycleBusinessLogic;
     @Mock
     private ArtifactsResolver artifactsResolver;
+    @Mock
+    private ArtifactTypeOperation artifactTypeOperation;
 
     public static final Resource resource = Mockito.mock(Resource.class);
     private Gson gson = new GsonBuilder().setPrettyPrinting().create();
 
     @Before
     public void initMocks() {
-        MockitoAnnotations.initMocks(this);
+        MockitoAnnotations.openMocks(this);
         when(userBusinessLogic.getUser(eq("jh0003"), anyBoolean())).thenReturn(USER);
         when(resource.getResourceType()).thenReturn(ResourceTypeEnum.VFC);
     }
@@ -536,16 +534,6 @@ public class ArtifactBusinessLogicTest extends BaseBusinessLogicMock{
         assertThat(result.isLeft()).isTrue();
     }
 
-    private ArtifactsBusinessLogic getArtifactsBusinessLogic() {
-        ArtifactsBusinessLogic artifactsBusinessLogic = new ArtifactsBusinessLogic(artifactCassandraDao,
-            toscaExportHandler, csarUtils, lifecycleBusinessLogic,
-            userBusinessLogic, artifactsResolver, elementDao, groupOperation, groupInstanceOperation,
-            groupTypeOperation, interfaceOperation, interfaceLifecycleTypeOperation, artifactToscaOperation);
-        artifactsBusinessLogic.setGraphLockOperation(graphLockOperation);
-        artifactsBusinessLogic.setToscaOperationFacade(toscaOperationFacade);
-        return artifactsBusinessLogic;
-    }
-
     @Test
     public void buildArtifactPayloadWhenShouldLockAndNotInTransaction() {
         ArtifactDefinition artifactDefinition = new ArtifactDefinition();
diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ArtifactTypeImportManagerTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ArtifactTypeImportManagerTest.java
new file mode 100644 (file)
index 0000000..28a7e9c
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2021 Nordix Foundation
+ *  ================================================================================
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *  SPDX-License-Identifier: Apache-2.0
+ *  ============LICENSE_END=========================================================
+ */
+package org.openecomp.sdc.be.components.impl;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.hasSize;
+import static org.hamcrest.core.Is.is;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.when;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.Optional;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.openecomp.sdc.be.model.Model;
+import org.openecomp.sdc.be.model.operations.impl.ArtifactTypeOperation;
+import org.openecomp.sdc.be.model.operations.impl.ModelOperation;
+
+public class ArtifactTypeImportManagerTest {
+
+    @InjectMocks
+    private ArtifactTypeImportManager artifactTypeImportManager;
+    @Mock
+    private CommonImportManager commonImportManager;
+    @Mock
+    private ModelOperation modelOperation;
+    @Mock
+    private ArtifactTypeOperation artifactTypeOperation;
+
+    @BeforeEach
+    public void setUp() {
+        MockitoAnnotations.openMocks(this);
+    }
+
+    @Test
+    void createArtifactTypeFromYmlTest() throws IOException {
+        when(commonImportManager.createElementTypesFromYml(Mockito.anyString(), any())).thenCallRealMethod();
+        when(commonImportManager.createElementTypesFromToscaJsonMap(any(), any())).thenCallRealMethod();
+        when(artifactTypeOperation.createArtifactType(any())).thenCallRealMethod();
+        when(modelOperation.findModelByName("test")).thenReturn(Optional.of(new Model("test")));
+        final var result = artifactTypeImportManager
+            .createArtifactTypes(getArtifactsYml(), "test", false);
+        assertThat("The createElementTypesFromYml should be left", result.isLeft(), is(true));
+        final var artifactTypes = result.left().value();
+        assertThat("The artifact types list should have size", artifactTypes, hasSize(1));
+    }
+
+    private String getArtifactsYml() throws IOException {
+        return new String(Files.readAllBytes(Paths.get("src/test/resources/types/artifactTypes.yml")));
+    }
+}
index 1c680e5..14d00ef 100644 (file)
@@ -128,6 +128,7 @@ import org.openecomp.sdc.be.model.operations.api.IGraphLockOperation;
 import org.openecomp.sdc.be.model.operations.api.IInterfaceLifecycleOperation;
 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
 import org.openecomp.sdc.be.model.operations.impl.ArtifactOperation;
+import org.openecomp.sdc.be.model.operations.impl.ArtifactTypeOperation;
 import org.openecomp.sdc.be.model.operations.impl.UserAdminOperation;
 import org.openecomp.sdc.be.resources.data.DAOArtifactData;
 import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum;
@@ -197,6 +198,9 @@ public class ArtifactsBusinessLogicTest extends BaseBusinessLogicMock {
     private ToscaExportHandler toscaExportHandler;
     @Mock
     private LifecycleBusinessLogic lifecycleBusinessLogic;
+    @Mock
+    private ArtifactTypeOperation artifactTypeOperation;
+
     private Gson gson = new GsonBuilder().setPrettyPrinting().create();
 
     private static List<ArtifactType> getAllTypes() {
@@ -2441,7 +2445,7 @@ public class ArtifactsBusinessLogicTest extends BaseBusinessLogicMock {
             toscaExportHandler, csarUtils, lifecycleBusinessLogic,
             userBusinessLogic, artifactsResolver, elementDao, groupOperation, groupInstanceOperation,
             groupTypeOperation,
-            interfaceOperation, interfaceLifecycleTypeOperation, artifactToscaOperation);
+            interfaceOperation, interfaceLifecycleTypeOperation, artifactToscaOperation, artifactTypeOperation);
         artifactsBusinessLogic.setComponentsUtils(componentsUtils);
         return artifactsBusinessLogic;
     }
index 90c1864..0453dc7 100644 (file)
@@ -129,6 +129,7 @@ import org.openecomp.sdc.be.model.operations.api.IGroupOperation;
 import org.openecomp.sdc.be.model.operations.api.IGroupTypeOperation;
 import org.openecomp.sdc.be.model.operations.api.IInterfaceLifecycleOperation;
 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
+import org.openecomp.sdc.be.model.operations.impl.ArtifactTypeOperation;
 import org.openecomp.sdc.be.model.operations.impl.CsarOperation;
 import org.openecomp.sdc.be.model.operations.impl.GraphLockOperation;
 import org.openecomp.sdc.be.model.operations.impl.InterfaceLifecycleOperation;
@@ -214,6 +215,7 @@ public class ResourceBusinessLogicTest {
        private final ToscaExportHandler toscaExportHandler = Mockito.mock(ToscaExportHandler.class);
        private final PolicyTypeOperation policyTypeOperation = Mockito.mock(PolicyTypeOperation.class);
        private final PolicyBusinessLogic policyBusinessLogic = Mockito.mock(PolicyBusinessLogic.class);
+       private final ArtifactTypeOperation artifactTypeOperation = Mockito.mock(ArtifactTypeOperation.class);
        private final DataTypeBusinessLogic dataTypeBusinessLogic = Mockito.mock(DataTypeBusinessLogic.class);
        private final PolicyTypeBusinessLogic policyTypeBusinessLogic = Mockito.mock(PolicyTypeBusinessLogic.class);
 
@@ -231,7 +233,7 @@ public class ResourceBusinessLogicTest {
        ComponentsUtils componentsUtils =  new ComponentsUtils(Mockito.mock(AuditingManager.class));
        ArtifactsBusinessLogic artifactManager = new ArtifactsBusinessLogic(artifactCassandraDao, toscaExportHandler, csarUtils, lifecycleBl,
                        userBusinessLogic, artifactsResolver, elementDao, groupOperation, groupInstanceOperation, groupTypeOperation,
-                       interfaceOperation, interfaceLifecycleTypeOperation, artifactToscaOperation);
+                       interfaceOperation, interfaceLifecycleTypeOperation, artifactToscaOperation, artifactTypeOperation);
        CsarOperation csarOperation = Mockito.mock(CsarOperation.class);
        @InjectMocks
        CsarBusinessLogic csarBusinessLogic ;
index 2305cd3..ef4ec18 100644 (file)
 
 package org.openecomp.sdc.be.servlets;
 
+import static org.mockito.Mockito.mock;
+
+import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.core.Response;
 import org.junit.Test;
+import org.openecomp.sdc.be.components.impl.ArtifactsBusinessLogic;
 import org.openecomp.sdc.be.components.impl.CapabilitiesBusinessLogic;
 import org.openecomp.sdc.be.components.impl.ComponentInstanceBusinessLogic;
 import org.openecomp.sdc.be.components.impl.InterfaceOperationBusinessLogic;
@@ -32,12 +38,6 @@ import org.openecomp.sdc.be.impl.ComponentsUtils;
 import org.openecomp.sdc.be.impl.ServletUtils;
 import org.openecomp.sdc.be.user.UserBusinessLogic;
 
-import javax.servlet.ServletContext;
-import javax.servlet.http.HttpServletRequest;
-import javax.ws.rs.core.Response;
-
-import static org.mockito.Mockito.mock;
-
 public class TypesFetchServletTest {
 
        private TypesFetchServlet createTestSubject() {
@@ -51,10 +51,11 @@ public class TypesFetchServletTest {
                CapabilitiesBusinessLogic capabilitiesBusinessLogic = mock(CapabilitiesBusinessLogic.class);
                InterfaceOperationBusinessLogic interfaceOperationBusinessLogic = mock(InterfaceOperationBusinessLogic.class);
                ResourceBusinessLogic resourceBusinessLogic = mock(ResourceBusinessLogic.class);
+               ArtifactsBusinessLogic artifactsBusinessLogic = mock(ArtifactsBusinessLogic.class);
 
                return new TypesFetchServlet(userBusinessLogic, componentInstanceBL, componentsUtils, servletUtils,
                                resourceImportManager, propertyBusinessLogic, relationshipTypeBusinessLogic, capabilitiesBusinessLogic,
-                               interfaceOperationBusinessLogic, resourceBusinessLogic);
+                               interfaceOperationBusinessLogic, resourceBusinessLogic, artifactsBusinessLogic);
        }
 
        
index 0373aa2..ed9b9a4 100644 (file)
@@ -23,6 +23,8 @@ package org.openecomp.sdc.be.servlets;
 import static java.util.Collections.emptyList;
 import static java.util.Collections.emptyMap;
 import static org.junit.Assert.assertEquals;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.Mockito.when;
 
 import fj.data.Either;
@@ -56,6 +58,7 @@ import org.junit.jupiter.api.TestInstance.Lifecycle;
 import org.mockito.Mock;
 import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
+import org.openecomp.sdc.be.components.impl.ArtifactTypeImportManager;
 import org.openecomp.sdc.be.components.impl.CapabilityTypeImportManager;
 import org.openecomp.sdc.be.components.impl.CategoriesImportManager;
 import org.openecomp.sdc.be.components.impl.DataTypeImportManager;
@@ -124,6 +127,8 @@ class TypesUploadServletTest extends JerseyTest {
     private ComponentsUtils componentUtils;
     @Mock
     private ResponseFormat responseFormat;
+    @Mock
+    private ArtifactTypeImportManager artifactTypeImportManager;
 
     @BeforeAll
     public void setup() {
@@ -137,6 +142,7 @@ class TypesUploadServletTest extends JerseyTest {
         when(webApplicationContext.getBean(InterfaceLifecycleTypeImportManager.class)).thenReturn(interfaceLifecycleTypeImportManager);
         when(webApplicationContext.getBean(GroupTypeImportManager.class)).thenReturn(groupTypeImportManager);
         when(webApplicationContext.getBean(CategoriesImportManager.class)).thenReturn(categoriesImportManager);
+        when(webApplicationContext.getBean(ArtifactTypeImportManager.class)).thenReturn(artifactTypeImportManager);
         when(webApplicationContext.getBean(ServletUtils.class)).thenReturn(servletUtils);
         when(servletUtils.getComponentsUtils()).thenReturn(componentUtils);
         when(servletUtils.getUserAdmin()).thenReturn(userAdmin);
@@ -164,7 +170,7 @@ class TypesUploadServletTest extends JerseyTest {
     void creatingCapabilityTypeSuccessTest() {
         final ImmutablePair<CapabilityTypeDefinition, Boolean> immutablePair = new ImmutablePair<>(new CapabilityTypeDefinition(), true);
         final Either<List<ImmutablePair<CapabilityTypeDefinition, Boolean>>, ResponseFormat> either = Either.left(Arrays.asList(immutablePair));
-        when(capabilityTypeImportManager.createCapabilityTypes(Mockito.anyString(), Mockito.isNull(), Mockito.anyBoolean())).thenReturn(either);
+        when(capabilityTypeImportManager.createCapabilityTypes(anyString(), Mockito.isNull(), Mockito.anyBoolean())).thenReturn(either);
         final FileDataBodyPart filePart = new FileDataBodyPart("capabilityTypeZip", new File("src/test/resources/types/capabilityTypes.zip"));
         MultiPart multipartEntity = new FormDataMultiPart();
         multipartEntity.bodyPart(filePart);
@@ -178,7 +184,7 @@ class TypesUploadServletTest extends JerseyTest {
     @Test
     void creatingCapabilityType_Either_isRight_FailedTest() {
         final Either<List<ImmutablePair<CapabilityTypeDefinition, Boolean>>, ResponseFormat> either = Either.right(new ResponseFormat(500));
-        when(capabilityTypeImportManager.createCapabilityTypes(Mockito.anyString(), Mockito.isNull(), Mockito.anyBoolean())).thenReturn(either);
+        when(capabilityTypeImportManager.createCapabilityTypes(anyString(), Mockito.isNull(), Mockito.anyBoolean())).thenReturn(either);
         final FileDataBodyPart filePart = new FileDataBodyPart("capabilityTypeZip", new File("src/test/resources/types/capabilityTypes.zip"));
         MultiPart multipartEntity = new FormDataMultiPart();
         multipartEntity.bodyPart(filePart);
@@ -193,7 +199,7 @@ class TypesUploadServletTest extends JerseyTest {
     void creatingCapabilityTypeWithModelSuccessTest() {
         final ImmutablePair<CapabilityTypeDefinition, Boolean> immutablePair = new ImmutablePair<>(new CapabilityTypeDefinition(), true);
         final Either<List<ImmutablePair<CapabilityTypeDefinition, Boolean>>, ResponseFormat> either = Either.left(Arrays.asList(immutablePair));
-        when(capabilityTypeImportManager.createCapabilityTypes(Mockito.anyString(), Mockito.eq("testModel"), Mockito.anyBoolean())).thenReturn(
+        when(capabilityTypeImportManager.createCapabilityTypes(anyString(), Mockito.eq("testModel"), Mockito.anyBoolean())).thenReturn(
             either);
         final FileDataBodyPart filePart = new FileDataBodyPart("capabilityTypeZip", new File("src/test/resources/types/capabilityTypes.zip"));
         FormDataMultiPart multipartEntity = new FormDataMultiPart();
@@ -210,7 +216,7 @@ class TypesUploadServletTest extends JerseyTest {
     void creatingDataTypeSuccessTest() {
         final ImmutablePair<DataTypeDefinition, Boolean> immutablePair = new ImmutablePair<>(new DataTypeDefinition(), true);
         final Either<List<ImmutablePair<DataTypeDefinition, Boolean>>, ResponseFormat> either = Either.left(Arrays.asList(immutablePair));
-        when(dataTypeImportManager.createDataTypes(Mockito.anyString(), Mockito.isNull(), Mockito.anyBoolean())).thenReturn(either);
+        when(dataTypeImportManager.createDataTypes(anyString(), Mockito.isNull(), Mockito.anyBoolean())).thenReturn(either);
         final FileDataBodyPart filePart = new FileDataBodyPart("dataTypesZip", new File("src/test/resources/types/datatypes.zip"));
         MultiPart multipartEntity = new FormDataMultiPart();
         multipartEntity.bodyPart(filePart);
@@ -224,7 +230,7 @@ class TypesUploadServletTest extends JerseyTest {
     @Test
     void creatingDataType_Either_isRight_FailedTest() {
         final Either<List<ImmutablePair<DataTypeDefinition, Boolean>>, ResponseFormat> either = Either.right(new ResponseFormat(500));
-        when(dataTypeImportManager.createDataTypes(Mockito.anyString(), Mockito.isNull(), Mockito.anyBoolean())).thenReturn(either);
+        when(dataTypeImportManager.createDataTypes(anyString(), Mockito.isNull(), Mockito.anyBoolean())).thenReturn(either);
         final FileDataBodyPart filePart = new FileDataBodyPart("dataTypesZip", new File("src/test/resources/types/datatypes.zip"));
         MultiPart multipartEntity = new FormDataMultiPart();
         multipartEntity.bodyPart(filePart);
@@ -239,7 +245,7 @@ class TypesUploadServletTest extends JerseyTest {
     void creatingDataType_AlreadyExists_FailedTest() {
         final ImmutablePair<DataTypeDefinition, Boolean> immutablePair = new ImmutablePair<>(new DataTypeDefinition(), false);
         final Either<List<ImmutablePair<DataTypeDefinition, Boolean>>, ResponseFormat> either = Either.left(Arrays.asList(immutablePair));
-        when(dataTypeImportManager.createDataTypes(Mockito.anyString(), Mockito.isNull(), Mockito.anyBoolean())).thenReturn(either);
+        when(dataTypeImportManager.createDataTypes(anyString(), Mockito.isNull(), Mockito.anyBoolean())).thenReturn(either);
         final FileDataBodyPart filePart = new FileDataBodyPart("dataTypesZip", new File("src/test/resources/types/datatypes.zip"));
         MultiPart multipartEntity = new FormDataMultiPart();
         multipartEntity.bodyPart(filePart);
@@ -254,7 +260,7 @@ class TypesUploadServletTest extends JerseyTest {
     void creatingDataTypeWithModelSuccessTest() {
         final ImmutablePair<DataTypeDefinition, Boolean> immutablePair = new ImmutablePair<>(new DataTypeDefinition(), true);
         final Either<List<ImmutablePair<DataTypeDefinition, Boolean>>, ResponseFormat> either = Either.left(Arrays.asList(immutablePair));
-        when(dataTypeImportManager.createDataTypes(Mockito.anyString(), Mockito.eq("testModel"), Mockito.anyBoolean())).thenReturn(either);
+        when(dataTypeImportManager.createDataTypes(anyString(), Mockito.eq("testModel"), Mockito.anyBoolean())).thenReturn(either);
         final FileDataBodyPart filePart = new FileDataBodyPart("dataTypesZip", new File("src/test/resources/types/datatypes.zip"));
         FormDataMultiPart multipartEntity = new FormDataMultiPart();
         multipartEntity.bodyPart(filePart);
@@ -270,7 +276,7 @@ class TypesUploadServletTest extends JerseyTest {
     void creatingRelationshipTypeSuccessTest() {
         final ImmutablePair<RelationshipTypeDefinition, Boolean> immutablePair = new ImmutablePair<>(new RelationshipTypeDefinition(), true);
         final Either<List<ImmutablePair<RelationshipTypeDefinition, Boolean>>, ResponseFormat> either = Either.left(Arrays.asList(immutablePair));
-        when(relationshipTypeImportManager.createRelationshipTypes(Mockito.anyString(), Mockito.isNull(), Mockito.anyBoolean())).thenReturn(either);
+        when(relationshipTypeImportManager.createRelationshipTypes(anyString(), Mockito.isNull(), Mockito.anyBoolean())).thenReturn(either);
         final FileDataBodyPart filePart = new FileDataBodyPart("relationshipTypeZip", new File("src/test/resources/types/relationship.zip"));
         MultiPart multipartEntity = new FormDataMultiPart();
         multipartEntity.bodyPart(filePart);
@@ -285,7 +291,7 @@ class TypesUploadServletTest extends JerseyTest {
     void creatingRelationshipType_AlreadyExists_FailedTest() {
         final ImmutablePair<RelationshipTypeDefinition, Boolean> immutablePair = new ImmutablePair<>(new RelationshipTypeDefinition(), false);
         final Either<List<ImmutablePair<RelationshipTypeDefinition, Boolean>>, ResponseFormat> either = Either.left(Arrays.asList(immutablePair));
-        when(relationshipTypeImportManager.createRelationshipTypes(Mockito.anyString(), Mockito.isNull(), Mockito.anyBoolean())).thenReturn(either);
+        when(relationshipTypeImportManager.createRelationshipTypes(anyString(), Mockito.isNull(), Mockito.anyBoolean())).thenReturn(either);
         final FileDataBodyPart filePart = new FileDataBodyPart("relationshipTypeZip", new File("src/test/resources/types/relationship.zip"));
         MultiPart multipartEntity = new FormDataMultiPart();
         multipartEntity.bodyPart(filePart);
@@ -300,7 +306,7 @@ class TypesUploadServletTest extends JerseyTest {
     void creatingRelationshipTypeWithModelSuccessTest() {
         final ImmutablePair<RelationshipTypeDefinition, Boolean> immutablePair = new ImmutablePair<>(new RelationshipTypeDefinition(), true);
         final Either<List<ImmutablePair<RelationshipTypeDefinition, Boolean>>, ResponseFormat> either = Either.left(Arrays.asList(immutablePair));
-        when(relationshipTypeImportManager.createRelationshipTypes(Mockito.anyString(), Mockito.eq("testModel"), Mockito.anyBoolean())).thenReturn(
+        when(relationshipTypeImportManager.createRelationshipTypes(anyString(), Mockito.eq("testModel"), Mockito.anyBoolean())).thenReturn(
             either);
         final FileDataBodyPart filePart = new FileDataBodyPart("relationshipTypeZip", new File("src/test/resources/types/relationship.zip"));
         FormDataMultiPart multipartEntity = new FormDataMultiPart();
@@ -366,7 +372,7 @@ class TypesUploadServletTest extends JerseyTest {
     void creatingInterfaceLifecycleTypeSuccessTest() {
         final ImmutablePair<InterfaceDefinition, Boolean> immutablePair = new ImmutablePair<>(new InterfaceDefinition(), true);
         final Either<List<InterfaceDefinition>, ResponseFormat> either = Either.left(emptyList());
-        when(interfaceLifecycleTypeImportManager.createLifecycleTypes(Mockito.anyString(), Mockito.isNull(), Mockito.anyBoolean()))
+        when(interfaceLifecycleTypeImportManager.createLifecycleTypes(anyString(), Mockito.isNull(), Mockito.anyBoolean()))
             .thenReturn(either);
         final FileDataBodyPart filePart = new FileDataBodyPart("interfaceLifecycleTypeZip",
             new File("src/test/resources/types/interfaceLifecycleTypes.zip"));
@@ -382,7 +388,7 @@ class TypesUploadServletTest extends JerseyTest {
     @Test
     void creatingInterfaceLifecycleType_Either_isRight_FailedTest() {
         final Either<List<InterfaceDefinition>, ResponseFormat> either = Either.right(new ResponseFormat(500));
-        when(interfaceLifecycleTypeImportManager.createLifecycleTypes(Mockito.anyString(), Mockito.isNull(), Mockito.anyBoolean()))
+        when(interfaceLifecycleTypeImportManager.createLifecycleTypes(anyString(), Mockito.isNull(), Mockito.anyBoolean()))
             .thenReturn(either);
         final FileDataBodyPart filePart = new FileDataBodyPart("interfaceLifecycleTypeZip",
             new File("src/test/resources/types/interfaceLifecycleTypes.zip"));
@@ -399,7 +405,7 @@ class TypesUploadServletTest extends JerseyTest {
     void creatingInterfaceLifecycleTypeWithModelSuccessTest() {
         final ImmutablePair<InterfaceDefinition, Boolean> immutablePair = new ImmutablePair<>(new InterfaceDefinition(), true);
         final Either<List<InterfaceDefinition>, ResponseFormat> either = Either.left(emptyList());
-        when(interfaceLifecycleTypeImportManager.createLifecycleTypes(Mockito.anyString(), Mockito.eq("testModel"), Mockito.anyBoolean()))
+        when(interfaceLifecycleTypeImportManager.createLifecycleTypes(anyString(), Mockito.eq("testModel"), Mockito.anyBoolean()))
             .thenReturn(either);
         final FileDataBodyPart filePart = new FileDataBodyPart("interfaceLifecycleTypeZip",
             new File("src/test/resources/types/interfaceLifecycleTypes.zip"));
@@ -465,7 +471,7 @@ class TypesUploadServletTest extends JerseyTest {
     @Test
     void creatingCategoriesTypeSuccessTest() {
         final Either<Map<String, List<CategoryDefinition>>, ResponseFormat> either = Either.left(emptyMap());
-        when(categoriesImportManager.createCategories(Mockito.anyString())).thenReturn(either);
+        when(categoriesImportManager.createCategories(anyString())).thenReturn(either);
         final FileDataBodyPart filePart = new FileDataBodyPart("categoriesZip", new File("src/test/resources/types/categoryTypes.zip"));
         MultiPart multipartEntity = new FormDataMultiPart();
         multipartEntity.bodyPart(filePart);
@@ -476,6 +482,30 @@ class TypesUploadServletTest extends JerseyTest {
         assertEquals(HttpStatus.CREATED_201, response.getStatus());
     }
 
+    @Test
+    void creatingArtifactTypeSuccessTest() {
+        when(artifactTypeImportManager.createArtifactTypes(anyString(), anyString(), anyBoolean()))
+            .thenReturn(Either.left(emptyList()));
+        final FileDataBodyPart filePart = new FileDataBodyPart("artifactsZip", new File("src/test/resources/types/artifactTypes.zip"));
+        final FormDataMultiPart multipartEntity = new FormDataMultiPart();
+        multipartEntity.bodyPart(filePart);
+        multipartEntity.field("model", "testModel");
+        final Response response = target().path("/v1/catalog/uploadType/artifactTypes").request(MediaType.APPLICATION_JSON)
+            .post(Entity.entity(multipartEntity, MediaType.MULTIPART_FORM_DATA), Response.class);
+        assertEquals(HttpStatus.CREATED_201, response.getStatus());
+    }
+
+    @Test
+    void creatingArtifactTypeFailTest() {
+        when(artifactTypeImportManager.createArtifactTypes(anyString(), anyString(), anyBoolean()))
+            .thenReturn(Either.right(new ResponseFormat(500)));
+        final FormDataMultiPart multipartEntity = new FormDataMultiPart();
+        multipartEntity.field("model", "testModel");
+        final Response response = target().path("/v1/catalog/uploadType/artifactTypes").request(MediaType.APPLICATION_JSON)
+            .post(Entity.entity(multipartEntity, MediaType.MULTIPART_FORM_DATA), Response.class);
+        assertEquals(HttpStatus.INTERNAL_SERVER_ERROR_500, response.getStatus());
+    }
+
     @Override
     protected void configureClient(ClientConfig config) {
         config.register(MultiPartFeature.class);
@@ -489,7 +519,7 @@ class TypesUploadServletTest extends JerseyTest {
         final TypesUploadServlet typesUploadServlet = new TypesUploadServlet(null, null, componentUtils,
             servletUtils, null, capabilityTypeImportManager, interfaceLifecycleTypeImportManager,
             categoriesImportManager, dataTypeImportManager,
-            groupTypeImportManager, policyTypeImportManager, relationshipTypeImportManager);
+            groupTypeImportManager, policyTypeImportManager, relationshipTypeImportManager, artifactTypeImportManager);
         final ResourceConfig resourceConfig = new ResourceConfig().register(typesUploadServlet);
 
         resourceConfig.register(MultiPartFeature.class);
diff --git a/catalog-be/src/test/resources/types/artifactTypes.yml b/catalog-be/src/test/resources/types/artifactTypes.yml
new file mode 100644 (file)
index 0000000..9d21830
--- /dev/null
@@ -0,0 +1,10 @@
+tosca.artifacts.Implementation.nfv.artifactTest:
+  derived_from: tosca.artifacts.Implementation
+  description: artifacts for Mistral workflows
+  mime_type: application/x-yaml
+  file_ext: [ yaml ]
+  properties:
+    prop_A:
+      type: string
+    prop_B:
+      type: string
diff --git a/catalog-be/src/test/resources/types/artifactTypes.zip b/catalog-be/src/test/resources/types/artifactTypes.zip
new file mode 100644 (file)
index 0000000..2e3ed3b
Binary files /dev/null and b/catalog-be/src/test/resources/types/artifactTypes.zip differ
index 800fc67..1862f85 100644 (file)
@@ -126,7 +126,8 @@ public enum ActionStatus {
     ABSTRACT, NORMAL,
     //including default imports in CSAR related
     CSAR_TOSCA_IMPORTS_ERROR,
+    //ArtifactType
+    ARTIFACT_TYPE_ALREADY_EXIST, FAILED_CREATE_ARTIFACTS_TYPES,
     //TOSCA node types
     INVALID_NODE_TYPES_YAML
-
 }
index 1c500e7..11de2a3 100644 (file)
@@ -20,6 +20,7 @@
 package org.openecomp.sdc.be.dao.graph;
 
 import java.util.Map;
+
 import org.openecomp.sdc.be.dao.graph.datatype.GraphElementTypeEnum;
 import org.openecomp.sdc.be.dao.graph.datatype.GraphNode;
 import org.openecomp.sdc.be.dao.graph.datatype.GraphRelation;
@@ -29,6 +30,7 @@ import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
 import org.openecomp.sdc.be.resources.data.AdditionalInfoParameterData;
 import org.openecomp.sdc.be.resources.data.AnnotationTypeData;
 import org.openecomp.sdc.be.resources.data.ArtifactData;
+import org.openecomp.sdc.be.resources.data.ArtifactTypeData;
 import org.openecomp.sdc.be.resources.data.AttributeData;
 import org.openecomp.sdc.be.resources.data.AttributeValueData;
 import org.openecomp.sdc.be.resources.data.CapabilityData;
@@ -260,6 +262,9 @@ public class GraphElementFactory {
                 case Model:
                     element = clazz.cast(new ModelData(properties));
                     break;
+                case ArtifactType:
+                    element = clazz.cast(new ArtifactTypeData(properties));
+                    break;
                 default:
                     break;
             }
diff --git a/catalog-dao/src/main/java/org/openecomp/sdc/be/resources/data/ArtifactTypeData.java b/catalog-dao/src/main/java/org/openecomp/sdc/be/resources/data/ArtifactTypeData.java
new file mode 100644 (file)
index 0000000..e138016
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2021 Nordix Foundation
+ *  ================================================================================
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *  SPDX-License-Identifier: Apache-2.0
+ *  ============LICENSE_END=========================================================
+ */
+package org.openecomp.sdc.be.resources.data;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.openecomp.sdc.be.dao.graph.datatype.GraphNode;
+import org.openecomp.sdc.be.dao.neo4j.GraphPropertiesDictionary;
+import org.openecomp.sdc.be.datatypes.elements.ArtifactTypeDataDefinition;
+import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
+
+public class ArtifactTypeData extends GraphNode {
+
+    private ArtifactTypeDataDefinition artifactTypeDefinition;
+
+    public ArtifactTypeData() {
+        super(NodeTypeEnum.Interface);
+        artifactTypeDefinition = new ArtifactTypeDataDefinition();
+    }
+
+    public ArtifactTypeData(ArtifactTypeDataDefinition artifactTypeDefinition) {
+        super(NodeTypeEnum.ArtifactType);
+        this.artifactTypeDefinition = artifactTypeDefinition;
+    }
+
+    public ArtifactTypeData(Map<String, Object> properties) {
+        this();
+        artifactTypeDefinition.setUniqueId((String) properties.get(GraphPropertiesDictionary.UNIQUE_ID.getProperty()));
+        artifactTypeDefinition.setType((String) properties.get(GraphPropertiesDictionary.TYPE.getProperty()));
+        artifactTypeDefinition.setDescription((String) properties.get(GraphPropertiesDictionary.DESCRIPTION.getProperty()));
+        artifactTypeDefinition.setCreationDate((Long) properties.get(GraphPropertiesDictionary.CREATION_DATE.getProperty()));
+        artifactTypeDefinition.setLastUpdated((Long) properties.get(GraphPropertiesDictionary.LAST_UPDATE_DATE.getProperty()));
+    }
+
+    public ArtifactTypeDataDefinition getArtifactTypeDataDefinition() {
+        return artifactTypeDefinition;
+    }
+
+    public void setArtifactTypeDataDefinition(ArtifactTypeDataDefinition artifactTypeDefinition) {
+        this.artifactTypeDefinition = artifactTypeDefinition;
+    }
+
+    @Override
+    public String getUniqueId() {
+        return artifactTypeDefinition.getUniqueId();
+    }
+
+    @Override
+    public Map<String, Object> toGraphMap() {
+        Map<String, Object> map = new HashMap<>();
+        addIfExists(map, GraphPropertiesDictionary.UNIQUE_ID, artifactTypeDefinition.getUniqueId());
+        addIfExists(map, GraphPropertiesDictionary.TYPE, artifactTypeDefinition.getType());
+        addIfExists(map, GraphPropertiesDictionary.CREATION_DATE, artifactTypeDefinition.getCreationDate());
+        addIfExists(map, GraphPropertiesDictionary.LAST_UPDATE_DATE, artifactTypeDefinition.getLastUpdated());
+        addIfExists(map, GraphPropertiesDictionary.DESCRIPTION, artifactTypeDefinition.getDescription());
+        return map;
+    }
+}
diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/ArtifactTypeDefinition.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/ArtifactTypeDefinition.java
new file mode 100644 (file)
index 0000000..692e9b9
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2021 Nordix Foundation
+ *  ================================================================================
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *  SPDX-License-Identifier: Apache-2.0
+ *  ============LICENSE_END=========================================================
+ */
+package org.openecomp.sdc.be.model;
+
+import java.util.List;
+
+import org.openecomp.sdc.be.datatypes.elements.ArtifactTypeDataDefinition;
+
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+import lombok.ToString;
+
+@Getter
+@Setter
+@NoArgsConstructor
+@ToString
+public class ArtifactTypeDefinition extends ArtifactTypeDataDefinition {
+
+    private List<PropertyDefinition> properties;
+
+    public ArtifactTypeDefinition(final ArtifactTypeDataDefinition artifactTypeDataDefinition) {
+        super(artifactTypeDataDefinition);
+    }
+
+    public ArtifactTypeDefinition(final ArtifactTypeDefinition artifactTypeDataDefinition) {
+        super(artifactTypeDataDefinition);
+        this.setName(artifactTypeDataDefinition.getName());
+        this.setDerivedFrom(artifactTypeDataDefinition.getDerivedFrom());
+        this.setUniqueId(artifactTypeDataDefinition.getUniqueId());
+        this.setDescription(artifactTypeDataDefinition.getDescription());
+        this.setModel(artifactTypeDataDefinition.getModel());
+    }
+
+}
index 57ca559..e421e61 100644 (file)
@@ -32,7 +32,8 @@ public enum ElementTypeEnum {
     DATA_TYPE("data_types"),
     CAPABILITY_TYPE("capability_types"),
     INTERFACE_LIFECYCLE_TYPE("interface_types"),
-    RELATIONSHIP_TYPE("relationship_types");
+    RELATIONSHIP_TYPE("relationship_types"),
+    ARTIFACT_TYPE("artifact_types");
 
     private final String toscaEntryName;
 }
diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/api/IArtifactTypeOperation.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/api/IArtifactTypeOperation.java
new file mode 100644 (file)
index 0000000..22e6f00
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2021 Nordix Foundation
+ *  ================================================================================
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *  SPDX-License-Identifier: Apache-2.0
+ *  ============LICENSE_END=========================================================
+ */
+package org.openecomp.sdc.be.model.operations.api;
+
+import java.util.Map;
+
+import org.openecomp.sdc.be.model.ArtifactTypeDefinition;
+
+public interface IArtifactTypeOperation {
+
+    ArtifactTypeDefinition createArtifactType(final ArtifactTypeDefinition artifactType);
+
+    ArtifactTypeDefinition createArtifactType(final ArtifactTypeDefinition artifactType, final boolean inTransaction);
+
+    Map<String, ArtifactTypeDefinition> getAllArtifactTypes(final String model);
+
+}
diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/ArtifactTypeOperation.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/ArtifactTypeOperation.java
new file mode 100644 (file)
index 0000000..4b1dcfb
--- /dev/null
@@ -0,0 +1,356 @@
+/*
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2021 Nordix Foundation
+ *  ================================================================================
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *  SPDX-License-Identifier: Apache-2.0
+ *  ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.sdc.be.model.operations.impl;
+
+import fj.data.Either;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.stream.Collectors;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.tuple.ImmutablePair;
+import org.openecomp.sdc.be.dao.api.ActionStatus;
+import org.openecomp.sdc.be.dao.graph.datatype.GraphEdge;
+import org.openecomp.sdc.be.dao.graph.datatype.GraphNode;
+import org.openecomp.sdc.be.dao.graph.datatype.GraphRelation;
+import org.openecomp.sdc.be.dao.janusgraph.JanusGraphGenericDao;
+import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus;
+import org.openecomp.sdc.be.dao.neo4j.GraphEdgeLabels;
+import org.openecomp.sdc.be.dao.neo4j.GraphPropertiesDictionary;
+import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
+import org.openecomp.sdc.be.model.ArtifactTypeDefinition;
+import org.openecomp.sdc.be.model.PropertyDefinition;
+import org.openecomp.sdc.be.model.jsonjanusgraph.operations.exception.ModelOperationExceptionSupplier;
+import org.openecomp.sdc.be.model.jsonjanusgraph.operations.exception.OperationException;
+import org.openecomp.sdc.be.model.operations.api.DerivedFromOperation;
+import org.openecomp.sdc.be.model.operations.api.IArtifactTypeOperation;
+import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
+import org.openecomp.sdc.be.resources.data.ArtifactTypeData;
+import org.openecomp.sdc.be.resources.data.ModelData;
+import org.openecomp.sdc.be.resources.data.PropertyData;
+import org.openecomp.sdc.be.resources.data.UniqueIdData;
+import org.openecomp.sdc.common.log.enums.EcompLoggerErrorCode;
+import org.openecomp.sdc.common.log.wrappers.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+/**
+ * This class is responsible for handling all operations for the TOSCA artifact types
+ */
+@Component("artifact-type-operation")
+public class ArtifactTypeOperation implements IArtifactTypeOperation {
+
+    private static final Logger LOGGER = Logger.getLogger(ArtifactTypeOperation.class.getName());
+
+    private final JanusGraphGenericDao janusGraphGenericDao;
+    private final PropertyOperation propertyOperation;
+    private final DerivedFromOperation derivedFromOperation;
+    private final ModelOperation modelOperation;
+
+    @Autowired
+    public ArtifactTypeOperation(final JanusGraphGenericDao janusGraphGenericDao,
+                                 final PropertyOperation propertyOperation,
+                                 final DerivedFromOperation derivedFromOperation,
+                                 final ModelOperation modelOperation) {
+        this.janusGraphGenericDao = janusGraphGenericDao;
+        this.propertyOperation = propertyOperation;
+        this.derivedFromOperation = derivedFromOperation;
+        this.modelOperation = modelOperation;
+    }
+
+    /**
+     * Creates a TOSCA artifact types
+     * @param artifactType the TOSCA artifact types definition to be created
+     * @return the created TOSCA artifact types definition
+     */
+    @Override
+    public ArtifactTypeDefinition createArtifactType(final ArtifactTypeDefinition artifactType) {
+        return createArtifactType(artifactType, false);
+    }
+
+    @Override
+    public ArtifactTypeDefinition createArtifactType(final ArtifactTypeDefinition artifactType,
+                                                     final boolean inTransaction) {
+        Either<ArtifactTypeData, JanusGraphOperationStatus> createNodeResult = null;
+        try {
+            artifactType.setUniqueId(UniqueIdBuilder.buildArtifactTypeUid(artifactType.getModel(), artifactType.getType()));
+            final ArtifactTypeData artifactTypeData = new ArtifactTypeData(artifactType);
+            final Either<ArtifactTypeData, JanusGraphOperationStatus> existArtifact = janusGraphGenericDao
+                .getNode(artifactTypeData.getUniqueIdKey(), artifactTypeData.getUniqueId(), ArtifactTypeData.class);
+            if (!existArtifact.isLeft()) {
+                createNodeResult = janusGraphGenericDao.createNode(artifactTypeData, ArtifactTypeData.class);
+                if (createNodeResult.isRight()) {
+                    final JanusGraphOperationStatus operationStatus = createNodeResult.right().value();
+                    LOGGER.error(EcompLoggerErrorCode.DATA_ERROR,
+                        "Failed to add artifact type {} to graph. Operation status {}", artifactType.getType(), operationStatus);
+                    throw new OperationException(ActionStatus.GENERAL_ERROR,
+                        String.format("Failed to create artifact type %s with status %s", artifactType.getType(),
+                            DaoStatusConverter.convertJanusGraphStatusToStorageStatus(operationStatus)));
+                }
+                addPropertiesToArtifactType(artifactType);
+                addModelRelation(artifactType);
+                addDerivedFromRelation(artifactType);
+                return convertArtifactDataDefinition(createNodeResult.left().value());
+            } else {
+                LOGGER.debug("Artifact type already exist {}", artifactType);
+                return convertArtifactDataDefinition(existArtifact.left().value());
+            }
+        } finally {
+            if (!inTransaction) {
+                if (createNodeResult == null || createNodeResult.isRight()) {
+                    LOGGER.debug("Rollback on graph.");
+                    janusGraphGenericDao.rollback();
+                } else {
+                    janusGraphGenericDao.commit();
+                }
+            }
+        }
+    }
+
+    /**
+     * Finds all TOSCA artifact types applicable to the given model name
+     * @param model model name
+     * @return all the TOSCA artifact types found
+     */
+    @Override
+    public Map<String, ArtifactTypeDefinition> getAllArtifactTypes(final String model) {
+        final Either<List<ArtifactTypeData>, JanusGraphOperationStatus> artifactTypes =
+            janusGraphGenericDao.getByCriteriaForModel(NodeTypeEnum.ArtifactType, Collections.emptyMap(), model, ArtifactTypeData.class);
+        if (artifactTypes.isRight()) {
+            if (JanusGraphOperationStatus.NOT_FOUND == artifactTypes.right().value()) {
+                return Collections.emptyMap();
+            }
+            throw new OperationException(ActionStatus.GENERAL_ERROR,
+                String.format("Failed to find artifact on JanusGraph with status %s",
+                    DaoStatusConverter.convertJanusGraphStatusToStorageStatus(artifactTypes.right().value())));
+        }
+        final Map<String, ArtifactTypeDefinition> artifactTypeDefinitionTypes = new HashMap<>();
+        final List<ArtifactTypeDefinition> artifactTypeList = artifactTypes.left().value().stream()
+            .map(this::convertArtifactDataDefinition)
+            .filter(artifactTypeDefinition -> artifactTypeDefinition.getUniqueId().equalsIgnoreCase(UniqueIdBuilder
+                .buildArtifactTypeUid(artifactTypeDefinition.getModel(), artifactTypeDefinition.getType())))
+            .collect(Collectors.toList());
+        for (final ArtifactTypeDefinition type : artifactTypeList) {
+            artifactTypeDefinitionTypes.put(type.getUniqueId(), type);
+        }
+        return artifactTypeDefinitionTypes;
+    }
+
+    /**
+     * Coverts the given artifact type data into a TOSCA artifact types definition
+     * @param artifactTypeData artifact type data representation
+     * @return the TOSCA artifact types definition
+     */
+    private ArtifactTypeDefinition convertArtifactDataDefinition(final ArtifactTypeData artifactTypeData) {
+        LOGGER.debug("The object returned after create tosca artifact type is {}", artifactTypeData);
+        final ArtifactTypeDefinition artifactType = new ArtifactTypeDefinition(artifactTypeData.getArtifactTypeDataDefinition());
+        final var modelAssociatedToArtifactOptional = getModelAssociatedToArtifact(artifactTypeData.getUniqueId());
+        if (!modelAssociatedToArtifactOptional.isEmpty()) {
+            artifactType.setModel(modelAssociatedToArtifactOptional.get());
+        }
+        artifactType.setType(artifactTypeData.getArtifactTypeDataDefinition().getType());
+        final ArtifactTypeData derivedFromNode = fillDerivedFrom(artifactType);
+        fillProperties(artifactType, derivedFromNode);
+        return artifactType;
+    }
+
+    /**
+     * Finds an artifact type data on JanusGraph based on the given parameters
+     * @param type the artifact type derived from
+     * @param model the model name
+     * @return the optional artifact type data found
+     */
+    private Optional<ArtifactTypeData> getLatestArtifactTypeByType(final String type, final String model) {
+        final Map<String, Object> mapCriteria = new HashMap<>();
+        mapCriteria.put(GraphPropertiesDictionary.TYPE.getProperty(), type);
+        final Either<List<ArtifactTypeData>, JanusGraphOperationStatus> result = janusGraphGenericDao.getByCriteriaForModel(NodeTypeEnum.ArtifactType,
+            mapCriteria, model, ArtifactTypeData.class);
+        if (result.isRight()) {
+            final JanusGraphOperationStatus status = result.right().value();
+            if (JanusGraphOperationStatus.NOT_FOUND == status) {
+                return Optional.empty();
+            }
+            throw new OperationException(ActionStatus.GENERAL_ERROR,
+                String.format("Failed to find artifact by type on JanusGraph with status %s",
+                    DaoStatusConverter.convertJanusGraphStatusToStorageStatus(status)));
+        }
+        return Optional.of(result.left().value().get(0));
+    }
+
+    /**
+     * Creates the derivedFrom relation for the given TOSCA artifact types
+     * @param artifactType the TOSCA artifact types definition
+     */
+    private void addDerivedFromRelation(final ArtifactTypeDefinition artifactType) {
+        final String derivedFrom = artifactType.getDerivedFrom();
+        final String artifactId = artifactType.getUniqueId();
+        if (derivedFrom.isEmpty()) {
+            return;
+        }
+        final var getArtifactTypeOptional = getLatestArtifactTypeByType(derivedFrom, artifactType.getModel());
+        if (getArtifactTypeOptional.isPresent()) {
+            if (derivedFromOperation.addDerivedFromRelation(artifactId, getArtifactTypeOptional.get().getUniqueId(),
+                NodeTypeEnum.ArtifactType).isRight()) {
+                throw new OperationException(ActionStatus.GENERAL_ERROR,
+                    String.format("Failed creating derivedFrom relation for artifact type %s", artifactType.getType()));
+            }
+        }
+    }
+
+    /**
+     * Adds a property definition to the given TOSCA artifact types definition
+     * @param artifactType the TOSCA artifact types
+     */
+    private void addPropertiesToArtifactType(final ArtifactTypeDefinition artifactType) {
+        final List<PropertyDefinition> properties = artifactType.getProperties();
+        final Either<Map<String, PropertyData>, JanusGraphOperationStatus> addPropertiesToArtifactType =
+            propertyOperation.addPropertiesToElementType(artifactType.getUniqueId(), NodeTypeEnum.ArtifactType, properties);
+        if (addPropertiesToArtifactType.isRight()) {
+            throw new OperationException(ActionStatus.GENERAL_ERROR,
+                String.format("Failed creating properties for artifact type %s with status %s",
+                    artifactType.getType(), DaoStatusConverter.convertJanusGraphStatusToStorageStatus(addPropertiesToArtifactType.right().value())));
+        }
+    }
+
+    /**
+     * Creates an edge between the given TOSCA artifact types and it`s model
+     * @param artifactType the TOSCA artifact types
+     */
+    private void addModelRelation(final ArtifactTypeDefinition artifactType) {
+        final String model = artifactType.getModel();
+        if (StringUtils.isNotEmpty(model)) {
+            final GraphNode from = new UniqueIdData(NodeTypeEnum.Model, UniqueIdBuilder.buildModelUid(model));
+            final GraphNode to = new UniqueIdData(NodeTypeEnum.ArtifactType, artifactType.getUniqueId());
+            LOGGER.info("Connecting model {} to type {}", from, to);
+            final Either<GraphRelation, JanusGraphOperationStatus> status = janusGraphGenericDao.createRelation(from,
+                to, GraphEdgeLabels.MODEL_ELEMENT, Collections.emptyMap());
+            if (status.isRight()) {
+                throw new OperationException(ActionStatus.GENERAL_ERROR,
+                    String.format("Failed creating relation between model %s and artifact type %s with status %s",
+                        model, artifactType.getType(), DaoStatusConverter.convertJanusGraphStatusToStorageStatus(status.right().value())));
+            }
+        }
+    }
+
+    /**
+     * Finds a model associated to the given artifact type unique id
+     * @param uid the TOSCA artifact types unique id
+     * @return
+     */
+    private Optional<String> getModelAssociatedToArtifact(final String uid) {
+        final Either<ImmutablePair<ModelData, GraphEdge>, JanusGraphOperationStatus> model =
+            janusGraphGenericDao.getParentNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.Interface), uid,
+                GraphEdgeLabels.MODEL_ELEMENT, NodeTypeEnum.Model, ModelData.class);
+        if (model.isLeft()) {
+            return Optional.ofNullable(model.left().value().getLeft().getName());
+        }
+        return Optional.empty();
+    }
+
+    /**
+     * Finds the derived from for teh given TOSCA artifact types
+     * @param artifactType
+     * @return
+     */
+    private ArtifactTypeData fillDerivedFrom(final ArtifactTypeDefinition artifactType) {
+        final Either<ArtifactTypeData, StorageOperationStatus> result = derivedFromOperation
+            .getDerivedFromChild(artifactType.getUniqueId(), NodeTypeEnum.ArtifactType, ArtifactTypeData.class)
+            .right().bind(this::handleDerivedFromNotExist).left()
+            .map(derivedFrom -> setDerivedFrom(artifactType, derivedFrom));
+        if (result.isRight()) {
+            throw new OperationException(ActionStatus.GENERAL_ERROR,
+                String.format("Failed fetching derivedFrom for artifact type %s with status %s",
+                    artifactType.getType(), result.right().value()));
+        }
+        return result.left().value();
+    }
+
+    private Either<ArtifactTypeData, StorageOperationStatus> handleDerivedFromNotExist(final StorageOperationStatus storageOperationStatus) {
+        if (storageOperationStatus == StorageOperationStatus.NOT_FOUND) {
+            return Either.left(null);
+        }
+        return Either.right(storageOperationStatus);
+    }
+
+    private ArtifactTypeData setDerivedFrom(final ArtifactTypeDefinition artifactType, final ArtifactTypeData derivedFrom) {
+        if (derivedFrom != null) {
+            artifactType.setDerivedFrom(derivedFrom.getArtifactTypeDataDefinition().getType());
+        }
+        return derivedFrom;
+    }
+
+    /**
+     * Finds all properties for the given TOSCA artifact types
+     * @param artifactType the TOSCA artifact types
+     * @param derivedFromNode the TOSCA artifact types derived from
+     */
+    private void fillProperties(final ArtifactTypeDefinition artifactType, final ArtifactTypeData derivedFromNode) {
+        final Either<List<PropertyDefinition>, StorageOperationStatus> result =
+            propertyOperation.findPropertiesOfNode(NodeTypeEnum.ArtifactType, artifactType.getUniqueId()).right()
+                .bind(this::handleNoProperties).left().bind(propsMap -> fillDerivedFromProperties(artifactType,
+                    derivedFromNode, new ArrayList<>(propsMap.values())));
+        if (result.isRight()) {
+            throw new OperationException(ActionStatus.GENERAL_ERROR,
+                String.format("Failed fetching properties for artifact type %s with status %s",
+                    artifactType.getType(), result.right().value()));
+        }
+    }
+
+    private Either<Map<String, PropertyDefinition>, StorageOperationStatus> handleNoProperties(
+        final JanusGraphOperationStatus janusGraphOperationStatus) {
+        if (janusGraphOperationStatus == JanusGraphOperationStatus.NOT_FOUND) {
+            return Either.left(new HashMap<>());
+        }
+        return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(janusGraphOperationStatus));
+    }
+
+    private Either<List<PropertyDefinition>, StorageOperationStatus> fillDerivedFromProperties(final ArtifactTypeDefinition artifactType,
+                                                                                               final ArtifactTypeData derivedFromNode,
+                                                                                               final List<PropertyDefinition> artifactTypeProperties)
+    {
+        if (derivedFromNode == null) {
+            artifactType.setProperties(artifactTypeProperties);
+            return Either.left(artifactTypeProperties);
+        }
+        return propertyOperation
+            .getAllPropertiesRec(derivedFromNode.getUniqueId(), NodeTypeEnum.ArtifactType, ArtifactTypeData.class)
+            .left().map(derivedFromProps -> {
+                artifactTypeProperties.addAll(derivedFromProps);
+                return artifactTypeProperties;
+            }).left().map(allProps -> {
+                artifactType.setProperties(allProps);
+                return allProps;
+            });
+    }
+
+    /**
+     * The Model field is an optional entry when uploading a resource. If the field is present, it validates if the Model name exists.
+     * @param modelName Model names declared on the resource json representation
+     */
+    public void validateModel(final String modelName) {
+        if (modelOperation.findModelByName(modelName).isEmpty()) {
+            LOGGER.error(EcompLoggerErrorCode.DATA_ERROR,"Could not find model name {}", modelName);
+            throw ModelOperationExceptionSupplier.invalidModel(modelName).get();
+        }
+    }
+}
index 8f1cbae..225fe6c 100644 (file)
@@ -218,4 +218,8 @@ public class UniqueIdBuilder {
     public static String buildModelUid(final String modelName) {
         return NodeTypeEnum.Model.getName() + DOT + modelName;
     }
+
+    public static String  buildArtifactTypeUid(final String modelName, final String name) {
+        return StringUtils.isEmpty(modelName) ? name + DOT + "artifactype" : modelName + DOT + name + DOT + "artifactype";
+    }
 }
diff --git a/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/ArtifactTypeDataDefinition.java b/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/ArtifactTypeDataDefinition.java
new file mode 100644 (file)
index 0000000..576c60b
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2021 Nordix Foundation
+ *  ================================================================================
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *  SPDX-License-Identifier: Apache-2.0
+ *  ============LICENSE_END=========================================================
+ */
+package org.openecomp.sdc.be.datatypes.elements;
+
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+import lombok.ToString;
+import org.openecomp.sdc.be.datatypes.tosca.ToscaDataDefinition;
+
+@Getter
+@Setter
+@NoArgsConstructor
+@ToString
+public class ArtifactTypeDataDefinition extends ToscaDataDefinition {
+
+    private String name;
+    private String uniqueId;
+    private String derivedFrom;
+    private String description;
+    private String model;
+    private Long creationDate;
+    private Long lastUpdated;
+
+    public ArtifactTypeDataDefinition(ArtifactTypeDataDefinition p) {
+        this.name = p.name;
+        this.uniqueId = p.uniqueId;
+        this.derivedFrom = p.derivedFrom;
+        this.description = p.description;
+        this.creationDate = p.creationDate;
+        this.lastUpdated = p.lastUpdated;
+        this.model = p.model;
+    }
+}
index 2a927b8..1711e7f 100644 (file)
@@ -64,7 +64,8 @@ public enum NodeTypeEnum {
     GroupInstance("groupInstance"),
     AnnotationType("annotationType"),
     Component("component"),
-    Model("model");
+    Model("model"),
+    ArtifactType("artifactType");
     // @formatter:on
 
     private final String name;