From 2b55a906b7115ff2b156b35a4ff66811157111ee Mon Sep 17 00:00:00 2001 From: aribeiro Date: Tue, 19 Oct 2021 09:11:16 +0100 Subject: [PATCH] Support for adding artifact types Issue-ID: SDC-3763 Change-Id: Ideb63cbb3eb4e383adebaa11de49e91414a2c9a7 Signed-off-by: aribeiro --- .../files/default/error-configuration.yaml | 16 + .../components/impl/ArtifactTypeImportManager.java | 100 ++++++ .../be/components/impl/ArtifactsBusinessLogic.java | 14 +- .../org/openecomp/sdc/be/impl/ComponentsUtils.java | 27 ++ .../sdc/be/servlets/TypesFetchServlet.java | 61 +++- .../sdc/be/servlets/TypesUploadServlet.java | 25 +- .../components/impl/ArtifactBusinessLogicTest.java | 56 ++-- .../impl/ArtifactTypeImportManagerTest.java | 73 +++++ .../impl/ArtifactsBusinessLogicTest.java | 6 +- .../components/impl/ResourceBusinessLogicTest.java | 4 +- .../sdc/be/servlets/TypesFetchServletTest.java | 15 +- .../sdc/be/servlets/TypesUploadServletTest.java | 60 +++- .../src/test/resources/types/artifactTypes.yml | 10 + .../src/test/resources/types/artifactTypes.zip | Bin 0 -> 365 bytes .../org/openecomp/sdc/be/dao/api/ActionStatus.java | 3 +- .../sdc/be/dao/graph/GraphElementFactory.java | 5 + .../sdc/be/resources/data/ArtifactTypeData.java | 75 +++++ .../sdc/be/model/ArtifactTypeDefinition.java | 51 +++ .../sdc/be/model/normatives/ElementTypeEnum.java | 3 +- .../operations/api/IArtifactTypeOperation.java | 33 ++ .../operations/impl/ArtifactTypeOperation.java | 356 +++++++++++++++++++++ .../be/model/operations/impl/UniqueIdBuilder.java | 4 + .../elements/ArtifactTypeDataDefinition.java | 50 +++ .../sdc/be/datatypes/enums/NodeTypeEnum.java | 3 +- 24 files changed, 970 insertions(+), 80 deletions(-) create mode 100644 catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ArtifactTypeImportManager.java create mode 100644 catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ArtifactTypeImportManagerTest.java create mode 100644 catalog-be/src/test/resources/types/artifactTypes.yml create mode 100644 catalog-be/src/test/resources/types/artifactTypes.zip create mode 100644 catalog-dao/src/main/java/org/openecomp/sdc/be/resources/data/ArtifactTypeData.java create mode 100644 catalog-model/src/main/java/org/openecomp/sdc/be/model/ArtifactTypeDefinition.java create mode 100644 catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/api/IArtifactTypeOperation.java create mode 100644 catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/ArtifactTypeOperation.java create mode 100644 common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/ArtifactTypeDataDefinition.java diff --git a/catalog-be/src/main/docker/backend/chef-repo/cookbooks/sdc-catalog-be/files/default/error-configuration.yaml b/catalog-be/src/main/docker/backend/chef-repo/cookbooks/sdc-catalog-be/files/default/error-configuration.yaml index cfde6b45b8..af517c5563 100644 --- a/catalog-be/src/main/docker/backend/chef-repo/cookbooks/sdc-catalog-be/files/default/error-configuration.yaml +++ b/catalog-be/src/main/docker/backend/chef-repo/cookbooks/sdc-catalog-be/files/default/error-configuration.yaml @@ -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 index 0000000000..e6ff100fc1 --- /dev/null +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ArtifactTypeImportManager.java @@ -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, ResponseFormat> createArtifactTypes(final String artifactTypesYml, + final String modelName, + final boolean includeToModelDefaultImports) { + if (StringUtils.isNotEmpty(modelName)) { + artifactTypeOperation.validateModel(modelName); + } + final Either, ActionStatus> artifactTypes = createArtifactTypeFromYml(artifactTypesYml, modelName); + if (artifactTypes.isRight()) { + return Either.right(componentsUtils.getResponseFormat(artifactTypes.right().value())); + } + final List elementTypes = createArtifactTypesByDao(artifactTypes.left().value()); + if (includeToModelDefaultImports) { + commonImportManager.addTypesToDefaultImports(ElementTypeEnum.ARTIFACT_TYPE, artifactTypesYml, modelName); + } + return Either.left(elementTypes); + } + + private Either, ActionStatus> createArtifactTypeFromYml( + final String artifactTypesYml, final String modelName) { + final Either, ActionStatus> artifactTypes = + commonImportManager.createElementTypesFromYml(artifactTypesYml, this::createArtifactTypeDefinition); + if (artifactTypes.isLeft()) { + artifactTypes.left().value().forEach(artifactType -> artifactType.setModel(modelName)); + return artifactTypes; + } + return artifactTypes; + } + + private List createArtifactTypesByDao( + final List artifactTypes) { + final List createdTypes = new ArrayList<>(); + artifactTypes.forEach(type -> createdTypes.add(artifactTypeOperation.createArtifactType(type))); + return createdTypes; + } + + private ArtifactTypeDefinition createArtifactTypeDefinition(final String type, + final Map 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; + } +} diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ArtifactsBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ArtifactsBusinessLogic.java index a566d6c73d..7b21484a7b 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ArtifactsBusinessLogic.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ArtifactsBusinessLogic.java @@ -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 Either ifTrue(boolean predicate, Supplier> ifTrue) { @@ -4263,4 +4268,11 @@ public class ArtifactsBusinessLogic extends BaseBusinessLogic { return operation == CREATE || operation == LINK; } } + + public Map getAllToscaArtifacts(final String modelName) { + if (StringUtils.isNotEmpty(modelName)) { + artifactTypeOperation.validateModel(modelName); + } + return artifactTypeOperation.getAllArtifactTypes(modelName); + } } diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/impl/ComponentsUtils.java b/catalog-be/src/main/java/org/openecomp/sdc/be/impl/ComponentsUtils.java index af05825545..5c2faccd77 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/impl/ComponentsUtils.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/impl/ComponentsUtils.java @@ -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; + } + } diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/TypesFetchServlet.java b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/TypesFetchServlet.java index 097398455f..7a229c88aa 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/TypesFetchServlet.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/TypesFetchServlet.java @@ -19,11 +19,22 @@ */ 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, Response> getComponent(ComponentBusinessLogic resourceBL, boolean isAbstract, String userId) { Either, ResponseFormat> actionResponse; List componentList; diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/TypesUploadServlet.java b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/TypesUploadServlet.java index 06738a88c5..fbd480169a 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/TypesUploadServlet.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/TypesUploadServlet.java @@ -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, 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 = { diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ArtifactBusinessLogicTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ArtifactBusinessLogicTest.java index f1a1aaaea1..616d9e42f9 100644 --- a/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ArtifactBusinessLogicTest.java +++ b/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ArtifactBusinessLogicTest.java @@ -20,6 +20,17 @@ 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 index 0000000000..28a7e9c13b --- /dev/null +++ b/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ArtifactTypeImportManagerTest.java @@ -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"))); + } +} diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ArtifactsBusinessLogicTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ArtifactsBusinessLogicTest.java index 1c680e5a15..14d00efd42 100644 --- a/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ArtifactsBusinessLogicTest.java +++ b/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ArtifactsBusinessLogicTest.java @@ -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 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; } diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ResourceBusinessLogicTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ResourceBusinessLogicTest.java index 90c1864ba7..0453dc7fef 100644 --- a/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ResourceBusinessLogicTest.java +++ b/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ResourceBusinessLogicTest.java @@ -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 ; diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/servlets/TypesFetchServletTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/servlets/TypesFetchServletTest.java index 2305cd3059..ef4ec18ec9 100644 --- a/catalog-be/src/test/java/org/openecomp/sdc/be/servlets/TypesFetchServletTest.java +++ b/catalog-be/src/test/java/org/openecomp/sdc/be/servlets/TypesFetchServletTest.java @@ -20,7 +20,13 @@ 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); } diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/servlets/TypesUploadServletTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/servlets/TypesUploadServletTest.java index 0373aa272a..ed9b9a4eff 100644 --- a/catalog-be/src/test/java/org/openecomp/sdc/be/servlets/TypesUploadServletTest.java +++ b/catalog-be/src/test/java/org/openecomp/sdc/be/servlets/TypesUploadServletTest.java @@ -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 immutablePair = new ImmutablePair<>(new CapabilityTypeDefinition(), true); final Either>, 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>, 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 immutablePair = new ImmutablePair<>(new CapabilityTypeDefinition(), true); final Either>, 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 immutablePair = new ImmutablePair<>(new DataTypeDefinition(), true); final Either>, 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>, 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 immutablePair = new ImmutablePair<>(new DataTypeDefinition(), false); final Either>, 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 immutablePair = new ImmutablePair<>(new DataTypeDefinition(), true); final Either>, 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 immutablePair = new ImmutablePair<>(new RelationshipTypeDefinition(), true); final Either>, 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 immutablePair = new ImmutablePair<>(new RelationshipTypeDefinition(), false); final Either>, 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 immutablePair = new ImmutablePair<>(new RelationshipTypeDefinition(), true); final Either>, 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 immutablePair = new ImmutablePair<>(new InterfaceDefinition(), true); final Either, 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, 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 immutablePair = new ImmutablePair<>(new InterfaceDefinition(), true); final Either, 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>, 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 index 0000000000..9d218303a5 --- /dev/null +++ b/catalog-be/src/test/resources/types/artifactTypes.yml @@ -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 index 0000000000000000000000000000000000000000..2e3ed3bb43cb0e00cbca4166e597c4d27ed00884 GIT binary patch literal 365 zcmWIWW@Zs#-~dAYCjVdtC=g_1U=UC$rL~Wlp7n7lY%lCPU^b_u+FSiz-=b+N!<1Y1i@#Qnmzo{8(aXi|z zD&97#s5C56?9(;R(B~0MZazt^ML{R~Upa-|VB5q~wfpe@5POiym_AZHm_Be%|EUyVaf} zf1_odV1n?rNtgb1Tl`g-7vRm#kt|?xWhT&vAm0UeGct)VBYci52l6=#ENKL>NDhYp SZ&o&tMn)iv2hu-490mZu_+ literal 0 HcmV?d00001 diff --git a/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/api/ActionStatus.java b/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/api/ActionStatus.java index 800fc679c6..1862f85a47 100644 --- a/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/api/ActionStatus.java +++ b/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/api/ActionStatus.java @@ -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 - } diff --git a/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/graph/GraphElementFactory.java b/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/graph/GraphElementFactory.java index 1c500e722d..11de2a3f25 100644 --- a/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/graph/GraphElementFactory.java +++ b/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/graph/GraphElementFactory.java @@ -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 index 0000000000..e138016d10 --- /dev/null +++ b/catalog-dao/src/main/java/org/openecomp/sdc/be/resources/data/ArtifactTypeData.java @@ -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 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 toGraphMap() { + Map 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 index 0000000000..692e9b963b --- /dev/null +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/ArtifactTypeDefinition.java @@ -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 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()); + } + +} diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/normatives/ElementTypeEnum.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/normatives/ElementTypeEnum.java index 57ca559615..e421e6154f 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/normatives/ElementTypeEnum.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/normatives/ElementTypeEnum.java @@ -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 index 0000000000..22e6f00a2a --- /dev/null +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/api/IArtifactTypeOperation.java @@ -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 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 index 0000000000..4b1dcfba97 --- /dev/null +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/ArtifactTypeOperation.java @@ -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 createNodeResult = null; + try { + artifactType.setUniqueId(UniqueIdBuilder.buildArtifactTypeUid(artifactType.getModel(), artifactType.getType())); + final ArtifactTypeData artifactTypeData = new ArtifactTypeData(artifactType); + final Either 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 getAllArtifactTypes(final String model) { + final Either, 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 artifactTypeDefinitionTypes = new HashMap<>(); + final List 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 getLatestArtifactTypeByType(final String type, final String model) { + final Map mapCriteria = new HashMap<>(); + mapCriteria.put(GraphPropertiesDictionary.TYPE.getProperty(), type); + final Either, 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 properties = artifactType.getProperties(); + final Either, 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 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 getModelAssociatedToArtifact(final String uid) { + final Either, 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 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 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, 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, StorageOperationStatus> handleNoProperties( + final JanusGraphOperationStatus janusGraphOperationStatus) { + if (janusGraphOperationStatus == JanusGraphOperationStatus.NOT_FOUND) { + return Either.left(new HashMap<>()); + } + return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(janusGraphOperationStatus)); + } + + private Either, StorageOperationStatus> fillDerivedFromProperties(final ArtifactTypeDefinition artifactType, + final ArtifactTypeData derivedFromNode, + final List 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(); + } + } +} diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/UniqueIdBuilder.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/UniqueIdBuilder.java index 8f1cbae1bb..225fe6c656 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/UniqueIdBuilder.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/UniqueIdBuilder.java @@ -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 index 0000000000..576c60b0a1 --- /dev/null +++ b/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/ArtifactTypeDataDefinition.java @@ -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; + } +} diff --git a/common-be/src/main/java/org/openecomp/sdc/be/datatypes/enums/NodeTypeEnum.java b/common-be/src/main/java/org/openecomp/sdc/be/datatypes/enums/NodeTypeEnum.java index 2a927b8f4a..1711e7f1dc 100644 --- a/common-be/src/main/java/org/openecomp/sdc/be/datatypes/enums/NodeTypeEnum.java +++ b/common-be/src/main/java/org/openecomp/sdc/be/datatypes/enums/NodeTypeEnum.java @@ -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; -- 2.16.6