From 1f7c57414533b9886962ede7b19a29669fe7a59a Mon Sep 17 00:00:00 2001 From: mojahidi Date: Fri, 1 Mar 2019 17:50:15 +0530 Subject: Requirement and capabilities feature 1. Enhance Service/VF/PNF to support Req & Cap 2. Added Type fetch APIs to fetch types from global types Change-Id: I2b749ec9da34e488421b8ebe311ccf03c4b7c0fd Issue-ID: SDC-2142 Signed-off-by: mojahidi --- .../main/resources/config/error-configuration.yaml | 113 ++++ .../components/impl/CapabilitiesBusinessLogic.java | 573 +++++++++++++++++++++ .../be/components/impl/CommonImportManager.java | 5 +- .../impl/RelationshipTypeBusinessLogic.java | 62 +++ .../impl/RelationshipTypeImportManager.java | 109 ++++ .../components/impl/RequirementBusinessLogic.java | 518 +++++++++++++++++++ .../lifecycle/CertificationChangeTransition.java | 8 + .../components/lifecycle/CheckoutTransition.java | 6 + .../components/merge/utils/MergeInstanceUtils.java | 8 +- .../validation/CapabilitiesValidation.java | 266 ++++++++++ .../validation/RequirementValidation.java | 272 ++++++++++ .../org/openecomp/sdc/be/impl/ComponentsUtils.java | 27 + .../sdc/be/servlets/BeGenericServlet.java | 10 + .../sdc/be/servlets/CapabilityServlet.java | 320 ++++++++++++ .../sdc/be/servlets/RequirementServlet.java | 325 ++++++++++++ .../sdc/be/servlets/TypesFetchServlet.java | 207 +++++++- .../sdc/be/servlets/TypesUploadServlet.java | 30 +- .../be/tosca/CapabilityRequirementConverter.java | 63 +-- .../tosca/relationship-types/relationshipTypes.yml | 59 +-- .../scripts/import/tosca/importNormativeAll.py | 4 + .../import/tosca/importNormativeRelationships.py | 83 +++ .../scripts/import/tosca/importONAPNormativeAll.py | 8 +- .../scripts/import/tosca/upgradeNormative.py | 4 + .../scripts/import/tosca/upgradeONAPNormative.py | 4 + .../impl/CapabilitiesBusinessLogicTest.java | 443 ++++++++++++++++ .../impl/RequirementBusinessLogicTest.java | 412 +++++++++++++++ .../validation/CapabilitiesValidationTest.java | 159 ++++++ .../validation/RequirementValidationTest.java | 156 ++++++ .../sdc/be/servlets/TypesUploadServletTest.java | 2 +- .../org/openecomp/sdc/be/dao/api/ActionStatus.java | 15 +- .../sdc/be/dao/graph/GraphElementFactory.java | 1 + .../sdc/be/dao/jsongraph/types/VertexTypeEnum.java | 2 +- .../be/dao/neo4j/GraphPropertiesDictionary.java | 301 +++++------ .../be/resources/data/RelationshipTypeData.java | 14 +- .../sdc/be/model/RelationshipTypeDefinition.java | 69 +++ .../sdc/be/model/jsontitan/datamodel/NodeType.java | 27 - .../be/model/jsontitan/datamodel/ToscaElement.java | 30 ++ .../model/jsontitan/operations/BaseOperation.java | 10 + .../operations/CapabilitiesOperation.java | 91 ++++ .../operations/NodeTemplateOperation.java | 239 ++++++--- .../jsontitan/operations/NodeTypeOperation.java | 10 +- .../jsontitan/operations/RequirementOperation.java | 92 ++++ .../operations/TopologyTemplateOperation.java | 80 +++ .../jsontitan/operations/ToscaOperationFacade.java | 5 +- .../be/model/jsontitan/utils/ModelConverter.java | 160 +++++- .../operations/api/ICapabilityTypeOperation.java | 4 + .../operations/impl/CapabilityTypeOperation.java | 137 ++++- .../be/model/operations/impl/OperationUtils.java | 27 + .../operations/impl/RelationshipTypeOperation.java | 513 ++++++++++++++++++ .../be/model/operations/impl/UniqueIdBuilder.java | 4 + .../sdc/be/model/utils/TypeCompareUtils.java | 16 + .../be/model/jsontitan/datamodel/NodeTypeTest.java | 8 +- .../impl/RelationshipTypeOperationTest.java | 474 +++++++++++++++++ .../impl/ToscaElementLifecycleOperationTest.java | 8 +- .../elements/CapabilityDataDefinition.java | 2 +- .../elements/RelationshipInstDataDefinition.java | 13 +- .../elements/RequirementDataDefinition.java | 6 +- .../be/datatypes/enums/JsonPresentationFields.java | 3 +- .../java/org/openecomp/sdc/ci/tests/api/Urls.java | 12 + .../sdc/ci/tests/capability/CapabilitiesTest.java | 119 +++++ .../sdc/ci/tests/datatypes/CapabilityDetails.java | 56 ++ .../sdc/ci/tests/datatypes/RequirementDetails.java | 74 +++ .../ci/tests/requirements/RequirementsTest.java | 118 +++++ .../ci/tests/utils/rest/CapabilityRestUtils.java | 76 +++ .../sdc/ci/tests/utils/rest/RequirementsUtils.java | 75 +++ .../src/main/resources/ci/testSuites/cap_req.xml | 10 + 66 files changed, 6758 insertions(+), 399 deletions(-) create mode 100644 catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/CapabilitiesBusinessLogic.java create mode 100644 catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/RelationshipTypeBusinessLogic.java create mode 100644 catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/RelationshipTypeImportManager.java create mode 100644 catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/RequirementBusinessLogic.java create mode 100644 catalog-be/src/main/java/org/openecomp/sdc/be/components/validation/CapabilitiesValidation.java create mode 100644 catalog-be/src/main/java/org/openecomp/sdc/be/components/validation/RequirementValidation.java create mode 100644 catalog-be/src/main/java/org/openecomp/sdc/be/servlets/CapabilityServlet.java create mode 100644 catalog-be/src/main/java/org/openecomp/sdc/be/servlets/RequirementServlet.java create mode 100644 catalog-be/src/main/resources/scripts/import/tosca/importNormativeRelationships.py create mode 100644 catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/CapabilitiesBusinessLogicTest.java create mode 100644 catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/RequirementBusinessLogicTest.java create mode 100644 catalog-be/src/test/java/org/openecomp/sdc/be/components/validation/CapabilitiesValidationTest.java create mode 100644 catalog-be/src/test/java/org/openecomp/sdc/be/components/validation/RequirementValidationTest.java create mode 100644 catalog-model/src/main/java/org/openecomp/sdc/be/model/RelationshipTypeDefinition.java create mode 100644 catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/CapabilitiesOperation.java create mode 100644 catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/RequirementOperation.java create mode 100644 catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/RelationshipTypeOperation.java create mode 100644 catalog-model/src/test/java/org/openecomp/sdc/be/model/operations/impl/RelationshipTypeOperationTest.java create mode 100644 test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/capability/CapabilitiesTest.java create mode 100644 test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/datatypes/CapabilityDetails.java create mode 100644 test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/datatypes/RequirementDetails.java create mode 100644 test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/requirements/RequirementsTest.java create mode 100644 test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/utils/rest/CapabilityRestUtils.java create mode 100644 test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/utils/rest/RequirementsUtils.java create mode 100644 test-apis-ci/src/main/resources/ci/testSuites/cap_req.xml diff --git a/asdctool/src/main/resources/config/error-configuration.yaml b/asdctool/src/main/resources/config/error-configuration.yaml index 92ba0610ae..01f8ea4785 100644 --- a/asdctool/src/main/resources/config/error-configuration.yaml +++ b/asdctool/src/main/resources/config/error-configuration.yaml @@ -1689,4 +1689,117 @@ errors: message: "Error: The server was acting as a gateway or proxy and received an invalid response from the upstream server", messageId: "SVC4674" } +#---------SVC4675------------------------------ +# %1 - resource Id + CAPABILITY_NOT_FOUND: { + code: 400, + message: "Error: Capability not found in the resource '%1'.", + messageId: "SVC4675" + } +#---------SVC4676------------------------------ +# %1 - resource Id + REQUIREMENT_NOT_FOUND: { + code: 400, + message: "Error: Requirement not found in the resource '%1'.", + messageId: "SVC4676" + } +#---------SVC4677----------------------------- + CAPABILITY_NAME_MANDATORY: { + code: 404, + message: "Error: Capability name is mandatory, Capability name can't be empty.", + messageId: "SVC4677" + } +#---------SVC4678----------------------------- + CAPABILITY_TYPE_MANDATORY: { + code: 404, + message: "Error: Capability type is mandatory, Capability type can't be empty.", + messageId: "SVC4678" + } +#---------SVC4679----------------------------- +# %1 - Capability Name + CAPABILITY_NAME_ALREADY_IN_USE: { + code: 400, + message: "Error: Capability name '%1' already in use, Your current changes will not be saved.", + messageId: "SVC4679" + } + +#---------SVC4680----------------------------- + REQUIREMENT_NAME_MANDATORY: { + code: 404, + message: "Error: Requirement name is mandatory, Requirement name can't be empty.", + messageId: "SVC4680" + } +#---------SVC4681----------------------------- + REQUIREMENT_CAPABILITY_MANDATORY: { + code: 404, + message: "Error: Requirement capability is mandatory, Requirement capability can't be empty.", + messageId: "SVC4681" + } +#---------SVC4682----------------------------- +# %1 - Requirement Name + REQUIREMENT_NAME_ALREADY_IN_USE: { + code: 400, + message: "Error: Requirement name '%1' already in use, Your current changes will not be saved.", + messageId: "SVC4682" + } +#---------SVC4683----------------------------- + MAX_OCCURRENCES_SHOULD_BE_GREATER_THAN_MIN_OCCURRENCES: { + code: 400, + message: "Error: maxOccurrences should be greater than minOccurrences", + messageId: "SVC4683" + } +#---------SVC4684----------------------------- +# %1 - Capability name + CAPABILITY_DELETION_NOT_ALLOWED_USED_IN_COMPOSITION: { + code: 409, + message: "Error: Capability '%1' can't be deleted, since it is used in service composition", + messageId: "SVC4684" + } +#---------SVC4685----------------------------- +# %1 - Requirement name + REQUIREMENT_DELETION_NOT_ALLOWED_USED_IN_COMPOSITION: { + code: 409, + message: "Error: Requirement '%1' can't be deleted, since it is used in service composition", + messageId: "SVC4685" + } +#---------SVC4686----------------------------- + CAPABILITY_UPDATE_NOT_ALLOWED_USED_IN_COMPOSITION: { + code: 409, + message: "Error: Capability can't be updated, since it is used in service composition", + messageId: "SVC4686" + } + +#---------SVC4687----------------------------- + REQUIREMENT_UPDATE_NOT_ALLOWED_USED_IN_COMPOSITION: { + code: 409, + message: "Error: Requirement can't be updated, since it is used in service composition", + messageId: "SVC4687" + } +#---------SVC4688----------------------------- + CAPABILITY_TYPE_CANNOT_BE_EMPTY: { + code: 500, + message: "Error: Capability types are empty. Please import the capability types.", + messageId: "SVC4688" + } +#---------SVC4689----------------------------- + RELATIONSHIP_TYPE_ALREADY_EXIST: { + code: 409, + message: "Error: Relationship Type with name '%1' already exists.", + messageId: "SVC4689" + } +#---------SVC4690----------------------------- +# %1 - Requirement name + INVALID_REQUIREMENT_NAME: { + code: 400, + message: "Requirement name '%1' is invalid, Only alphanumeric chars, underscore and dot allowed", + messageId: "SVC4690" + } + +#---------SVC4691----------------------------- +# %1 - Capability name + INVALID_CAPABILITY_NAME: { + code: 400, + message: "Capability name '%1' is invalid, Only alphanumeric chars, underscore and dot allowed", + messageId: "SVC4691" + } \ No newline at end of file diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/CapabilitiesBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/CapabilitiesBusinessLogic.java new file mode 100644 index 0000000000..75d5836df6 --- /dev/null +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/CapabilitiesBusinessLogic.java @@ -0,0 +1,573 @@ +/* + * Copyright © 2016-2018 European Support Limited + * + * 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. + */ + +package org.openecomp.sdc.be.components.impl; + +import fj.data.Either; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang.StringUtils; +import org.openecomp.sdc.be.components.validation.CapabilitiesValidation; +import org.openecomp.sdc.be.config.BeEcompErrorManager; +import org.openecomp.sdc.be.dao.api.ActionStatus; +import org.openecomp.sdc.be.dao.titan.TitanOperationStatus; +import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum; +import org.openecomp.sdc.be.model.CapabilityDefinition; +import org.openecomp.sdc.be.model.CapabilityTypeDefinition; +import org.openecomp.sdc.be.model.ComponentParametersView; +import org.openecomp.sdc.be.model.User; +import org.openecomp.sdc.be.model.jsontitan.operations.CapabilitiesOperation; +import org.openecomp.sdc.be.model.operations.api.ICapabilityTypeOperation; +import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus; +import org.openecomp.sdc.exception.ResponseFormat; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.UUID; +import java.util.stream.Collectors; + +@Component("capabilitiesBusinessLogic") +public class CapabilitiesBusinessLogic extends BaseBusinessLogic { + private static final Logger LOGGER = LoggerFactory.getLogger(CapabilitiesBusinessLogic.class); + private static final String FAILED_TO_LOCK_COMPONENT_RESPONSE_IS + = "Failed to lock component {}. Response is {}"; + private static final String DELETE_CAPABILITIES = "deleteCapability"; + private static final String GET_CAPABILITIES = "getCapabilities"; + private static final String EXCEPTION_OCCURRED_DURING_CAPABILITIES + = "Exception occurred during {}. Response is {}"; + + @Autowired + private CapabilitiesOperation capabilitiesOperation; + @Autowired + private CapabilitiesValidation capabilitiesValidation; + @Autowired + private ICapabilityTypeOperation capabilityTypeOperation; + + + public void setCapabilitiesValidation(CapabilitiesValidation capabilitiesValidation) { + this.capabilitiesValidation = capabilitiesValidation; + } + + public void setCapabilitiesOperation(CapabilitiesOperation capabilitiesOperation) { + this.capabilitiesOperation = capabilitiesOperation; + } + + public Either, ResponseFormat> createCapabilities( + String componentId, List capabilityDefinitions, + User user, String errorContext, boolean lock) { + validateUserExists(user.getUserId(), errorContext, true); + Either componentEither + = getComponentDetails(componentId); + if (componentEither.isRight()) { + return Either.right(componentEither.right().value()); + } + org.openecomp.sdc.be.model.Component storedComponent = componentEither.left().value(); + Either capabilitiesValidationEither = capabilitiesValidation + .validateCapabilities(capabilityDefinitions, storedComponent, false); + if (capabilitiesValidationEither.isRight()) { + return Either.right(capabilitiesValidationEither.right().value()); + } + + Either lockResult = lockComponentResult(lock, + storedComponent, errorContext); + if (lockResult.isRight()) { + return Either.right(lockResult.right().value()); + } + try { + Either, StorageOperationStatus> result; + List capabilitiesListStoredInComponent = null; + Map> storedComponentCapabilities + = storedComponent.getCapabilities(); + if (org.apache.commons.collections.MapUtils.isNotEmpty(storedComponentCapabilities)) { + CapabilityDefinition capabilityDefinitionToGetType = capabilityDefinitions.get(0); + if(Objects.isNull(capabilityDefinitionToGetType)) { + return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT)); + } + capabilitiesListStoredInComponent + = getCapabilityStoredInComponentByType(capabilityDefinitionToGetType + .getType(), storedComponentCapabilities); + } + List capabilitiesDefListToCreate; + List capabilitiesToReturn; + if (CollectionUtils.isNotEmpty(capabilitiesListStoredInComponent)) { + capabilitiesDefListToCreate = capabilityDefinitions.stream() + .map(capabilityDefinition -> + initiateNewCapability(storedComponent, capabilityDefinition)) + .collect(Collectors.toList()); + capabilitiesToReturn = capabilitiesDefListToCreate; + capabilitiesDefListToCreate.addAll(capabilitiesListStoredInComponent); + result = capabilitiesOperation.updateCapabilities(componentId, + capabilitiesDefListToCreate); + } else { + capabilitiesToReturn = capabilityDefinitions.stream() + .map(capabilityDefinition -> initiateNewCapability( + storedComponent, capabilityDefinition)) + .collect(Collectors.toList()); + result = capabilitiesOperation.addCapabilities(componentId, capabilitiesToReturn); + } + if (result.isRight()) { + titanDao.rollback(); + return Either.right(componentsUtils.getResponseFormat( + componentsUtils.convertFromStorageResponse(result.right().value(), + storedComponent.getComponentType()), "")); + } + titanDao.commit(); + return Either.left(capabilitiesToReturn); + } catch (Exception e) { + titanDao.rollback(); + LOGGER.error(EXCEPTION_OCCURRED_DURING_CAPABILITIES, "addOrUpdate", e); + return Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR)); + } finally { + if (lockResult.isLeft() && lockResult.left().value()) { + graphLockOperation.unlockComponent(storedComponent.getUniqueId(), + NodeTypeEnum.getByNameIgnoreCase(storedComponent.getComponentType().getValue())); + } + } + } + + public Either, ResponseFormat> updateCapabilities( + String componentId, List capabilityDefinitions, + User user, String errorContext, boolean lock) { + validateUserExists(user.getUserId(), errorContext, true); + Either componentEither + = getComponentDetails(componentId); + if (componentEither.isRight()) { + return Either.right(componentEither.right().value()); + } + org.openecomp.sdc.be.model.Component storedComponent = componentEither.left().value(); + Either capabilitiesValidationEither = capabilitiesValidation + .validateCapabilities(capabilityDefinitions, storedComponent, true); + if (capabilitiesValidationEither.isRight()) { + return Either.right(capabilitiesValidationEither.right().value()); + } + + Either lockResult = lockComponentResult(lock, + storedComponent, errorContext); + if (lockResult.isRight()) { + return Either.right(lockResult.right().value()); + } + try { + Either, StorageOperationStatus> result; + List capabilitiesListStoredInComponent = null; + Map> storedComponentCapabilities + = storedComponent.getCapabilities(); + if (org.apache.commons.collections.MapUtils.isNotEmpty(storedComponentCapabilities)) { + CapabilityDefinition capabilityDefinitionToGetType = capabilityDefinitions.get(0); + if(Objects.isNull(capabilityDefinitionToGetType)) { + return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT)); + } + capabilitiesListStoredInComponent + = getCapabilityStoredInComponentByType(capabilityDefinitionToGetType + .getType(), storedComponentCapabilities); + } + List capabilitiesDefListToUpdate = new ArrayList<>(); + List capabilitiesToReturn = null; + if (CollectionUtils.isNotEmpty(capabilitiesListStoredInComponent)) { + if (capabilityDefinitions.stream().anyMatch(capabilityDefinition -> + isCapabilityUsedInServiceComposition(capabilityDefinition, storedComponent))) { + LOGGER.error("Capability can't be edited, since it is" + + " used in service composition"); + return Either.right(componentsUtils.getResponseFormat( + ActionStatus.CAPABILITY_UPDATE_NOT_ALLOWED_USED_IN_COMPOSITION)); + } + for (CapabilityDefinition capabilityDefinitionToUpdate : capabilityDefinitions) { + capabilitiesToReturn = capabilitiesListStoredInComponent.stream() + .filter(capToUpdate -> capToUpdate.getUniqueId() + .equals(capabilityDefinitionToUpdate.getUniqueId())) + .map(capabilityDefinition -> updateCapability(capabilityDefinition, + capabilityDefinitionToUpdate)).collect(Collectors.toList()); + capabilitiesListStoredInComponent.removeIf(capToUpdate -> + capToUpdate.getUniqueId().equals(capabilityDefinitionToUpdate.getUniqueId())); + if (CollectionUtils.isNotEmpty(capabilitiesToReturn)) { + capabilitiesListStoredInComponent.addAll(capabilitiesToReturn); + capabilitiesDefListToUpdate.addAll(capabilitiesListStoredInComponent); + } else { + Either, ResponseFormat> capTypeUpdateEither + = handleCapabilityTypeUpdateWhenNewTypeExist(storedComponent, + storedComponent.getCapabilities(), capabilitiesToReturn, capabilityDefinitionToUpdate); + if (capTypeUpdateEither.isRight()) { + return Either.right(capTypeUpdateEither.right().value()); + } + capabilitiesDefListToUpdate = capTypeUpdateEither.left().value(); + } + } + result = capabilitiesOperation.updateCapabilities(componentId, + capabilitiesDefListToUpdate); + } else { + Either, ResponseFormat> capabilityDefinitionToDelete + = handleCapabilityTypeUpdateWhenNewTypeNotExist(capabilityDefinitions, + storedComponent, storedComponentCapabilities); + if (capabilityDefinitionToDelete != null) { + return capabilityDefinitionToDelete; + } + capabilitiesToReturn = capabilityDefinitions.stream() + .map(capabilityDefinition -> initiateNewCapability( + storedComponent, capabilityDefinition)) + .collect(Collectors.toList()); + result = capabilitiesOperation.addCapabilities(componentId, capabilitiesToReturn); + } + if (result.isRight()) { + titanDao.rollback(); + return Either.right(componentsUtils.getResponseFormat( + componentsUtils.convertFromStorageResponse(result.right().value(), + storedComponent.getComponentType()), "")); + } + + titanDao.commit(); + return Either.left(capabilitiesToReturn); + } catch (Exception e) { + titanDao.rollback(); + LOGGER.error(EXCEPTION_OCCURRED_DURING_CAPABILITIES, "addOrUpdate", e); + return Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR)); + } finally { + if (lockResult.isLeft() && lockResult.left().value()) { + graphLockOperation.unlockComponent(storedComponent.getUniqueId(), + NodeTypeEnum.getByNameIgnoreCase(storedComponent.getComponentType().getValue())); + } + } + } + + private Either, ResponseFormat> handleCapabilityTypeUpdateWhenNewTypeExist( + org.openecomp.sdc.be.model.Component storedComponent, Map> storedComponentCapabilities, + List capabilitiesToReturn, + CapabilityDefinition capabilityDefinitionToUpdate) { + List capabilitiesListStoredInComponent; + List capabilitiesDefsToCreateOrUpdate = new ArrayList<>(); + Optional definitionOptional = storedComponentCapabilities + .values().stream().flatMap(Collection::stream) + .filter(capabilityDefinition -> capabilityDefinition.getUniqueId() + .equals(capabilityDefinitionToUpdate.getUniqueId())).findAny(); + if (!definitionOptional.isPresent()) { + return Either.right(componentsUtils.getResponseFormat( + ActionStatus.CAPABILITY_NOT_FOUND, storedComponent.getUniqueId())); + } + CapabilityDefinition capabilityDefinitionToDelete = definitionOptional.get(); + + capabilitiesListStoredInComponent = getCapabilityStoredInComponentByType( + capabilityDefinitionToUpdate.getType(), storedComponentCapabilities); + Either, StorageOperationStatus> deleteCapabilityEither + = deleteCapability(storedComponent, storedComponentCapabilities, capabilityDefinitionToDelete); + if (deleteCapabilityEither.isRight()) { + titanDao.rollback(); + return Either.right(componentsUtils.getResponseFormat(deleteCapabilityEither.right().value())); + } + capabilitiesToReturn.add(initiateNewCapability(storedComponent, capabilityDefinitionToUpdate)); + + capabilitiesDefsToCreateOrUpdate.addAll(capabilitiesToReturn); + capabilitiesDefsToCreateOrUpdate.addAll(capabilitiesListStoredInComponent); + return Either.left(capabilitiesDefsToCreateOrUpdate); + } + + private Either, ResponseFormat> handleCapabilityTypeUpdateWhenNewTypeNotExist( + List capabilityDefinitions, + org.openecomp.sdc.be.model.Component storedComponent, + Map> storedComponentCapabilities) { + for (CapabilityDefinition capabilityDefinitionToUpdate : capabilityDefinitions) { + + Optional definitionOptional = storedComponentCapabilities.values() + .stream().flatMap(Collection::stream) + .filter(capabilityDefinition -> capabilityDefinition.getUniqueId() + .equals(capabilityDefinitionToUpdate.getUniqueId())).findAny(); + if (!definitionOptional.isPresent()) { + return Either.right(componentsUtils.getResponseFormat( + ActionStatus.CAPABILITY_NOT_FOUND, storedComponent.getUniqueId())); + } + CapabilityDefinition capabilityDefinitionToDelete = definitionOptional.get(); + Boolean isCapabilityUsedInServiceComposition = isCapabilityUsedInServiceComposition( + capabilityDefinitionToDelete, storedComponent); + if (isCapabilityUsedInServiceComposition) { + LOGGER.error("Capability {} can't be edited, since it is used in service composition", + capabilityDefinitionToDelete.getUniqueId()); + return Either.right(componentsUtils.getResponseFormat( + ActionStatus.CAPABILITY_UPDATE_NOT_ALLOWED_USED_IN_COMPOSITION, + capabilityDefinitionToDelete.getName())); + } + Either, StorageOperationStatus> deleteCapabilityEither + = deleteCapability(storedComponent, storedComponentCapabilities, + capabilityDefinitionToDelete); + if (deleteCapabilityEither.isRight()) { + titanDao.rollback(); + return Either.right(componentsUtils.getResponseFormat(deleteCapabilityEither.right().value())); + } + } + return null; + } + + public Either getCapability( + String componentId, + String capabilityToGet, User user, boolean lock) { + validateUserExists(user.getUserId(), GET_CAPABILITIES, true); + Either componentEither + = getComponentDetails(componentId); + if (componentEither.isRight()) { + return Either.right(componentEither.right().value()); + } + org.openecomp.sdc.be.model.Component storedComponent = componentEither.left().value(); + + Either lockResult = lockComponentResult(lock, + storedComponent, GET_CAPABILITIES); + if (lockResult.isRight()) { + return Either.right(lockResult.right().value()); + } + try { + List capabilityDefinitions = storedComponent.getCapabilities() + .values().stream() + .flatMap(Collection::stream).collect(Collectors.toList()); + if (capabilityDefinitions.isEmpty()) { + return Either.right(componentsUtils.getResponseFormat( + ActionStatus.CAPABILITY_NOT_FOUND, componentId)); + } + + CapabilityDefinition capabilityDefinitionToReturn; + Optional capabilityDefinitionOptional + = capabilityDefinitions.stream() + .filter(capabilityDefinition -> capabilityDefinition.getUniqueId() + .equals(capabilityToGet)).findAny(); + if (capabilityDefinitionOptional.isPresent()) { + capabilityDefinitionToReturn = capabilityDefinitionOptional.get(); + } else { + return Either.right(componentsUtils.getResponseFormat( + ActionStatus.CAPABILITY_NOT_FOUND, componentId)); + } + + return Either.left(capabilityDefinitionToReturn); + } catch (Exception e) { + LOGGER.error(EXCEPTION_OCCURRED_DURING_CAPABILITIES, "get", e); + return Either.right(componentsUtils.getResponseFormat( + ActionStatus.CAPABILITY_NOT_FOUND, componentId)); + } finally { + if (lockResult.isLeft() && lockResult.left().value()) { + graphLockOperation.unlockComponent(storedComponent.getUniqueId(), + NodeTypeEnum.getByNameIgnoreCase(storedComponent.getComponentType() + .getValue())); + } + } + } + + public Either deleteCapability( + String componentId, String capabilityIdToDelete, User user, + boolean lock) { + validateUserExists(user.getUserId(), DELETE_CAPABILITIES, true); + Either componentEither + = getComponentDetails(componentId); + if (componentEither.isRight()) { + return Either.right(componentEither.right().value()); + } + org.openecomp.sdc.be.model.Component storedComponent = componentEither.left().value(); + + Either lockResult = lockComponentResult(lock, + storedComponent, DELETE_CAPABILITIES); + if (lockResult.isRight()) { + return Either.right(lockResult.right().value()); + } + + try { + Map> storedComponentCapabilities + = storedComponent.getCapabilities(); + if (storedComponentCapabilities.isEmpty()) { + return Either.right(componentsUtils.getResponseFormat( + ActionStatus.CAPABILITY_NOT_FOUND, componentId)); + } + + Optional definitionOptional = storedComponentCapabilities + .values().stream().flatMap(Collection::stream) + .filter(capabilityDefinition -> capabilityDefinition.getUniqueId() + .equals(capabilityIdToDelete)).findAny(); + if (!definitionOptional.isPresent()) { + return Either.right(componentsUtils.getResponseFormat( + ActionStatus.CAPABILITY_NOT_FOUND, componentId)); + } + CapabilityDefinition capabilityDefinitionToDelete = definitionOptional.get(); + Boolean isCapabilityUsedInServiceComposition + = isCapabilityUsedInServiceComposition(capabilityDefinitionToDelete, storedComponent); + if (isCapabilityUsedInServiceComposition) { + LOGGER.error("Capability {} can't be deleted, since it is used in service composition", + capabilityDefinitionToDelete.getUniqueId()); + return Either.right(componentsUtils.getResponseFormat( + ActionStatus.CAPABILITY_DELETION_NOT_ALLOWED_USED_IN_COMPOSITION, + capabilityDefinitionToDelete.getName())); + } + + Either, StorageOperationStatus> result + = deleteCapability(storedComponent, storedComponentCapabilities, + capabilityDefinitionToDelete); + if (result.isRight()) { + titanDao.rollback(); + LOGGER.error("Failed to delete capability from component {}. Response is {}", + storedComponent.getName(), result.right().value()); + return Either.right(componentsUtils.getResponseFormat( + componentsUtils.convertFromStorageResponse(result.right().value(), + storedComponent.getComponentType()))); + } + + titanDao.commit(); + return Either.left(capabilityDefinitionToDelete); + } catch (Exception e) { + LOGGER.error(EXCEPTION_OCCURRED_DURING_CAPABILITIES, "delete", e); + titanDao.rollback(); + return Either.right(componentsUtils.getResponseFormat(ActionStatus.CAPABILITY_NOT_FOUND)); + } finally { + if (lockResult.isLeft() && lockResult.left().value()) { + graphLockOperation.unlockComponent(storedComponent.getUniqueId(), + NodeTypeEnum.getByNameIgnoreCase(storedComponent.getComponentType().getValue())); + } + } + } + + private Either, StorageOperationStatus> deleteCapability( + org.openecomp.sdc.be.model.Component storedComponent, + Map> storedComponentCapabilities, + CapabilityDefinition capabilityDefinitionToDelete) { + List capabilitiesListStoredInComponent = + getCapabilityStoredInComponentByType(capabilityDefinitionToDelete.getType(), + storedComponentCapabilities); + if(capabilitiesListStoredInComponent == null) { + return Either.right(StorageOperationStatus.BAD_REQUEST); + } + capabilitiesListStoredInComponent.removeIf(capabilityDefinition -> + capabilityDefinition.getUniqueId().equals(capabilityDefinitionToDelete.getUniqueId())); + Either, StorageOperationStatus> result; + if (capabilitiesListStoredInComponent.isEmpty()) { + StorageOperationStatus operationStatus = capabilitiesOperation.deleteCapabilities(storedComponent, + capabilityDefinitionToDelete.getType()); + if (StorageOperationStatus.OK.equals(operationStatus)) { + result = Either.left(Collections.singletonList(capabilityDefinitionToDelete)); + } else { + result = Either.right(operationStatus); + } + } else { + result = capabilitiesOperation.updateCapabilities(storedComponent.getUniqueId(), + capabilitiesListStoredInComponent); + } + return result; + } + + + private Either getComponentDetails( + String componentId) { + ComponentParametersView filter = new ComponentParametersView(true); + filter.setIgnoreCapabilities(false); + filter.setIgnoreCapabiltyProperties(false); + Either + componentStorageOperationStatusEither = toscaOperationFacade + .getToscaElement(componentId, filter); + if (componentStorageOperationStatusEither.isRight()) { + StorageOperationStatus errorStatus = componentStorageOperationStatusEither.right().value(); + LOGGER.error("Failed to fetch component information by component id {}, Response is {}", + componentId, errorStatus); + return Either.right(componentsUtils.getResponseFormat(componentsUtils + .convertFromStorageResponse(errorStatus))); + } + return Either.left(componentStorageOperationStatusEither.left().value()); + } + + private Either lockComponentResult( + boolean lock, org.openecomp.sdc.be.model.Component component, + String action) { + if (lock) { + Either lockResult = lockComponent(component.getUniqueId(), + component, action); + if (lockResult.isRight()) { + LOGGER.debug(FAILED_TO_LOCK_COMPONENT_RESPONSE_IS, component.getName(), + lockResult.right().value().getFormattedMessage()); + titanDao.rollback(); + return Either.right(lockResult.right().value()); + } + } + return Either.left(true); + } + + private List getCapabilityStoredInComponentByType( + String capabilityType, Map> capabilities) { + Optional>> entryOptional + = capabilities.entrySet().stream(). + filter(map -> map.getKey().equals(capabilityType)).findFirst(); + return entryOptional.map(Map.Entry::getValue).orElse(null); + + } + + private CapabilityDefinition initiateNewCapability( + org.openecomp.sdc.be.model.Component component, + CapabilityDefinition capabilityDefinition) { + if (StringUtils.isEmpty(capabilityDefinition.getUniqueId())) + capabilityDefinition.setUniqueId(UUID.randomUUID().toString()); + if (StringUtils.isEmpty(capabilityDefinition.getOwnerId())) + capabilityDefinition.setOwnerId(component.getUniqueId()); + if (StringUtils.isEmpty(capabilityDefinition.getOwnerName())) + capabilityDefinition.setOwnerName(component.getName()); + capabilityDefinition.setLeftOccurrences(capabilityDefinition.getMaxOccurrences()); + return capabilityDefinition; + } + + private CapabilityDefinition updateCapability(CapabilityDefinition storedCapability, + CapabilityDefinition capabilityToUpdate) { + storedCapability.setName(capabilityToUpdate.getName()); + storedCapability.setDescription(capabilityToUpdate.getDescription()); + storedCapability.setType(capabilityToUpdate.getType()); + storedCapability.setValidSourceTypes(capabilityToUpdate.getValidSourceTypes()); + storedCapability.setMinOccurrences(capabilityToUpdate.getMinOccurrences()); + storedCapability.setMaxOccurrences(capabilityToUpdate.getMaxOccurrences()); + + return storedCapability; + } + + + private Boolean isCapabilityUsedInServiceComposition( + CapabilityDefinition capabilityDefinition, + org.openecomp.sdc.be.model.Component component) { + Either, StorageOperationStatus> + componentList = toscaOperationFacade + .getParentComponents(component.getUniqueId()); + if (componentList.isRight()) { + return Boolean.FALSE; + } + return componentList.left().value().stream().flatMap(parentComponent -> parentComponent + .getComponentInstancesRelations().stream()) + .flatMap(requirementCapabilityRelDef -> requirementCapabilityRelDef.getRelationships().stream()) + .anyMatch(capabilityRequirementRelationship -> capabilityRequirementRelationship + .getRelation().getCapabilityUid().equals(capabilityDefinition.getUniqueId())); + } + + public Either, ResponseFormat> getAllCapabilityTypes() { + Either, TitanOperationStatus> capabilityTypeCacheAll = + capabilityTypeOperation.getAllCapabilityTypes(); + if (capabilityTypeCacheAll.isRight()) { + TitanOperationStatus operationStatus = capabilityTypeCacheAll.right().value(); + if (TitanOperationStatus.NOT_FOUND == operationStatus) { + BeEcompErrorManager.getInstance().logInternalDataError("FetchCapabilityTypes", "Capability types are " + + "not loaded", + BeEcompErrorManager.ErrorSeverity.ERROR); + return Either.right(componentsUtils.getResponseFormat(ActionStatus.DATA_TYPE_CANNOT_BE_EMPTY)); + } else { + BeEcompErrorManager.getInstance().logInternalFlowError("FetchCapabilityTypes", "Failed to fetch capability " + + "types", + BeEcompErrorManager.ErrorSeverity.ERROR); + return Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR)); + } + } + return Either.left(capabilityTypeCacheAll.left().value()); + } +} diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/CommonImportManager.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/CommonImportManager.java index b60b5c7e09..773dc639a9 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/CommonImportManager.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/CommonImportManager.java @@ -173,7 +173,7 @@ public class CommonImportManager { } public enum ElementTypeEnum { - POLICY_TYPE, GROUP_TYPE, DATA_TYPE, CAPABILITY_TYPE, INTERFACE_LIFECYCLE_TYPE + POLICY_TYPE, GROUP_TYPE, DATA_TYPE, CAPABILITY_TYPE, INTERFACE_LIFECYCLE_TYPE, RELATIONSHIP_TYPE } private ActionStatus convertFromStorageResponseForElementType(StorageOperationStatus status, ElementTypeEnum elementTypeEnum) { @@ -191,6 +191,9 @@ public class CommonImportManager { case INTERFACE_LIFECYCLE_TYPE: ret = componentsUtils.convertFromStorageResponseForLifecycleType(status); break; + case RELATIONSHIP_TYPE: + ret = componentsUtils.convertFromStorageResponseForRelationshipType(status); + break; default: ret = componentsUtils.convertFromStorageResponse(status); break; diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/RelationshipTypeBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/RelationshipTypeBusinessLogic.java new file mode 100644 index 0000000000..4a909785b2 --- /dev/null +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/RelationshipTypeBusinessLogic.java @@ -0,0 +1,62 @@ +/* + * Copyright © 2016-2018 European Support Limited + * + * 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. + */ + +package org.openecomp.sdc.be.components.impl; + +import java.util.Map; + +import fj.data.Either; +import org.openecomp.sdc.be.config.BeEcompErrorManager; +import org.openecomp.sdc.be.dao.api.ActionStatus; +import org.openecomp.sdc.be.dao.titan.TitanOperationStatus; +import org.openecomp.sdc.be.impl.ComponentsUtils; +import org.openecomp.sdc.be.model.RelationshipTypeDefinition; +import org.openecomp.sdc.be.model.operations.impl.RelationshipTypeOperation; +import org.openecomp.sdc.exception.ResponseFormat; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component("relationshipTypeBusinessLogic") +public class RelationshipTypeBusinessLogic { + + @Autowired + private RelationshipTypeOperation relationshipTypeOperation; + + @Autowired + protected ComponentsUtils componentsUtils; + + public Either, ResponseFormat> getAllRelationshipTypes() { + Either, TitanOperationStatus> allRelationshipTypes = + relationshipTypeOperation.getAllRelationshipTypes(); + if (allRelationshipTypes.isRight()) { + TitanOperationStatus operationStatus = allRelationshipTypes.right().value(); + if (TitanOperationStatus.NOT_FOUND == operationStatus) { + BeEcompErrorManager.getInstance().logInternalDataError("FetchRelationshipTypes", "Relationship types " + + "are " + + "not loaded", + BeEcompErrorManager.ErrorSeverity.ERROR); + return Either.right(componentsUtils.getResponseFormat(ActionStatus.DATA_TYPE_CANNOT_BE_EMPTY)); + } else { + BeEcompErrorManager.getInstance().logInternalFlowError("FetchRelationshipTypes", "Failed to fetch " + + "relationship types", + BeEcompErrorManager.ErrorSeverity.ERROR); + return Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR)); + } + } + return Either.left(allRelationshipTypes.left().value()); + } + +} diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/RelationshipTypeImportManager.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/RelationshipTypeImportManager.java new file mode 100644 index 0000000000..18671f8caf --- /dev/null +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/RelationshipTypeImportManager.java @@ -0,0 +1,109 @@ +/* + * Copyright © 2016-2018 European Support Limited + * + * 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. + */ + +package org.openecomp.sdc.be.components.impl; + +import java.util.List; +import java.util.Map; + +import fj.data.Either; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.openecomp.sdc.be.components.impl.CommonImportManager.ElementTypeEnum; +import org.openecomp.sdc.be.dao.api.ActionStatus; +import org.openecomp.sdc.be.impl.ComponentsUtils; +import org.openecomp.sdc.be.model.RelationshipTypeDefinition; +import org.openecomp.sdc.be.model.operations.impl.DaoStatusConverter; +import org.openecomp.sdc.be.model.operations.impl.RelationshipTypeOperation; +import org.openecomp.sdc.be.utils.TypeUtils; +import org.openecomp.sdc.exception.ResponseFormat; +import org.springframework.stereotype.Component; + +@Component("relationshipTypeImportManager") +public class RelationshipTypeImportManager { + + private final RelationshipTypeOperation relationshipTypeOperation; + private final CommonImportManager commonImportManager; + private ComponentsUtils componentsUtils; + + public RelationshipTypeImportManager(RelationshipTypeOperation relationshipTypeOperation, + CommonImportManager commonImportManager) { + this.relationshipTypeOperation = relationshipTypeOperation; + this.commonImportManager = commonImportManager; + } + + public Either>, ResponseFormat> createRelationshipTypes( + String relationshipYml) { + return createRelationshipTypes(relationshipYml, false); + } + + private Either>, ResponseFormat> createRelationshipTypes( + String relationshipTypeYml, boolean inTransaction) { + return commonImportManager.createElementTypes(relationshipTypeYml, + relationshipTypesFromYml -> createRelationshipTypesFromYml(relationshipTypeYml), + relationshipTypesToCreate -> createRelationshipTypesByDao(relationshipTypesToCreate, + inTransaction), ElementTypeEnum.RELATIONSHIP_TYPE); + } + + private Either, ActionStatus> createRelationshipTypesFromYml( + String relationshipTypeYml) { + return commonImportManager.createElementTypesFromYml(relationshipTypeYml, + this::createRelationshipType); + } + + private Either>, ResponseFormat> createRelationshipTypesByDao( + List relationshipTypesToCreate, boolean inTransaction) { + return commonImportManager.createElementTypesByDao(relationshipTypesToCreate, this::validateRelationshipType, + relationshipType -> new ImmutablePair<>(ElementTypeEnum.RELATIONSHIP_TYPE, relationshipType.getType()), + relationshipTypeName -> relationshipTypeOperation.getRelationshipTypeByName(relationshipTypeName) + .right().map(DaoStatusConverter::convertTitanStatusToStorageStatus), + relationshipType -> relationshipTypeOperation.addRelationshipType(relationshipType, inTransaction), + (newRelationshipType, oldRelationshipType) -> relationshipTypeOperation + .updateRelationshipType(newRelationshipType, oldRelationshipType, inTransaction)); + } + + + private Either validateRelationshipType(RelationshipTypeDefinition relationshipType) { + Either result = Either.left(ActionStatus.OK); + if (relationshipType.getType() == null) { + ResponseFormat responseFormat = + componentsUtils.getResponseFormat(ActionStatus.MISSING_RELATIONSHIP_TYPE, relationshipType.getType()); + result = Either.right(responseFormat); + } + return result; + } + + private RelationshipTypeDefinition createRelationshipType(String relationshipTypeName, + Map toscaJson) { + RelationshipTypeDefinition relationshipType = new RelationshipTypeDefinition(); + + relationshipType.setType(relationshipTypeName); + + // Description + commonImportManager.setField(toscaJson, TypeUtils.ToscaTagNamesEnum.DESCRIPTION.getElementName(), + relationshipType::setDescription); + // Derived From + commonImportManager.setField(toscaJson, TypeUtils.ToscaTagNamesEnum.DERIVED_FROM.getElementName(), + relationshipType::setDerivedFrom); + // Properties + commonImportManager.setPropertiesMap(toscaJson, relationshipType::setProperties); + //valid-target-types + if(toscaJson.get("valid_target_types") instanceof List) + relationshipType.setValidTargetTypes((List) toscaJson.get("valid_target_types")); + + return relationshipType; + } + +} diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/RequirementBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/RequirementBusinessLogic.java new file mode 100644 index 0000000000..c07a9fc09f --- /dev/null +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/RequirementBusinessLogic.java @@ -0,0 +1,518 @@ +/* + * Copyright © 2016-2018 European Support Limited + * + * 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. + */ + +package org.openecomp.sdc.be.components.impl; + +import fj.data.Either; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang.StringUtils; +import org.openecomp.sdc.be.components.validation.RequirementValidation; +import org.openecomp.sdc.be.dao.api.ActionStatus; +import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum; +import org.openecomp.sdc.be.model.ComponentParametersView; +import org.openecomp.sdc.be.model.RequirementDefinition; +import org.openecomp.sdc.be.model.User; +import org.openecomp.sdc.be.model.jsontitan.operations.RequirementOperation; +import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus; +import org.openecomp.sdc.exception.ResponseFormat; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.UUID; +import java.util.stream.Collectors; + +@Component("requirementBusinessLogic") +public class RequirementBusinessLogic extends BaseBusinessLogic { + private static final Logger LOGGER = LoggerFactory.getLogger(RequirementBusinessLogic.class); + private static final String FAILED_TO_LOCK_COMPONENT_RESPONSE_IS + = "Failed to lock component {}. Response is {}"; + private static final String DELETE_REQUIREMENTS = "deleteRequirement"; + private static final String GET_REQUIREMENTS = "getRequirements"; + private static final String EXCEPTION_OCCURRED_DURING_REQUIREMENTS + = "Exception occurred during {}. Response is {}"; + + @Autowired + private RequirementOperation requirementOperation; + @Autowired + private RequirementValidation requirementValidation; + + + public void setRequirementOperation(RequirementOperation requirementOperation) { + this.requirementOperation = requirementOperation; + } + + public void setRequirementValidation(RequirementValidation requirementValidation) { + this.requirementValidation = requirementValidation; + } + + public Either, ResponseFormat> createRequirements( + String componentId, List requirementDefinitions, + User user, String errorContext, boolean lock) { + validateUserExists(user.getUserId(), errorContext, true); + Either componentEither + = getComponentDetails(componentId); + if (componentEither.isRight()) { + return Either.right(componentEither.right().value()); + } + org.openecomp.sdc.be.model.Component storedComponent = componentEither.left().value(); + + Either requirementsValidationEither = requirementValidation + .validateRequirements(requirementDefinitions, storedComponent, false); + if (requirementsValidationEither.isRight()) { + return Either.right(requirementsValidationEither.right().value()); + } + + Either lockResult = lockComponentResult(lock, + storedComponent, errorContext); + if (lockResult.isRight()) { + return Either.right(lockResult.right().value()); + } + + try { + Either, StorageOperationStatus> result; + List requirementsListStoredInComponent = null; + Map> storedComponentRequirements + = storedComponent.getRequirements(); + if (org.apache.commons.collections.MapUtils.isNotEmpty(storedComponentRequirements)) { + RequirementDefinition requirementDefinitionToGetType = requirementDefinitions.get(0); + if(Objects.isNull(requirementDefinitionToGetType)) { + return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT)); + } + requirementsListStoredInComponent + = getRequirementStoredInComponentByType(requirementDefinitionToGetType + .getCapability(), storedComponentRequirements); + } + List requirementsToReturn; + if (org.apache.commons.collections.CollectionUtils + .isNotEmpty(requirementsListStoredInComponent)) { + List requirementDefToCreate = requirementDefinitions.stream() + .map(requirementDefinition -> initiateNewRequirement(storedComponent, requirementDefinition)) + .collect(Collectors.toList()); + requirementsToReturn = requirementDefToCreate; + requirementDefToCreate.addAll(requirementsListStoredInComponent); + result = requirementOperation.updateRequirement(componentId, requirementDefToCreate); + } else { + requirementsToReturn = requirementDefinitions.stream().map(requirementDefinition -> + initiateNewRequirement(storedComponent, requirementDefinition)) + .collect(Collectors.toList()); + result = requirementOperation.addRequirement(componentId, requirementsToReturn); + } + if (result.isRight()) { + titanDao.rollback(); + return Either.right(componentsUtils.getResponseFormat( + componentsUtils.convertFromStorageResponse(result.right().value(), + storedComponent.getComponentType()), "")); + } + titanDao.commit(); + return Either.left(requirementsToReturn); + } catch (Exception e) { + titanDao.rollback(); + LOGGER.error(EXCEPTION_OCCURRED_DURING_REQUIREMENTS, "addOrUpdate", e); + return Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR)); + } finally { + if (lockResult.isLeft() && lockResult.left().value()) { + graphLockOperation.unlockComponent(storedComponent.getUniqueId(), + NodeTypeEnum.getByNameIgnoreCase(storedComponent.getComponentType().getValue())); + } + } + } + + public Either, ResponseFormat> updateRequirements( + String componentId, List requirementDefinitions, + User user, String errorContext, boolean lock) { + validateUserExists(user.getUserId(), errorContext, true); + Either componentEither + = getComponentDetails(componentId); + if (componentEither.isRight()) { + return Either.right(componentEither.right().value()); + } + org.openecomp.sdc.be.model.Component storedComponent = componentEither.left().value(); + + Either requirementsValidationEither = requirementValidation + .validateRequirements(requirementDefinitions, storedComponent, true); + if (requirementsValidationEither.isRight()) { + return Either.right(requirementsValidationEither.right().value()); + } + + Either lockResult = lockComponentResult(lock, + storedComponent, errorContext); + if (lockResult.isRight()) { + return Either.right(lockResult.right().value()); + } + try { + Either, StorageOperationStatus> result; + List requirementsListStoredInComponent = null; + Map> storedComponentRequirements + = storedComponent.getRequirements(); + if (org.apache.commons.collections.MapUtils.isNotEmpty(storedComponentRequirements)) { + RequirementDefinition requirementDefinitionToGetType = requirementDefinitions.get(0); + if(Objects.isNull(requirementDefinitionToGetType)) { + return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT)); + } + requirementsListStoredInComponent + = getRequirementStoredInComponentByType(requirementDefinitionToGetType + .getCapability(), storedComponentRequirements); + } + List requirementsToReturn = null; + if (org.apache.commons.collections.CollectionUtils + .isNotEmpty(requirementsListStoredInComponent)) { + List requirementDefToUpdate = new ArrayList<>(); + if (requirementDefinitions.stream().anyMatch(requirementDefinition -> + isRequirementUsedInServiceComposition(requirementDefinition, storedComponent))) { + LOGGER.error("Requirement can't be edited, since it is used in service composition"); + return Either.right(componentsUtils.getResponseFormat(ActionStatus + .REQUIREMENT_UPDATE_NOT_ALLOWED_USED_IN_COMPOSITION)); + } + for (RequirementDefinition requirementDefinitionToUpdate : requirementDefinitions) { + requirementsToReturn = requirementsListStoredInComponent.stream() + .filter(reqToUpdate -> reqToUpdate.getUniqueId() + .equals(requirementDefinitionToUpdate.getUniqueId())) + .map(requirementDefinition -> updateRequirement(requirementDefinition, + requirementDefinitionToUpdate)).collect(Collectors.toList()); + requirementsListStoredInComponent.removeIf(reqToUpdate -> + reqToUpdate.getUniqueId().equals(requirementDefinitionToUpdate.getUniqueId())); + + if (CollectionUtils.isNotEmpty(requirementsToReturn)) { + requirementsListStoredInComponent.addAll(requirementsToReturn); + requirementDefToUpdate.addAll(requirementsListStoredInComponent); + } else { + Either, ResponseFormat> updateCapTypeEither + = handleUpdateRequirementCapabilityWhenNewCapabilityExist(storedComponent, + storedComponentRequirements, + requirementsToReturn, requirementDefinitionToUpdate); + if (updateCapTypeEither.isRight()) { + return Either.right(updateCapTypeEither.right().value()); + } + requirementDefToUpdate = updateCapTypeEither.left().value(); + } + } + result = requirementOperation.updateRequirement(componentId, requirementDefToUpdate); + } else { + Either, ResponseFormat> requirementDefinitionToDelete + = handleRequirementCapabilityUpdateWhenNewCapabilityNotExist(requirementDefinitions, + storedComponent, storedComponentRequirements); + if (requirementDefinitionToDelete != null) { + return requirementDefinitionToDelete; + } + requirementsToReturn = requirementDefinitions.stream().map(requirementDefinition -> + initiateNewRequirement(storedComponent, requirementDefinition)) + .collect(Collectors.toList()); + result = requirementOperation.addRequirement(componentId, requirementsToReturn); + } + if (result.isRight()) { + titanDao.rollback(); + return Either.right(componentsUtils.getResponseFormat( + componentsUtils.convertFromStorageResponse(result.right().value(), + storedComponent.getComponentType()), "")); + } + titanDao.commit(); + return Either.left(requirementsToReturn); + } catch (Exception e) { + titanDao.rollback(); + LOGGER.error(EXCEPTION_OCCURRED_DURING_REQUIREMENTS, "addOrUpdate", e); + return Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR)); + } finally { + if (lockResult.isLeft() && lockResult.left().value()) { + graphLockOperation.unlockComponent(storedComponent.getUniqueId(), + NodeTypeEnum.getByNameIgnoreCase(storedComponent.getComponentType().getValue())); + } + } + } + + private Either, ResponseFormat> handleUpdateRequirementCapabilityWhenNewCapabilityExist( + org.openecomp.sdc.be.model.Component storedComponent, + Map> storedComponentRequirements, + List requirementsToReturn, + RequirementDefinition requirementDefinitionToUpdate) { + List requirementsListStoredInComponent; + List requirementDefsToCreateOrUpdate = new ArrayList<>(); + Optional definitionOptional = storedComponentRequirements + .values().stream().flatMap(Collection::stream) + .filter(requirementDefinition -> requirementDefinition.getUniqueId() + .equals(requirementDefinitionToUpdate.getUniqueId())).findAny(); + if (!definitionOptional.isPresent()) { + return Either.right(componentsUtils.getResponseFormat( + ActionStatus.REQUIREMENT_NOT_FOUND, storedComponent.getUniqueId())); + } + RequirementDefinition requirementDefinitionToDelete = definitionOptional.get(); + + requirementsListStoredInComponent = getRequirementStoredInComponentByType( + requirementDefinitionToUpdate.getCapability(), storedComponentRequirements); + Either, StorageOperationStatus> deleteRequirementEither + = deleteRequirement(storedComponent, storedComponentRequirements, requirementDefinitionToDelete); + if (deleteRequirementEither.isRight()) { + titanDao.rollback(); + return Either.right(componentsUtils.getResponseFormat(deleteRequirementEither.right().value())); + } + requirementsToReturn.add(initiateNewRequirement(storedComponent, requirementDefinitionToUpdate)); + + requirementDefsToCreateOrUpdate.addAll(requirementsToReturn); + requirementDefsToCreateOrUpdate.addAll(requirementsListStoredInComponent); + return Either.left(requirementDefsToCreateOrUpdate); + } + + private Either, ResponseFormat> handleRequirementCapabilityUpdateWhenNewCapabilityNotExist( + List requirementDefinitions, + org.openecomp.sdc.be.model.Component storedComponent, + Map> storedComponentRequirements) { + for (RequirementDefinition requirementDefinitionToUpdate : requirementDefinitions) { + + Optional definitionOptional = storedComponentRequirements + .values().stream().flatMap(Collection::stream) + .filter(requirementDefinition -> requirementDefinition.getUniqueId() + .equals(requirementDefinitionToUpdate.getUniqueId())).findAny(); + if (!definitionOptional.isPresent()) { + return Either.right(componentsUtils.getResponseFormat( + ActionStatus.REQUIREMENT_NOT_FOUND, storedComponent.getUniqueId())); + } + RequirementDefinition requirementDefinitionToDelete = definitionOptional.get(); + Boolean isRequirementUsedInServiceComposition + = isRequirementUsedInServiceComposition(requirementDefinitionToDelete, storedComponent); + if (isRequirementUsedInServiceComposition) { + LOGGER.error("Requirement {} can't be edited, since it is used in service composition", + requirementDefinitionToDelete.getUniqueId()); + return Either.right(componentsUtils.getResponseFormat(ActionStatus + .REQUIREMENT_UPDATE_NOT_ALLOWED_USED_IN_COMPOSITION, + requirementDefinitionToDelete.getName())); + } + Either, StorageOperationStatus> deleteRequirementEither + = deleteRequirement(storedComponent, storedComponentRequirements, requirementDefinitionToDelete); + if (deleteRequirementEither.isRight()) { + titanDao.rollback(); + return Either.right(componentsUtils.getResponseFormat(deleteRequirementEither.right().value())); + } + } + return null; + } + + public Either getRequirement(String componentId, + String requirementIdToGet, User user, boolean lock) { + validateUserExists(user.getUserId(), GET_REQUIREMENTS, true); + Either componentEither = getComponentDetails(componentId); + if (componentEither.isRight()) { + return Either.right(componentEither.right().value()); + } + org.openecomp.sdc.be.model.Component storedComponent = componentEither.left().value(); + + Either lockResult = lockComponentResult(lock, storedComponent, GET_REQUIREMENTS); + if (lockResult.isRight()) { + return Either.right(lockResult.right().value()); + } + try { + + List requirementDefinitions = storedComponent.getRequirements().values().stream() + .flatMap(Collection::stream).collect(Collectors.toList()); + if (requirementDefinitions.isEmpty()) { + return Either.right(componentsUtils.getResponseFormat(ActionStatus.REQUIREMENT_NOT_FOUND, componentId)); + } + + RequirementDefinition requirementDefinitionToReturn; + Optional requirementDefinitionOptional = requirementDefinitions.stream() + .filter(requirementDefinition -> requirementDefinition.getUniqueId().equals(requirementIdToGet)).findAny(); + if (requirementDefinitionOptional.isPresent()) { + requirementDefinitionToReturn = requirementDefinitionOptional.get(); + } else { + return Either.right(componentsUtils.getResponseFormat(ActionStatus.REQUIREMENT_NOT_FOUND, componentId)); + } + return Either.left(requirementDefinitionToReturn); + } catch (Exception e) { + LOGGER.error(EXCEPTION_OCCURRED_DURING_REQUIREMENTS, "get", e); + return Either.right(componentsUtils.getResponseFormat(ActionStatus.REQUIREMENT_NOT_FOUND, componentId)); + } finally { + if (lockResult.isLeft() && lockResult.left().value()) { + graphLockOperation.unlockComponent(storedComponent.getUniqueId(), + NodeTypeEnum.getByNameIgnoreCase(storedComponent.getComponentType().getValue())); + } + } + } + + public Either deleteRequirement(String componentId, + String requirementIdToDelete, + User user, boolean lock) { + validateUserExists(user.getUserId(), DELETE_REQUIREMENTS, true); + Either componentEither + = getComponentDetails(componentId); + if (componentEither.isRight()) { + return Either.right(componentEither.right().value()); + } + org.openecomp.sdc.be.model.Component storedComponent = componentEither.left().value(); + + Either lockResult = lockComponentResult(lock, storedComponent, DELETE_REQUIREMENTS); + if (lockResult.isRight()) { + return Either.right(lockResult.right().value()); + } + + try { + Map> storedComponentRequirements = storedComponent.getRequirements(); + if (storedComponentRequirements.isEmpty()) { + return Either.right(componentsUtils.getResponseFormat(ActionStatus.REQUIREMENT_NOT_FOUND, componentId)); + } + + Optional definitionOptional = storedComponentRequirements + .values().stream().flatMap(Collection::stream) + .filter(requirementDefinition -> requirementDefinition.getUniqueId() + .equals(requirementIdToDelete)).findAny(); + if (!definitionOptional.isPresent()) { + return Either.right(componentsUtils.getResponseFormat(ActionStatus.REQUIREMENT_NOT_FOUND, componentId)); + } + RequirementDefinition requirementDefinitionToDelete = definitionOptional.get(); + + Boolean isRequirementUsedInServiceComposition + = isRequirementUsedInServiceComposition(requirementDefinitionToDelete, storedComponent); + if (isRequirementUsedInServiceComposition) { + LOGGER.error("Requirement {} can't be deleted, since it is used in service composition", + requirementDefinitionToDelete.getUniqueId()); + return Either.right(componentsUtils.getResponseFormat(ActionStatus + .CAPABILITY_DELETION_NOT_ALLOWED_USED_IN_COMPOSITION, + requirementDefinitionToDelete.getName())); + } + + Either, StorageOperationStatus> result + = deleteRequirement(storedComponent, storedComponentRequirements, requirementDefinitionToDelete); + if (result.isRight()) { + titanDao.rollback(); + LOGGER.error("Failed to delete requirement from component {}. Response is {}", + storedComponent.getName(), result.right().value()); + return Either.right(componentsUtils.getResponseFormat(componentsUtils + .convertFromStorageResponse(result.right().value(), storedComponent.getComponentType()))); + } + titanDao.commit(); + return Either.left(requirementDefinitionToDelete); + } catch (Exception e) { + LOGGER.error(EXCEPTION_OCCURRED_DURING_REQUIREMENTS, "delete", e); + titanDao.rollback(); + return Either.right(componentsUtils.getResponseFormat(ActionStatus.REQUIREMENT_NOT_FOUND)); + } finally { + if (lockResult.isLeft() && lockResult.left().value()) { + graphLockOperation.unlockComponent(storedComponent.getUniqueId(), + NodeTypeEnum.getByNameIgnoreCase(storedComponent.getComponentType().getValue())); + } + } + } + + private Either, StorageOperationStatus> deleteRequirement( + org.openecomp.sdc.be.model.Component storedComponent, Map> storedComponentRequirements, + RequirementDefinition requirementDefinitionToDelete) { + List requirementStoredInComponentByType = + getRequirementStoredInComponentByType(requirementDefinitionToDelete.getCapability(), + storedComponentRequirements); + if(requirementStoredInComponentByType == null) { + return Either.right(StorageOperationStatus.BAD_REQUEST); + } + requirementStoredInComponentByType.removeIf(requirementDefinition -> + requirementDefinition.getUniqueId().equals(requirementDefinitionToDelete.getUniqueId())); + Either, StorageOperationStatus> result; + if (requirementStoredInComponentByType.isEmpty()) { + + StorageOperationStatus operationStatus = requirementOperation.deleteRequirements(storedComponent, + requirementDefinitionToDelete.getCapability()); + if (operationStatus.equals(StorageOperationStatus.OK)) { + result = Either.left(Collections.singletonList(requirementDefinitionToDelete)); + } else { + result = Either.right(operationStatus); + } + } else { + result = requirementOperation.updateRequirement(storedComponent.getUniqueId(), + requirementStoredInComponentByType); + } + return result; + } + + private Either getComponentDetails(String componentId) { + ComponentParametersView filter = new ComponentParametersView(true); + filter.setIgnoreRequirements(false); + Either componentStorageOperationStatusEither + = toscaOperationFacade.getToscaElement(componentId, filter); + if (componentStorageOperationStatusEither.isRight()) { + StorageOperationStatus errorStatus = componentStorageOperationStatusEither.right().value(); + LOGGER.error("Failed to fetch component information by component id {}, Response is {}", componentId, errorStatus); + return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(errorStatus))); + } + return Either.left(componentStorageOperationStatusEither.left().value()); + } + + private Either lockComponentResult(boolean lock, + org.openecomp.sdc.be.model.Component component, + String action) { + if (lock) { + Either lockResult = lockComponent(component.getUniqueId(), component, action); + if (lockResult.isRight()) { + LOGGER.debug(FAILED_TO_LOCK_COMPONENT_RESPONSE_IS, component.getName(), + lockResult.right().value().getFormattedMessage()); + titanDao.rollback(); + return Either.right(lockResult.right().value()); + } + } + return Either.left(true); + } + + private List getRequirementStoredInComponentByType( + String capabilityType, Map> requirements) { + + Optional>> entryOptional + = requirements.entrySet().stream().filter(map -> map.getKey().equals(capabilityType)).findFirst(); + return entryOptional.map(Map.Entry::getValue).orElse(null); + + } + + private RequirementDefinition initiateNewRequirement(org.openecomp.sdc.be.model.Component component, + RequirementDefinition requirementDefinition) { + if (StringUtils.isEmpty(requirementDefinition.getUniqueId())) + requirementDefinition.setUniqueId(UUID.randomUUID().toString()); + if (StringUtils.isEmpty(requirementDefinition.getOwnerId())) + requirementDefinition.setOwnerId(component.getUniqueId()); + if (StringUtils.isEmpty(requirementDefinition.getOwnerName())) + requirementDefinition.setOwnerName(component.getName()); + requirementDefinition.setLeftOccurrences(requirementDefinition.getMaxOccurrences()); + return requirementDefinition; + } + + private RequirementDefinition updateRequirement(RequirementDefinition storedRequirement, + RequirementDefinition requirementToUpdate) { + storedRequirement.setName(requirementToUpdate.getName()); + storedRequirement.setCapability(requirementToUpdate.getCapability()); + storedRequirement.setNode(requirementToUpdate.getNode()); + storedRequirement.setRelationship(requirementToUpdate.getRelationship()); + storedRequirement.setMinOccurrences(requirementToUpdate.getMinOccurrences()); + storedRequirement.setMaxOccurrences(requirementToUpdate.getMaxOccurrences()); + return storedRequirement; + } + + private Boolean isRequirementUsedInServiceComposition(RequirementDefinition requirementDefinition, + org.openecomp.sdc.be.model.Component component) { + Either, StorageOperationStatus> componentList + = toscaOperationFacade.getParentComponents(component.getUniqueId()); + if (componentList.isRight()) { + return Boolean.FALSE; + } + return componentList.left().value().stream() + .flatMap(parentComponent -> parentComponent.getComponentInstancesRelations() + .stream()).flatMap(requirementCapabilityRelDef -> requirementCapabilityRelDef.getRelationships().stream()) + .anyMatch(capabilityRequirementRelationship -> capabilityRequirementRelationship.getRelation() + .getRequirementUid().equals(requirementDefinition.getUniqueId())); + } +} diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/lifecycle/CertificationChangeTransition.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/lifecycle/CertificationChangeTransition.java index e6a6491aed..2ca6ca41cb 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/lifecycle/CertificationChangeTransition.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/lifecycle/CertificationChangeTransition.java @@ -37,6 +37,7 @@ import org.openecomp.sdc.be.model.jsontitan.operations.ToscaOperationFacade; import org.openecomp.sdc.be.model.jsontitan.utils.ModelConverter; import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus; import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum; +import org.openecomp.sdc.be.tosca.ToscaUtils; import org.openecomp.sdc.be.user.Role; import org.openecomp.sdc.common.log.wrappers.Logger; import org.openecomp.sdc.exception.ResponseFormat; @@ -193,6 +194,7 @@ public class CertificationChangeTransition extends LifeCycleTransition { } } updateCalculatedCapabilitiesRequirements(componentAfterCertification); + updateCapReqOwnerId(componentAfterCertification); result = Either.left(componentAfterCertification); return result; } finally { @@ -212,6 +214,12 @@ public class CertificationChangeTransition extends LifeCycleTransition { } + private void updateCapReqOwnerId(Component component) { + if(component.isTopologyTemplate() && ToscaUtils.isNotComplexVfc(component)) { + toscaOperationFacade.updateCapReqOwnerId(component.getUniqueId()); + } + } + private void updateCalculatedCapabilitiesRequirements(Component certifiedComponent) { if(certifiedComponent.getComponentType() == ComponentTypeEnum.SERVICE){ toscaOperationFacade.updateNamesOfCalculatedCapabilitiesRequirements(certifiedComponent.getUniqueId()); diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/lifecycle/CheckoutTransition.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/lifecycle/CheckoutTransition.java index 525df14ef8..0c4464239e 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/lifecycle/CheckoutTransition.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/lifecycle/CheckoutTransition.java @@ -123,6 +123,7 @@ public class CheckoutTransition extends LifeCycleTransition { } } handleCalculatedCapabilitiesRequirements(clonedComponent); + updateCapReqOwnerId(clonedComponent); } } finally { @@ -148,6 +149,11 @@ public class CheckoutTransition extends LifeCycleTransition { } } + private void updateCapReqOwnerId(Component component) { + if(component.isTopologyTemplate() && ToscaUtils.isNotComplexVfc(component)) { + toscaOperationFacade.updateCapReqOwnerId(component.getUniqueId()); + } + } private StorageOperationStatus upgradeToLatestGenericData(Component clonedComponent) { StorageOperationStatus updateStatus = StorageOperationStatus.OK; diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/utils/MergeInstanceUtils.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/utils/MergeInstanceUtils.java index 06da9ecd98..55cf75b769 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/utils/MergeInstanceUtils.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/utils/MergeInstanceUtils.java @@ -122,11 +122,17 @@ public class MergeInstanceUtils { else { instanceBuildingBlocks = ComponentInstanceBuildingBlocks.of(new ArrayList<>(), singletonList(componentInstance)); } + return instanceBuildingBlocks; } else { instanceBuildingBlocks = recursiveScanForAtomicBuildingBlocks(component); + if(org.apache.commons.collections.MapUtils.isNotEmpty(component.getCapabilities()) || org.apache.commons.collections.MapUtils.isNotEmpty(component.getRequirements())) { + ComponentInstanceBuildingBlocks nonAtomicBlocks = ComponentInstanceBuildingBlocks.of(new ArrayList<>(), singletonList(componentInstance)); + return ComponentInstanceBuildingBlocks.merge(instanceBuildingBlocks, nonAtomicBlocks); + } + return instanceBuildingBlocks; + } - return instanceBuildingBlocks; } public RelationMergeInfo mapRelationCapability(RequirementCapabilityRelDef relDef, List capsOwners) { diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/validation/CapabilitiesValidation.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/validation/CapabilitiesValidation.java new file mode 100644 index 0000000000..9590ec97d9 --- /dev/null +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/validation/CapabilitiesValidation.java @@ -0,0 +1,266 @@ +/* + * Copyright © 2016-2018 European Support Limited + * + * 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. + */ + +package org.openecomp.sdc.be.components.validation; + +import fj.data.Either; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.collections.MapUtils; +import org.apache.commons.lang.StringUtils; +import org.openecomp.sdc.be.components.impl.ResponseFormatManager; +import org.openecomp.sdc.be.dao.api.ActionStatus; +import org.openecomp.sdc.be.model.CapabilityDefinition; +import org.openecomp.sdc.exception.ResponseFormat; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +@Component("capabilitiesValidation") +public class CapabilitiesValidation { + private static final Logger LOGGER = LoggerFactory.getLogger(CapabilitiesValidation.class); + private static final String CAPABILITY_NOT_FOUND_IN_COMPONENT = "Capability not found in component {} "; + private static final Pattern NAME_VALIDATION_REGEX_PATTERN = Pattern.compile("^[a-zA-Z0-9_.]*$"); + + public Either validateCapabilities( + Collection capabilities, + org.openecomp.sdc.be.model.Component component, boolean isUpdate) { + + for(CapabilityDefinition capabilityDefinition : capabilities) { + Either validateCapabilityResponse = validateCapability( + capabilityDefinition, component, isUpdate); + if (validateCapabilityResponse.isRight()) { + return validateCapabilityResponse; + } + } + return Either.left(Boolean.TRUE); + } + + private Either validateCapability(CapabilityDefinition capabilityDefinition, + org.openecomp.sdc.be.model.Component component, + boolean isUpdate) { + ResponseFormatManager responseFormatManager = getResponseFormatManager(); + + if(isUpdate) { + Either capabilityExistValidationEither + = isCapabilityExist(capabilityDefinition, responseFormatManager, component); + if (capabilityExistValidationEither.isRight()) { + return Either.right(capabilityExistValidationEither.right().value()); + } + } + Either capabilityNameValidationResponse + = validateCapabilityName(capabilityDefinition, responseFormatManager, component, isUpdate); + if (capabilityNameValidationResponse.isRight()) { + return Either.right(capabilityNameValidationResponse.right().value()); + } + Either capabilityTypeEmptyEither = + isCapabilityTypeEmpty(responseFormatManager, capabilityDefinition.getType()); + if (capabilityTypeEmptyEither.isRight()) { + return Either.right(capabilityTypeEmptyEither.right().value()); + } + + Either capabilityOccurrencesValidationEither = + validateOccurrences(capabilityDefinition, responseFormatManager); + if (capabilityOccurrencesValidationEither.isRight()) { + return Either.right(capabilityOccurrencesValidationEither.right().value()); + } + + return Either.left(Boolean.FALSE); + } + + private Either validateOccurrences(CapabilityDefinition capabilityDefinition, + ResponseFormatManager responseFormatManager) { + String maxOccurrences = capabilityDefinition.getMaxOccurrences(); + String minOccurrences = capabilityDefinition.getMinOccurrences(); + if(StringUtils.isNotEmpty(maxOccurrences) && StringUtils.isNotEmpty(minOccurrences)) { + Either capabilityOccurrencesValidationEither = + validateOccurrences(responseFormatManager, minOccurrences, + maxOccurrences); + if (capabilityOccurrencesValidationEither.isRight()) { + return Either.right(capabilityOccurrencesValidationEither.right().value()); + } + } + return Either.left(Boolean.TRUE); + } + + private Either isCapabilityExist(CapabilityDefinition definition, + ResponseFormatManager responseFormatManager, + org.openecomp.sdc.be.model.Component component) { + Map> componentCapabilities = component.getCapabilities(); + if(MapUtils.isEmpty(componentCapabilities)){ + LOGGER.error(CAPABILITY_NOT_FOUND_IN_COMPONENT, component.getUniqueId()); + ResponseFormat errorResponse = responseFormatManager.getResponseFormat(ActionStatus + .CAPABILITY_NOT_FOUND, component.getUniqueId()); + return Either.right(errorResponse); + } + + List capabilityDefinitionList = componentCapabilities.values() + .stream().flatMap(Collection::stream).collect(Collectors.toList()); + if(CollectionUtils.isEmpty(capabilityDefinitionList)){ + LOGGER.error(CAPABILITY_NOT_FOUND_IN_COMPONENT, component.getUniqueId()); + ResponseFormat errorResponse = responseFormatManager.getResponseFormat(ActionStatus + .CAPABILITY_NOT_FOUND, component.getUniqueId()); + return Either.right(errorResponse); + } + boolean isCapabilityExist = capabilityDefinitionList.stream().anyMatch(capabilityDefinition -> + capabilityDefinition.getUniqueId().equalsIgnoreCase(definition.getUniqueId())); + + if(!isCapabilityExist) { + LOGGER.error(CAPABILITY_NOT_FOUND_IN_COMPONENT, component.getUniqueId()); + ResponseFormat errorResponse = responseFormatManager.getResponseFormat(ActionStatus + .CAPABILITY_NOT_FOUND, component.getUniqueId()); + return Either.right(errorResponse); + } + return Either.left(Boolean.TRUE); + } + + private Either validateCapabilityName(CapabilityDefinition capabilityDefinition, + ResponseFormatManager responseFormatManager, + org.openecomp.sdc.be.model.Component component, + boolean isUpdate) { + Either capabilityNameEmptyEither = + isCapabilityNameEmpty(responseFormatManager, capabilityDefinition.getName()); + if (capabilityNameEmptyEither.isRight()) { + return Either.right(capabilityNameEmptyEither.right().value()); + } + + Either capabilityNameRegexValidationResponse = + isCapabilityNameRegexValid(responseFormatManager, capabilityDefinition.getName()); + if (capabilityNameRegexValidationResponse.isRight()) { + return Either.right(capabilityNameRegexValidationResponse.right().value()); + } + + Either operationTypeUniqueResponse + = validateCapabilityNameUnique(capabilityDefinition, component, isUpdate ); + if(operationTypeUniqueResponse.isRight()) { + return Either.right(operationTypeUniqueResponse.right().value()); + } + if (!operationTypeUniqueResponse.left().value()) { + LOGGER.error("Capability name {} already in use ", capabilityDefinition.getName()); + ResponseFormat errorResponse = responseFormatManager.getResponseFormat(ActionStatus + .CAPABILITY_NAME_ALREADY_IN_USE, capabilityDefinition.getName()); + return Either.right(errorResponse); + } + return Either.left(Boolean.TRUE); + } + + private Either isCapabilityNameEmpty( + ResponseFormatManager responseFormatManager, String capabilityName) { + if (StringUtils.isEmpty(capabilityName)) { + LOGGER.error("Capability Name is mandatory"); + ResponseFormat errorResponse = responseFormatManager.getResponseFormat(ActionStatus + .CAPABILITY_NAME_MANDATORY); + return Either.right(errorResponse); + } + return Either.left(Boolean.TRUE); + } + + private Either isCapabilityTypeEmpty( + ResponseFormatManager responseFormatManager, String capabilityType) { + if (StringUtils.isEmpty(capabilityType)) { + LOGGER.error("Capability type is mandatory"); + ResponseFormat errorResponse = responseFormatManager.getResponseFormat(ActionStatus + .CAPABILITY_TYPE_MANDATORY); + return Either.right(errorResponse); + } + return Either.left(Boolean.TRUE); + } + + + private Either validateOccurrences ( + ResponseFormatManager responseFormatManager, + String minOccurrences, String maxOccurrences ) { + if(StringUtils.isNotEmpty(maxOccurrences)&& "UNBOUNDED".equalsIgnoreCase(maxOccurrences) + && Integer.parseInt(minOccurrences) >= 0) { + return Either.left(Boolean.TRUE); + } else if(Integer.parseInt(minOccurrences) < 0) { + LOGGER.debug("Invalid occurrences format.low_bound occurrence negative {}", minOccurrences); + ResponseFormat responseFormat = responseFormatManager.getResponseFormat(ActionStatus.INVALID_OCCURRENCES); + return Either.right(responseFormat); + } else if(Integer.parseInt(maxOccurrences) < Integer.parseInt(minOccurrences)){ + LOGGER.error("Capability maxOccurrences should be greater than minOccurrences"); + ResponseFormat errorResponse = responseFormatManager.getResponseFormat(ActionStatus + .MAX_OCCURRENCES_SHOULD_BE_GREATER_THAN_MIN_OCCURRENCES); + return Either.right(errorResponse); + } + return Either.left(Boolean.TRUE); + } + + private Either validateCapabilityNameUnique( + CapabilityDefinition capabilityDefinition, + org.openecomp.sdc.be.model.Component component, + boolean isUpdate) { + boolean isCapabilityNameUnique = false; + + Map> componentCapabilities = component.getCapabilities(); + if(MapUtils.isEmpty(componentCapabilities)){ + return Either.left(true); + } + + List capabilityDefinitionList = componentCapabilities.values() + .stream().flatMap(Collection::stream).collect(Collectors.toList()); + + if(CollectionUtils.isEmpty(capabilityDefinitionList)){ + return Either.left(true); + } + + Map capabilityNameMap = new HashMap<>(); + capabilityDefinitionList.forEach(capability -> capabilityNameMap + .put(capability.getUniqueId(), capability.getName())); + + if (!capabilityNameMap.values().contains(capabilityDefinition.getName())){ + isCapabilityNameUnique = true; + } + if (!isCapabilityNameUnique && isUpdate){ + List> capNamesEntries = capabilityNameMap.entrySet() + .stream().filter(entry -> entry.getValue() + .equalsIgnoreCase(capabilityDefinition.getName())) + .collect(Collectors.toList()); + if(capNamesEntries.size() == 1 && capNamesEntries.get(0).getKey() + .equals(capabilityDefinition.getUniqueId())) { + isCapabilityNameUnique = true; + } + } + return Either.left(isCapabilityNameUnique); + } + + private Either isCapabilityNameRegexValid(ResponseFormatManager responseFormatManager, + String capabilityName) { + if (!isValidCapabilityName(capabilityName)) { + LOGGER.error("Capability name {} is invalid, Only alphanumeric chars, underscore and dot allowed", + capabilityName); + ResponseFormat errorResponse = responseFormatManager + .getResponseFormat(ActionStatus.INVALID_CAPABILITY_NAME, capabilityName); + return Either.right(errorResponse); + } + return Either.left(Boolean.TRUE); + } + + private boolean isValidCapabilityName(String capabilityName) { + return NAME_VALIDATION_REGEX_PATTERN.matcher(capabilityName).matches(); + } + + protected ResponseFormatManager getResponseFormatManager() { + return ResponseFormatManager.getInstance(); + } + +} diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/validation/RequirementValidation.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/validation/RequirementValidation.java new file mode 100644 index 0000000000..0c6a29415a --- /dev/null +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/validation/RequirementValidation.java @@ -0,0 +1,272 @@ +/* + * Copyright © 2016-2018 European Support Limited + * + * 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. + */ + +package org.openecomp.sdc.be.components.validation; + +import fj.data.Either; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.collections.MapUtils; +import org.apache.commons.lang.StringUtils; +import org.openecomp.sdc.be.components.impl.ResponseFormatManager; +import org.openecomp.sdc.be.dao.api.ActionStatus; +import org.openecomp.sdc.be.model.RequirementDefinition; +import org.openecomp.sdc.exception.ResponseFormat; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +@Component("requirementValidation") +public class RequirementValidation { + + private static final Logger LOGGER = LoggerFactory.getLogger(RequirementValidation.class); + private static final String REQUIREMENT_NOT_FOUND_IN_COMPONENT = "Requirement not found in component {} "; + private static final Pattern NAME_VALIDATION_REGEX_PATTERN = Pattern.compile("^[a-zA-Z0-9_.]*$"); + + public Either validateRequirements( + Collection requirements, + org.openecomp.sdc.be.model.Component component, boolean isUpdate) { + + for(RequirementDefinition requirementDefinition : requirements) { + Either requirementValidationResponse + = validateRequirement(requirementDefinition, component, isUpdate); + if (requirementValidationResponse.isRight()) { + return requirementValidationResponse; + } + } + return Either.left(Boolean.TRUE); + } + + private Either validateRequirement( + RequirementDefinition requirementDefinition, + org.openecomp.sdc.be.model.Component component, + boolean isUpdate) { + ResponseFormatManager responseFormatManager = getResponseFormatManager(); + if(isUpdate) { + Either requirementExistValidationEither + = isRequirementExist(requirementDefinition, responseFormatManager, component); + if (requirementExistValidationEither.isRight()) { + return Either.right(requirementExistValidationEither.right().value()); + } + } + + Either requirementNameValidationResponse + = isRequirementNameValid(requirementDefinition, responseFormatManager, + component, isUpdate); + if (requirementNameValidationResponse.isRight()) { + return Either.right(requirementNameValidationResponse.right().value()); + } + + Either requirementTypeEmptyEither = + isRequirementCapabilityEmpty(responseFormatManager, + requirementDefinition.getCapability()); + if (requirementTypeEmptyEither.isRight()) { + return Either.right(requirementTypeEmptyEither.right().value()); + } + Either requirementOccurrencesValidationEither = + validateOccurrences(requirementDefinition, responseFormatManager); + if (requirementOccurrencesValidationEither.isRight()) { + return Either.right(requirementOccurrencesValidationEither.right().value()); + } + return Either.left(Boolean.TRUE); + } + + private Either validateOccurrences(RequirementDefinition requirementDefinition, + ResponseFormatManager responseFormatManager) { + String maxOccurrences = requirementDefinition.getMaxOccurrences(); + String minOccurrences = requirementDefinition.getMinOccurrences(); + if(StringUtils.isNotEmpty(maxOccurrences) && StringUtils.isNotEmpty(minOccurrences)) { + Either requirementOccurrencesValidationEither = + validateOccurrences(responseFormatManager, minOccurrences, + maxOccurrences); + if (requirementOccurrencesValidationEither.isRight()) { + return Either.right(requirementOccurrencesValidationEither.right().value()); + } + } + return Either.left(Boolean.TRUE); + } + + private Either isRequirementNameValid( + RequirementDefinition requirementDefinition, + ResponseFormatManager responseFormatManager, + org.openecomp.sdc.be.model.Component component, boolean isUpdate) { + Either requirementNameEmptyEither = + isRequirementNameEmpty(responseFormatManager, requirementDefinition.getName()); + if (requirementNameEmptyEither.isRight()) { + return Either.right(requirementNameEmptyEither.right().value()); + } + + Either requirementNameRegexValidationResponse = + isRequirementNameRegexValid(responseFormatManager, requirementDefinition.getName()); + if (requirementNameRegexValidationResponse.isRight()) { + return Either.right(requirementNameRegexValidationResponse.right().value()); + } + + Either requirementNameUniqueResponse + = validateRequirementNameUnique(requirementDefinition, + component, isUpdate ); + if(requirementNameUniqueResponse.isRight()) { + return Either.right(requirementNameUniqueResponse.right().value()); + } + if (!requirementNameUniqueResponse.left().value()) { + LOGGER.error("Requirement name {} already in use ", requirementDefinition.getName()); + ResponseFormat errorResponse = responseFormatManager.getResponseFormat(ActionStatus + .REQUIREMENT_NAME_ALREADY_IN_USE, requirementDefinition.getName()); + return Either.right(errorResponse); + } + return Either.left(Boolean.TRUE); + } + + private Either isRequirementNameEmpty( + ResponseFormatManager responseFormatManager, + String requirementName) { + if (StringUtils.isEmpty(requirementName)) { + LOGGER.error("Requirement Name is mandatory"); + ResponseFormat errorResponse = responseFormatManager.getResponseFormat(ActionStatus + .REQUIREMENT_NAME_MANDATORY); + return Either.right(errorResponse); + } + return Either.left(Boolean.TRUE); + } + + private Either validateOccurrences ( + ResponseFormatManager responseFormatManager, + String minOccurrences, String maxOccurrences ) { + if(StringUtils.isNotEmpty(maxOccurrences)&& "UNBOUNDED".equalsIgnoreCase(maxOccurrences) + && Integer.parseInt(minOccurrences) >= 0) { + return Either.left(Boolean.TRUE); + } else if(Integer.parseInt(minOccurrences) < 0) { + LOGGER.debug("Invalid occurrences format.low_bound occurrence negative {}", minOccurrences); + ResponseFormat responseFormat = responseFormatManager.getResponseFormat(ActionStatus.INVALID_OCCURRENCES); + return Either.right(responseFormat); + } + else if(Integer.parseInt(maxOccurrences) < Integer.parseInt(minOccurrences)){ + LOGGER.error("Requirement maxOccurrences should be greater than minOccurrences"); + ResponseFormat errorResponse = responseFormatManager.getResponseFormat(ActionStatus + .MAX_OCCURRENCES_SHOULD_BE_GREATER_THAN_MIN_OCCURRENCES); + return Either.right(errorResponse); + } + return Either.left(Boolean.TRUE); + } + private Either isRequirementCapabilityEmpty( + ResponseFormatManager responseFormatManager, + String requirementCapability) { + if (StringUtils.isEmpty(requirementCapability)) { + LOGGER.error("Requirement capability is mandatory"); + ResponseFormat errorResponse = responseFormatManager.getResponseFormat(ActionStatus + .REQUIREMENT_CAPABILITY_MANDATORY); + return Either.right(errorResponse); + } + return Either.left(Boolean.TRUE); + } + + private Either validateRequirementNameUnique( + RequirementDefinition requirementDefinition, + org.openecomp.sdc.be.model.Component component, + boolean isUpdate) { + boolean isRequirementNameUnique = false; + + Map> componentRequirements = component.getRequirements(); + if(MapUtils.isEmpty(componentRequirements)){ + return Either.left(true); + } + List requirementDefinitionList = componentRequirements.values() + .stream().flatMap(Collection::stream).collect(Collectors.toList()); + + if(CollectionUtils.isEmpty(requirementDefinitionList)){ + return Either.left(true); + } + + Map requirementNameMap = new HashMap<>(); + requirementDefinitionList.forEach(requirement -> requirementNameMap + .put(requirement.getUniqueId(), requirement.getName())); + + if (!requirementNameMap.values().contains(requirementDefinition.getName())){ + isRequirementNameUnique = true; + } + if (!isRequirementNameUnique && isUpdate){ + List> reqNamesEntry = requirementNameMap.entrySet() + .stream().filter(entry -> entry.getValue().equalsIgnoreCase(requirementDefinition.getName())) + .collect(Collectors.toList()); + if(reqNamesEntry.size() == 1 && reqNamesEntry.get(0).getKey() + .equals(requirementDefinition.getUniqueId())) { + isRequirementNameUnique = true; + } + } + return Either.left(isRequirementNameUnique); + } + + private Either isRequirementExist( + RequirementDefinition definition, + ResponseFormatManager responseFormatManager, + org.openecomp.sdc.be.model.Component component) { + Map> componentRequirements = component.getRequirements(); + if(MapUtils.isEmpty(componentRequirements)){ + LOGGER.error(REQUIREMENT_NOT_FOUND_IN_COMPONENT, component.getUniqueId()); + ResponseFormat errorResponse = responseFormatManager.getResponseFormat(ActionStatus + .REQUIREMENT_NOT_FOUND, component.getUniqueId()); + return Either.right(errorResponse); + } + + List requirementDefinitionList = componentRequirements.values() + .stream().flatMap(Collection::stream).collect(Collectors.toList()); + if(CollectionUtils.isEmpty(requirementDefinitionList)){ + LOGGER.error(REQUIREMENT_NOT_FOUND_IN_COMPONENT, component.getUniqueId()); + ResponseFormat errorResponse = responseFormatManager.getResponseFormat(ActionStatus + .REQUIREMENT_NOT_FOUND, component.getUniqueId()); + return Either.right(errorResponse); + } + boolean isRequirementExist = requirementDefinitionList.stream() + .anyMatch(requirementDefinition -> requirementDefinition.getUniqueId() + .equalsIgnoreCase(definition.getUniqueId())); + + if(!isRequirementExist) { + LOGGER.error(REQUIREMENT_NOT_FOUND_IN_COMPONENT, component.getUniqueId()); + ResponseFormat errorResponse = responseFormatManager.getResponseFormat(ActionStatus + .REQUIREMENT_NOT_FOUND, component.getUniqueId()); + return Either.right(errorResponse); + } + return Either.left(Boolean.TRUE); + } + + private Either isRequirementNameRegexValid(ResponseFormatManager responseFormatManager, + String requirementName) { + if (!isValidRequirementName(requirementName)) { + LOGGER.error("Requirement name {} is invalid, Only alphanumeric chars, underscore and dot allowed", + requirementName); + ResponseFormat errorResponse = responseFormatManager + .getResponseFormat(ActionStatus.INVALID_REQUIREMENT_NAME, requirementName); + return Either.right(errorResponse); + } + return Either.left(Boolean.TRUE); + } + + private boolean isValidRequirementName(String requirementName) { + return NAME_VALIDATION_REGEX_PATTERN.matcher(requirementName).matches(); + } + + protected ResponseFormatManager getResponseFormatManager() { + return ResponseFormatManager.getInstance(); + } + +} + 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 909d4da994..0930daad04 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 @@ -1522,5 +1522,32 @@ public class ComponentsUtils { } return getResponseFormat(exception.getActionStatus(), exception.getParams()); } + public ActionStatus convertFromStorageResponseForRelationshipType( + 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.RELATIONSHIP_TYPE_ALREADY_EXIST; + break; + case SCHEMA_VIOLATION: + responseEnum = ActionStatus.RELATIONSHIP_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/BeGenericServlet.java b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/BeGenericServlet.java index c321df1449..d27db55158 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/BeGenericServlet.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/BeGenericServlet.java @@ -148,6 +148,16 @@ public class BeGenericServlet extends BasicServlet { return getClassFromWebAppContext(context, () -> InterfaceOperationBusinessLogic.class); } + protected CapabilitiesBusinessLogic getCapabilitiesBL(ServletContext context) { + return getClassFromWebAppContext(context, () -> CapabilitiesBusinessLogic.class); + } + + protected RelationshipTypeBusinessLogic getRelationshipTypeBL(ServletContext context) { + return getClassFromWebAppContext(context, () -> RelationshipTypeBusinessLogic.class); + } + protected RequirementBusinessLogic getRequirementBL(ServletContext context) { + return getClassFromWebAppContext(context, () -> RequirementBusinessLogic.class); + } ComponentsCleanBusinessLogic getComponentCleanerBL(ServletContext context) { return getClassFromWebAppContext(context, () -> ComponentsCleanBusinessLogic.class); } diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/CapabilityServlet.java b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/CapabilityServlet.java new file mode 100644 index 0000000000..a1456bb65d --- /dev/null +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/CapabilityServlet.java @@ -0,0 +1,320 @@ +/* + * Copyright © 2016-2018 European Support Limited + * + * 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. + */ + +package org.openecomp.sdc.be.servlets; + +import com.jcabi.aspects.Loggable; +import fj.data.Either; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import org.openecomp.sdc.be.components.impl.CapabilitiesBusinessLogic; +import org.openecomp.sdc.be.config.BeEcompErrorManager; +import org.openecomp.sdc.be.dao.api.ActionStatus; +import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum; +import org.openecomp.sdc.be.model.CapabilityDefinition; +import org.openecomp.sdc.be.model.User; +import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum; +import org.openecomp.sdc.be.ui.model.UiComponentDataTransfer; +import org.openecomp.sdc.common.api.Constants; +import org.openecomp.sdc.common.log.wrappers.Logger; +import org.openecomp.sdc.exception.ResponseFormat; + +import javax.inject.Singleton; +import javax.servlet.ServletContext; +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.HeaderParam; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import java.util.List; +import java.util.Optional; + +@Loggable(prepend = true, value = Loggable.DEBUG, trim = false) +@Path("/v1/catalog") +@Consumes(MediaType.APPLICATION_JSON) +@Produces(MediaType.APPLICATION_JSON) +@Api(value = "Capability Servlet", description = "Capability Servlet") +@Singleton +public class CapabilityServlet extends AbstractValidationsServlet { + private static final Logger LOGGER = Logger.getLogger(CapabilityServlet.class); + + @POST + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @Path("/resources/{resourceId}/capabilities") + @ApiOperation(value = "Create Capabilities on resource", httpMethod = "POST", + notes = "Create Capabilities on resource", response = Response.class) + @ApiResponses(value = {@ApiResponse(code = 201, message = "Create Capabilities"), + @ApiResponse(code = 403, message = "Restricted operation"), + @ApiResponse(code = 400, message = "Invalid content / Missing content"), + @ApiResponse(code = 409, message = "Capability already exist")}) + public Response createCapabilitiesOnResource( + @ApiParam(value = "Capability to create", required = true) String data, + @ApiParam(value = "Resource Id") @PathParam("resourceId") String resourceId, + @Context final HttpServletRequest request, + @HeaderParam(value = Constants.USER_ID_HEADER) String userId) { + return createOrUpdate(data, "resources" , resourceId, + request, userId, false, "createCapabilities"); + } + + @PUT + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @Path("/resources/{resourceId}/capabilities") + @ApiOperation(value = "Update Capabilities on resource", httpMethod = "PUT", + notes = "Update Capabilities on resource", response = CapabilityDefinition.class) + @ApiResponses(value = {@ApiResponse(code = 201, message = "Update Capabilities"), + @ApiResponse(code = 403, message = "Restricted operation"), + @ApiResponse(code = 400, message = "Invalid content / Missing content")}) + public Response updateCapabilitiesOnResource( + @ApiParam(value = "Capabilities to update", required = true) String data, + @ApiParam(value = "Component Id") @PathParam("resourceId") String resourceId, + @Context final HttpServletRequest request, + @HeaderParam(value = Constants.USER_ID_HEADER) String userId) { + return createOrUpdate(data, "resources", resourceId, + request, userId, true, "updateCapabilities"); + } + + @GET + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @Path("/resources/{resourceId}/capabilities/{capabilityId}") + @ApiOperation(value = "Get Capability from resource", httpMethod = "GET", + notes = "GET Capability from resource", response = CapabilityDefinition.class) + @ApiResponses(value = {@ApiResponse(code = 201, message = "GET Capability"), + @ApiResponse(code = 403, message = "Restricted operation"), + @ApiResponse(code = 400, message = "Invalid content / Missing content")}) + public Response getCapabilityOnResource( + @ApiParam(value = "Resource Id") @PathParam("resourceId") String resourceId, + @ApiParam(value = "Capability Id") @PathParam("capabilityId") String capabilityId, + @Context final HttpServletRequest request, + @HeaderParam(value = Constants.USER_ID_HEADER) String userId) { + + return get(capabilityId, resourceId, request, userId); + } + + @DELETE + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @Path("/resources/{resourceId}/capabilities/{capabilityId}") + @ApiOperation(value = "Delete capability from resource", httpMethod = "DELETE", + notes = "Delete capability from resource", response = CapabilityDefinition.class) + @ApiResponses(value = {@ApiResponse(code = 201, message = "Delete capability"), + @ApiResponse(code = 403, message = "Restricted operation"), + @ApiResponse(code = 400, message = "Invalid content / Missing content")}) + public Response deleteCapabilityOnResource( + @ApiParam(value = "capability Id") @PathParam("capabilityId") String capabilityId, + @ApiParam(value = "Resource Id") @PathParam("resourceId") String resourceId, + @Context final HttpServletRequest request, + @HeaderParam(value = Constants.USER_ID_HEADER) String userId) { + return delete(capabilityId, resourceId, request, userId); + } + + @POST + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @Path("/services/{serviceId}/capabilities") + @ApiOperation(value = "Create Capabilities on service", httpMethod = "POST", + notes = "Create Capabilities on service", response = Response.class) + @ApiResponses(value = {@ApiResponse(code = 201, message = "Create Capabilities"), + @ApiResponse(code = 403, message = "Restricted operation"), + @ApiResponse(code = 400, message = "Invalid content / Missing content"), + @ApiResponse(code = 409, message = "Capability already exist")}) + public Response createCapabilitiesOnService( + @ApiParam(value = "Capability to create", required = true) String data, + @ApiParam(value = "Service Id") @PathParam("serviceId") String serviceId, + @Context final HttpServletRequest request, + @HeaderParam(value = Constants.USER_ID_HEADER) String userId) { + return createOrUpdate(data, "services" , serviceId, + request, userId, false, "createCapabilities"); + } + + @PUT + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @Path("/services/{serviceId}/capabilities") + @ApiOperation(value = "Update Capabilities on service", httpMethod = "PUT", + notes = "Update Capabilities on service", response = CapabilityDefinition.class) + @ApiResponses(value = {@ApiResponse(code = 201, message = "Update Capabilities"), + @ApiResponse(code = 403, message = "Restricted operation"), + @ApiResponse(code = 400, message = "Invalid content / Missing content")}) + public Response updateCapabilitiesOnService( + @ApiParam(value = "Capabilities to update", required = true) String data, + @ApiParam(value = "Component Id") @PathParam("serviceId") String serviceId, + @Context final HttpServletRequest request, + @HeaderParam(value = Constants.USER_ID_HEADER) String userId) { + return createOrUpdate(data, "services", serviceId, + request, userId, true, "updateCapabilities"); + } + + @GET + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @Path("/services/{serviceId}/capabilities/{capabilityId}") + @ApiOperation(value = "Get Capability from service", httpMethod = "GET", + notes = "GET Capability from service", response = CapabilityDefinition.class) + @ApiResponses(value = {@ApiResponse(code = 201, message = "GET Capability"), + @ApiResponse(code = 403, message = "Restricted operation"), + @ApiResponse(code = 400, message = "Invalid content / Missing content")}) + public Response getCapabilityOnService( + @ApiParam(value = "Service Id") @PathParam("serviceId") String serviceId, + @ApiParam(value = "Capability Id") @PathParam("capabilityId") String capabilityId, + @Context final HttpServletRequest request, + @HeaderParam(value = Constants.USER_ID_HEADER) String userId) { + + return get(capabilityId, serviceId, request, userId); + } + + @DELETE + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @Path("/services/{serviceId}/capabilities/{capabilityId}") + @ApiOperation(value = "Delete capability from service", httpMethod = "DELETE", + notes = "Delete capability from service", response = CapabilityDefinition.class) + @ApiResponses(value = {@ApiResponse(code = 201, message = "Delete capability"), + @ApiResponse(code = 403, message = "Restricted operation"), + @ApiResponse(code = 400, message = "Invalid content / Missing content")}) + public Response deleteCapabilityOnService( + @ApiParam(value = "capability Id") @PathParam("capabilityId") String capabilityId, + @ApiParam(value = "Service Id") @PathParam("serviceId") String serviceId, + @Context final HttpServletRequest request, + @HeaderParam(value = Constants.USER_ID_HEADER) String userId) { + return delete(capabilityId, serviceId, request, userId); + } + + private Response createOrUpdate (String data, String componentType, String componentId, + HttpServletRequest request, + String userId, + boolean isUpdate, + String errorContext) { + ServletContext context = request.getSession().getServletContext(); + String url = request.getMethod() + " " + request.getRequestURI(); + + User modifier = new User(); + modifier.setUserId(userId); + LOGGER.debug("Start create or update request of {} with modifier id {}", url, userId); + try { + String componentIdLower = componentId.toLowerCase(); + CapabilitiesBusinessLogic businessLogic = getCapabilitiesBL(context); + + Either, ResponseFormat> mappedCapabilitiesDataEither + = getMappedCapabilitiesData(data, modifier, ComponentTypeEnum.findByParamName(componentType)); + if(mappedCapabilitiesDataEither.isRight()) { + LOGGER.error("Failed to create or update capabilities"); + buildErrorResponse(mappedCapabilitiesDataEither.right().value()); + } + List mappedCapabilitiesData = mappedCapabilitiesDataEither.left().value(); + Either, ResponseFormat> actionResponse; + if(isUpdate) { + actionResponse = businessLogic.updateCapabilities(componentIdLower, + mappedCapabilitiesData, modifier, errorContext, true); + } else { + actionResponse = businessLogic.createCapabilities(componentIdLower, + mappedCapabilitiesData, modifier, errorContext, true); + } + if (actionResponse.isRight()) { + LOGGER.error("Failed to create or update capabilities"); + return buildErrorResponse(actionResponse.right().value()); + } + return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), + actionResponse.left().value()); + } catch (Exception e) { + BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Capabilities create or update"); + LOGGER.error("Failed to create or update capabilities with an error", e); + return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR)); + } + } + + private Response get (String capabilityIdToGet, String componentId, + HttpServletRequest request, String userId){ + ServletContext context = request.getSession().getServletContext(); + String url = request.getMethod() + " " + request.getRequestURI(); + + User modifier = new User(); + modifier.setUserId(userId); + LOGGER.debug("Start get request of {} with modifier id {}", url, userId); + + try { + String componentIdLower = componentId.toLowerCase(); + CapabilitiesBusinessLogic businessLogic = getCapabilitiesBL(context); + + Either actionResponse = businessLogic + .getCapability(componentIdLower, capabilityIdToGet, modifier, true); + if (actionResponse.isRight()) { + LOGGER.error("failed to get capability"); + return buildErrorResponse(actionResponse.right().value()); + } + Object result = RepresentationUtils.toFilteredRepresentation(actionResponse.left().value()); + return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), result); + } catch (Exception e) { + BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Get capability"); + LOGGER.error("get capabilities failed with exception", e); + return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR)); + } + } + + private Response delete (String capabilityId, String componentId, HttpServletRequest + request, String userId){ + + ServletContext context = request.getSession().getServletContext(); + String url = request.getMethod() + " " + request.getRequestURI(); + + User modifier = new User(); + modifier.setUserId(userId); + LOGGER.debug("Start delete request of {} with modifier id {}", url, userId); + + try { + String componentIdLower = componentId.toLowerCase(); + CapabilitiesBusinessLogic businessLogic = getCapabilitiesBL(context); + + Either actionResponse = businessLogic + .deleteCapability(componentIdLower, capabilityId, modifier, true); + if (actionResponse.isRight()) { + LOGGER.error("failed to delete capability"); + return buildErrorResponse(actionResponse.right().value()); + } + Object result = RepresentationUtils.toRepresentation(actionResponse.left().value()); + return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), result); + } catch (Exception e) { + BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Delete capability"); + LOGGER.error("Delete capability failed with an error", e); + return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR)); + } + } + + private Either, ResponseFormat> getMappedCapabilitiesData(String inputJson, User user, + ComponentTypeEnum componentTypeEnum){ + Either mappedData = getComponentsUtils() + .convertJsonToObjectUsingObjectMapper(inputJson, user, UiComponentDataTransfer.class, + AuditingActionEnum.CREATE_RESOURCE, componentTypeEnum); + Optional> capabilityDefinitionList = + mappedData.left().value().getCapabilities().values().stream().findFirst(); + return capabilityDefinitionList., ResponseFormat>> + map(Either::left).orElseGet(() -> Either.right(getComponentsUtils() + .getResponseFormat(ActionStatus.GENERAL_ERROR))); + } +} diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/RequirementServlet.java b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/RequirementServlet.java new file mode 100644 index 0000000000..51f6783f0d --- /dev/null +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/RequirementServlet.java @@ -0,0 +1,325 @@ +/* + * Copyright © 2016-2018 European Support Limited + * + * 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. + */ + +package org.openecomp.sdc.be.servlets; + +import com.jcabi.aspects.Loggable; +import fj.data.Either; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import org.openecomp.sdc.be.components.impl.RequirementBusinessLogic; +import org.openecomp.sdc.be.config.BeEcompErrorManager; +import org.openecomp.sdc.be.dao.api.ActionStatus; +import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum; +import org.openecomp.sdc.be.model.RequirementDefinition; +import org.openecomp.sdc.be.model.User; +import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum; +import org.openecomp.sdc.be.ui.model.UiComponentDataTransfer; +import org.openecomp.sdc.common.api.Constants; +import org.openecomp.sdc.common.log.wrappers.Logger; +import org.openecomp.sdc.exception.ResponseFormat; + +import javax.inject.Singleton; +import javax.servlet.ServletContext; +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.HeaderParam; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import java.util.List; +import java.util.Optional; + +@Loggable(prepend = true, value = Loggable.DEBUG, trim = false) +@Path("/v1/catalog") +@Consumes(MediaType.APPLICATION_JSON) +@Produces(MediaType.APPLICATION_JSON) +@Api(value = "Requirement Servlet", description = "Requirement Servlet") +@Singleton +public class RequirementServlet extends AbstractValidationsServlet { + private static final Logger LOGGER = Logger.getLogger(RequirementServlet.class); + + @POST + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @Path("/resources/{resourceId}/requirements") + @ApiOperation(value = "Create requirements on resource", httpMethod = "POST", + notes = "Create requirements on resource", response = Response.class) + @ApiResponses(value = {@ApiResponse(code = 201, message = "Create requirements"), + @ApiResponse(code = 403, message = "Restricted operation"), + @ApiResponse(code = 400, message = "Invalid content / Missing content"), + @ApiResponse(code = 409, message = "requirement already exist")}) + public Response createRequirementsOnResource( + @ApiParam(value = "Requirement to create", required = true) String data, + @ApiParam(value = "Resource Id") @PathParam("resourceId") String resourceId, + @Context final HttpServletRequest request, + @HeaderParam(value = Constants.USER_ID_HEADER) String userId) { + return createOrUpdate(data, "resources" , resourceId, request, + userId, false, "createRequirements"); + } + + + @PUT + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @Path("/resources/{resourceId}/requirements") + @ApiOperation(value = "Update Requirements on resource", httpMethod = "PUT", + notes = "Update Requirements on resource", response = RequirementDefinition.class) + @ApiResponses(value = {@ApiResponse(code = 201, message = "Update Requirements"), + @ApiResponse(code = 403, message = "Restricted operation"), + @ApiResponse(code = 400, message = "Invalid content / Missing content")}) + public Response updateRequirementsOnResource( + @ApiParam(value = "Requirements to update", required = true) String data, + @ApiParam(value = "Component Id") @PathParam("resourceId") String resourceId, + @Context final HttpServletRequest request, + @HeaderParam(value = Constants.USER_ID_HEADER) String userId) { + return createOrUpdate(data, "resources", resourceId, request, + userId, true, "updateRequirements"); + } + + @GET + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @Path("/resources/{resourceId}/requirements/{requirementId}") + @ApiOperation(value = "Get Requirement from resource", httpMethod = "GET", + notes = "GET Requirement from resource", response = RequirementDefinition.class) + @ApiResponses(value = {@ApiResponse(code = 201, message = "GET requirement"), + @ApiResponse(code = 403, message = "Restricted operation"), + @ApiResponse(code = 400, message = "Invalid content / Missing content")}) + public Response getRequirementsFromResource( + @ApiParam(value = "Resource Id") @PathParam("resourceId") String resourceId, + @ApiParam(value = "Requirement Id") @PathParam("requirementId") String requirementId, + @Context final HttpServletRequest request, + @HeaderParam(value = Constants.USER_ID_HEADER) String userId) { + + return get(requirementId, resourceId, request, userId); + } + + @DELETE + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @Path("/resources/{resourceId}/requirements/{requirementId}") + @ApiOperation(value = "Delete requirements from resource", httpMethod = "DELETE", + notes = "Delete requirements from resource", response = RequirementDefinition.class) + @ApiResponses(value = {@ApiResponse(code = 201, message = "Delete requirement"), + @ApiResponse(code = 403, message = "Restricted operation"), + @ApiResponse(code = 400, message = "Invalid content / Missing content")}) + public Response deleteRequirementsFromResource( + @ApiParam(value = "Resource Id") @PathParam("resourceId") String resourceId, + @ApiParam(value = "requirement Id") @PathParam("requirementId") String requirementId, + @Context final HttpServletRequest request, + @HeaderParam(value = Constants.USER_ID_HEADER) String userId) { + return delete(requirementId, resourceId, request, userId); + } + + @POST + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @Path("/services/{serviceId}/requirements") + @ApiOperation(value = "Create requirements on service", httpMethod = "POST", + notes = "Create requirements on service", response = Response.class) + @ApiResponses(value = {@ApiResponse(code = 201, message = "Create Requirements"), + @ApiResponse(code = 403, message = "Restricted operation"), + @ApiResponse(code = 400, message = "Invalid content / Missing content"), + @ApiResponse(code = 409, message = "Requirement already exist")}) + public Response createRequirementsOnService( + @ApiParam(value = "Requirements to create", required = true) String data, + @ApiParam(value = "Service Id") @PathParam("serviceId") String serviceId, + @Context final HttpServletRequest request, + @HeaderParam(value = Constants.USER_ID_HEADER) String userId) { + return createOrUpdate(data, "services" , serviceId, request, userId, + false , "createRequirements"); + } + + + @PUT + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @Path("/services/{serviceId}/requirements") + @ApiOperation(value = "Update requirements on service", httpMethod = "PUT", + notes = "Update requirements on service", response = RequirementDefinition.class) + @ApiResponses(value = {@ApiResponse(code = 201, message = "Update requirements"), + @ApiResponse(code = 403, message = "Restricted operation"), + @ApiResponse(code = 400, message = "Invalid content / Missing content")}) + public Response updateRequirementsOnService( + @ApiParam(value = "Requirements to update", required = true) String data, + @ApiParam(value = "Component Id") @PathParam("serviceId") String serviceId, + @Context final HttpServletRequest request, + @HeaderParam(value = Constants.USER_ID_HEADER) String userId) { + return createOrUpdate(data, "services", serviceId, request, userId, + true, "updateRequirements"); + } + + @GET + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @Path("/services/{serviceId}/requirements/{requirementId}") + @ApiOperation(value = "Get requirement from service", httpMethod = "GET", + notes = "GET requirement from service", response = RequirementDefinition.class) + @ApiResponses(value = {@ApiResponse(code = 201, message = "GET Requirements"), + @ApiResponse(code = 403, message = "Restricted operation"), + @ApiResponse(code = 400, message = "Invalid content / Missing content")}) + public Response getRequirementsOnService( + @ApiParam(value = "Service Id") @PathParam("serviceId") String serviceId, + @ApiParam(value = "Requirement Id") @PathParam("requirementId") String requirementId, + @Context final HttpServletRequest request, + @HeaderParam(value = Constants.USER_ID_HEADER) String userId) { + + return get(requirementId, serviceId, request, userId); + } + + + @DELETE + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @Path("/services/{serviceId}/requirements/{requirementId}") + @ApiOperation(value = "Delete requirement from service", httpMethod = "DELETE", + notes = "Delete requirement from service", response = RequirementDefinition.class) + @ApiResponses(value = {@ApiResponse(code = 201, message = "Delete Requirements"), + @ApiResponse(code = 403, message = "Restricted operation"), + @ApiResponse(code = 400, message = "Invalid content / Missing content")}) + public Response deleteRequirementsOnService( + @ApiParam(value = "Service Id") @PathParam("serviceId") String serviceId, + @ApiParam(value = "Requirement Id") @PathParam("requirementId") String requirementId, + @Context final HttpServletRequest request, + @HeaderParam(value = Constants.USER_ID_HEADER) String userId) { + return delete(requirementId, serviceId, request, userId); + } + + + private Response createOrUpdate (String data, String componentType, String componentId, + HttpServletRequest request, String userId, + boolean isUpdate, String errorContext) { + ServletContext context = request.getSession().getServletContext(); + String url = request.getMethod() + " " + request.getRequestURI(); + + User modifier = new User(); + modifier.setUserId(userId); + LOGGER.debug("Start create or update request of {} with modifier id {}", url, userId); + + try { + String componentIdLower = componentId.toLowerCase(); + RequirementBusinessLogic businessLogic = getRequirementBL(context); + + Either, ResponseFormat> mappedRequirementDataEither = + getMappedRequirementData(data, modifier, ComponentTypeEnum.findByParamName(componentType)); + if(mappedRequirementDataEither.isRight()) { + LOGGER.error("Failed to create or update requirements"); + return buildErrorResponse(mappedRequirementDataEither.right().value()); + } + List mappedRequirementData = mappedRequirementDataEither.left().value(); + Either, ResponseFormat> actionResponse; + if(isUpdate) { + actionResponse = businessLogic.updateRequirements(componentIdLower, mappedRequirementData, modifier, + errorContext, true); + } else { + actionResponse = businessLogic.createRequirements(componentIdLower, mappedRequirementData, modifier, + errorContext, true); + } + + if (actionResponse.isRight()) { + LOGGER.error("Failed to create or update requirements"); + return buildErrorResponse(actionResponse.right().value()); + } + + return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), + actionResponse.left().value()); + } catch (Exception e) { + BeEcompErrorManager.getInstance().logBeRestApiGeneralError("requirements create or update"); + LOGGER.error("Failed to create or update requirements with an error", e); + return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR)); + } + } + + private Response get (String requirementIdToGet, String componentId, + HttpServletRequest request, String userId){ + ServletContext context = request.getSession().getServletContext(); + String url = request.getMethod() + " " + request.getRequestURI(); + + User modifier = new User(); + modifier.setUserId(userId); + LOGGER.debug("Start get request of {} with modifier id {}", url, userId); + + try { + String componentIdLower = componentId.toLowerCase(); + RequirementBusinessLogic businessLogic = getRequirementBL(context); + + Either actionResponse = businessLogic + .getRequirement(componentIdLower, requirementIdToGet, modifier, true); + if (actionResponse.isRight()) { + LOGGER.error("failed to get requirements"); + return buildErrorResponse(actionResponse.right().value()); + } + Object result = RepresentationUtils.toFilteredRepresentation(actionResponse.left().value()); + return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), result); + } catch (Exception e) { + BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Get requirements"); + LOGGER.error("get requirements failed with exception", e); + return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR)); + } + } + + private Response delete (String requirementId, String componentId, HttpServletRequest + request, String userId){ + + ServletContext context = request.getSession().getServletContext(); + String url = request.getMethod() + " " + request.getRequestURI(); + + User modifier = new User(); + modifier.setUserId(userId); + LOGGER.debug("Start delete request of {} with modifier id {}", url, userId); + + try { + String componentIdLower = componentId.toLowerCase(); + RequirementBusinessLogic businessLogic = getRequirementBL(context); + + Either actionResponse = businessLogic + .deleteRequirement(componentIdLower, requirementId, modifier, true); + if (actionResponse.isRight()) { + LOGGER.error("failed to delete requirements"); + return buildErrorResponse(actionResponse.right().value()); + } + Object result = RepresentationUtils.toRepresentation(actionResponse.left().value()); + return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), result); + } catch (Exception e) { + BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Delete requirements"); + LOGGER.error("Delete requirements failed with an error", e); + return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR)); + } + } + + private Either, ResponseFormat> getMappedRequirementData(String inputJson, User user, + ComponentTypeEnum componentTypeEnum){ + Either mappedData = getComponentsUtils() + .convertJsonToObjectUsingObjectMapper(inputJson, user, UiComponentDataTransfer.class, + AuditingActionEnum.CREATE_RESOURCE, componentTypeEnum); + Optional> requirementDefinitionList = mappedData.left().value() + .getRequirements().values().stream().findFirst(); + return requirementDefinitionList., ResponseFormat>> + map(Either::left).orElseGet(() -> Either.right(getComponentsUtils() + .getResponseFormat(ActionStatus.GENERAL_ERROR))); + } +} 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 00b04a4ffc..459629ff26 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 @@ -26,28 +26,44 @@ import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiResponse; import io.swagger.annotations.ApiResponses; +import org.apache.commons.collections4.ListUtils; +import org.openecomp.sdc.be.components.impl.CapabilitiesBusinessLogic; +import org.openecomp.sdc.be.components.impl.ComponentBusinessLogic; import org.openecomp.sdc.be.components.impl.InterfaceOperationBusinessLogic; import org.openecomp.sdc.be.components.impl.PropertyBusinessLogic; +import org.openecomp.sdc.be.components.impl.RelationshipTypeBusinessLogic; import org.openecomp.sdc.be.config.BeEcompErrorManager; import org.openecomp.sdc.be.dao.api.ActionStatus; -import org.openecomp.sdc.be.impl.WebAppContextWrapper; +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.model.CapabilityTypeDefinition; +import org.openecomp.sdc.be.model.Component; import org.openecomp.sdc.be.model.DataTypeDefinition; import org.openecomp.sdc.be.model.InterfaceDefinition; +import org.openecomp.sdc.be.model.RelationshipTypeDefinition; import org.openecomp.sdc.be.model.User; import org.openecomp.sdc.common.api.Constants; import org.openecomp.sdc.common.datastructure.Wrapper; import org.openecomp.sdc.common.log.wrappers.Logger; import org.openecomp.sdc.exception.ResponseFormat; -import org.springframework.web.context.WebApplicationContext; import javax.inject.Singleton; import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; -import javax.ws.rs.*; +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.HeaderParam; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; +import java.util.HashMap; +import java.util.List; import java.util.Map; +import java.util.stream.Collectors; + @Loggable(prepend = true, value = Loggable.DEBUG, trim = false) @Path("/v1/catalog") @@ -56,6 +72,7 @@ import java.util.Map; public class TypesFetchServlet extends AbstractValidationsServlet { private static final Logger log = Logger.getLogger(TypesFetchServlet.class); + private static final String FAILED_TO_GET_ALL_NON_ABSTRACT = "failed to get all non abstract {}"; @GET @Path("dataTypes") @@ -154,4 +171,188 @@ public class TypesFetchServlet extends AbstractValidationsServlet { return buildErrorResponse(responseFormat); } } + @GET + @Path("capabilityTypes") + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @ApiOperation(value = "Get capability types", httpMethod = "GET", notes = "Returns capability types", response = + Response.class) + @ApiResponses(value = {@ApiResponse(code = 200, message = "capabilityTypes"), + @ApiResponse(code = 403, message = "Restricted operation"), + @ApiResponse(code = 400, message = "Invalid content / Missing content"), + @ApiResponse(code = 404, message = "Capability types not found")}) + public Response getAllCapabilityTypesServlet(@Context final HttpServletRequest request, @HeaderParam(value = + Constants.USER_ID_HEADER) String userId) { + + Wrapper responseWrapper = new Wrapper<>(); + Wrapper userWrapper = new Wrapper<>(); + ServletContext context = request.getSession().getServletContext(); + + try { + init(); + validateUserExist(responseWrapper, userWrapper, userId); + + if (responseWrapper.isEmpty()) { + String url = request.getMethod() + " " + request.getRequestURI(); + log.debug("Start handle request of {} | modifier id is {}", url, userId); + + CapabilitiesBusinessLogic businessLogic = getCapabilitiesBL(context); + Either, ResponseFormat> allDataTypes = + businessLogic.getAllCapabilityTypes(); + + if (allDataTypes.isRight()) { + log.info("Failed to get all capability types. Reason - {}", allDataTypes.right().value()); + Response errorResponse = buildErrorResponse(allDataTypes.right().value()); + responseWrapper.setInnerElement(errorResponse); + + } else { + + Map dataTypes = allDataTypes.left().value(); + String dataTypeJson = gson.toJson(dataTypes); + Response okResponse = + buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), dataTypeJson); + responseWrapper.setInnerElement(okResponse); + + } + } + + return responseWrapper.getInnerElement(); + } catch (Exception e) { + BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Get Capability Types"); + log.debug("get all capability types failed with exception", e); + ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR); + return buildErrorResponse(responseFormat); + } + } + + @GET + @Path("relationshipTypes") + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @ApiOperation(value = "Get relationship types", httpMethod = "GET", notes = "Returns relationship types", response = + Response.class) + @ApiResponses(value = {@ApiResponse(code = 200, message = "relationshipTypes"), + @ApiResponse(code = 403, message = "Restricted operation"), + @ApiResponse(code = 400, message = "Invalid content / Missing content"), + @ApiResponse(code = 404, message = "Relationship types not found")}) + public Response getAllRelationshipTypesServlet(@Context final HttpServletRequest request, @HeaderParam(value = + Constants.USER_ID_HEADER) String userId) { + + Wrapper responseWrapper = new Wrapper<>(); + Wrapper userWrapper = new Wrapper<>(); + ServletContext context = request.getSession().getServletContext(); + + try { + init(); + validateUserExist(responseWrapper, userWrapper, userId); + + if (responseWrapper.isEmpty()) { + String url = request.getMethod() + " " + request.getRequestURI(); + log.debug("Start handle request of {} | modifier id is {}", url, userId); + + RelationshipTypeBusinessLogic businessLogic = getRelationshipTypeBL(context); + Either, ResponseFormat> allDataTypes = + businessLogic.getAllRelationshipTypes(); + + if (allDataTypes.isRight()) { + log.info("Failed to get all relationship types. Reason - {}", allDataTypes.right().value()); + Response errorResponse = buildErrorResponse(allDataTypes.right().value()); + responseWrapper.setInnerElement(errorResponse); + + } else { + + Map dataTypes = allDataTypes.left().value(); + String dataTypeJson = gson.toJson(dataTypes); + Response okResponse = + buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), dataTypeJson); + responseWrapper.setInnerElement(okResponse); + + } + } + + return responseWrapper.getInnerElement(); + } catch (Exception e) { + BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Get Relationship Types"); + log.debug("get all relationship types failed with exception", e); + ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR); + return buildErrorResponse(responseFormat); + } + } + + @GET + @Path("nodeTypes") + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @ApiOperation(value = "Get node types", httpMethod = "GET", notes = "Returns node types", response = Response.class) + @ApiResponses(value = {@ApiResponse(code = 200, message = "nodeTypes"), @ApiResponse(code = 403, message = + "Restricted operation"), @ApiResponse(code = 400, message = "Invalid content / Missing content"), + @ApiResponse(code = 404, message = "Node types not found")}) + public Response getAllNodeTypesServlet(@Context final HttpServletRequest request, @HeaderParam(value = + Constants.USER_ID_HEADER) String userId) { + + Wrapper responseWrapper = new Wrapper<>(); + Wrapper userWrapper = new Wrapper<>(); + ServletContext context = request.getSession().getServletContext(); + Either, Response> response; + Map componentMap; + + try { + init(); + validateUserExist(responseWrapper, userWrapper, userId); + + if (responseWrapper.isEmpty()) { + String url = request.getMethod() + " " + request.getRequestURI(); + log.debug("Start handle request of {} | modifier id is {}", url, userId); + + ComponentBusinessLogic resourceBL = getComponentBL(ComponentTypeEnum.RESOURCE, context); + response = getComponent(resourceBL, true, userId); + if (response.isRight()) { + return response.right().value(); + } + componentMap = new HashMap<>(response.left().value()); + + response = getComponent(resourceBL, false, userId); + if (response.isRight()) { + return response.right().value(); + } + componentMap.putAll(response.left().value()); + + String nodeTypesJson = gson.toJson(componentMap); + Response okResponse = + buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), nodeTypesJson); + responseWrapper.setInnerElement(okResponse); + } + + return responseWrapper.getInnerElement(); + } catch (Exception e) { + BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Get Node Types"); + log.debug("get all node types failed with exception", e); + ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR); + return buildErrorResponse(responseFormat); + } + } + + private Either, Response> getComponent(ComponentBusinessLogic resourceBL, boolean isAbstract, + String userId) { + Either, ResponseFormat> actionResponse; + List componentList; + + actionResponse = + resourceBL.getLatestVersionNotAbstractComponentsMetadata(isAbstract, HighestFilterEnum.HIGHEST_ONLY + , ComponentTypeEnum.RESOURCE, null, userId); + if (actionResponse.isRight()) { + log.debug(FAILED_TO_GET_ALL_NON_ABSTRACT, ComponentTypeEnum.RESOURCE.getValue()); + return Either.right(buildErrorResponse(actionResponse.right().value())); + } + + componentList = actionResponse.left().value(); + + return Either.left(ListUtils.emptyIfNull(componentList).stream() + .filter(component -> ((ResourceMetadataDataDefinition) component + .getComponentMetadataDefinition().getMetadataDataDefinition()).getToscaResourceName() != null) + .collect(Collectors.toMap( + component -> ((ResourceMetadataDataDefinition) component + .getComponentMetadataDefinition().getMetadataDataDefinition()).getToscaResourceName(), + component -> component, (component1, component2) -> component1))); + } } 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 a09e34fa9a..8ecda2ce61 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 @@ -34,6 +34,7 @@ import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum; import org.openecomp.sdc.be.model.DataTypeDefinition; import org.openecomp.sdc.be.model.GroupTypeDefinition; import org.openecomp.sdc.be.model.PolicyTypeDefinition; +import org.openecomp.sdc.be.model.RelationshipTypeDefinition; import org.openecomp.sdc.be.model.User; import org.openecomp.sdc.be.model.normatives.ToscaTypeMetadata; import org.openecomp.sdc.common.api.Constants; @@ -72,15 +73,18 @@ public class TypesUploadServlet extends AbstractValidationsServlet { private final DataTypeImportManager dataTypeImportManager; private final GroupTypeImportManager groupTypeImportManager; private final PolicyTypeImportManager policyTypeImportManager; + private final RelationshipTypeImportManager relationshipTypeImportManager; public TypesUploadServlet(CapabilityTypeImportManager capabilityTypeImportManager, InterfaceLifecycleTypeImportManager interfaceLifecycleTypeImportManager, CategoriesImportManager categoriesImportManager, DataTypeImportManager dataTypeImportManager, - GroupTypeImportManager groupTypeImportManager, PolicyTypeImportManager policyTypeImportManager) { + GroupTypeImportManager groupTypeImportManager, PolicyTypeImportManager policyTypeImportManager, + RelationshipTypeImportManager relationshipTypeImportManager) { this.capabilityTypeImportManager = capabilityTypeImportManager; this.interfaceLifecycleTypeImportManager = interfaceLifecycleTypeImportManager; this.categoriesImportManager = categoriesImportManager; this.dataTypeImportManager = dataTypeImportManager; this.groupTypeImportManager = groupTypeImportManager; this.policyTypeImportManager = policyTypeImportManager; + this.relationshipTypeImportManager = relationshipTypeImportManager; } @POST @@ -93,6 +97,21 @@ public class TypesUploadServlet extends AbstractValidationsServlet { return uploadElementTypeServletLogic(createElementsMethod, file, request, creator, NodeTypeEnum.CapabilityType.name()); } + @POST + @Path("/relationship") + @ApiOperation(value = "Create Relationship Type from yaml", httpMethod = "POST", + notes = "Returns created Relationship Type", response = Response.class) + @ApiResponses(value = {@ApiResponse(code = 201, message = "Relationship Type created"), + @ApiResponse(code = 403, message = "Restricted operation"), + @ApiResponse(code = 400, message = "Invalid content / Missing content"), + @ApiResponse(code = 409, message = "Relationship Type already exist")}) + public Response uploadRelationshipType(@ApiParam("FileInputStream") @FormDataParam("relationshipTypeZip") File file, + @Context final HttpServletRequest request, + @HeaderParam("USER_ID") String creator) { + return uploadElementTypeServletLogic(this::createRelationshipTypes, file, request, creator, + NodeTypeEnum.RelationshipType.getName()); + } + @POST @Path("/interfaceLifecycle") @ApiOperation(value = "Create Interface Lyfecycle Type from yaml", httpMethod = "POST", notes = "Returns created Interface Lifecycle Type", response = Response.class) @@ -299,6 +318,13 @@ public class TypesUploadServlet extends AbstractValidationsServlet { } } } - + // relationship types + private void createRelationshipTypes(Wrapper responseWrapper, String relationshipTypesYml) { + final Supplier>, ResponseFormat>> + generateElementTypeFromYml = + () -> relationshipTypeImportManager.createRelationshipTypes(relationshipTypesYml); + buildStatusForElementTypeCreate(responseWrapper, generateElementTypeFromYml, + ActionStatus.RELATIONSHIP_TYPE_ALREADY_EXIST, NodeTypeEnum.RelationshipType.name()); + } } diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/CapabilityRequirementConverter.java b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/CapabilityRequirementConverter.java index 04119fed7b..bd797c970b 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/CapabilityRequirementConverter.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/CapabilityRequirementConverter.java @@ -258,22 +258,22 @@ public class CapabilityRequirementConverter { private Either, ToscaError> buildAddSubstitutionMappingsCapabilities(Map componentsCache, Component component, Map> capabilities) { - Map toscaRequirements = new HashMap<>(); + Map toscaCapabilities = new HashMap<>(); Either, ToscaError> result = null; for (Map.Entry> entry : capabilities.entrySet()) { Optional failedToAddRequirement = entry.getValue() .stream() - .filter(c->!addEntry(componentsCache, toscaRequirements, component, new SubstitutionEntry(c.getName(), c.getParentName(), ""), c.getPreviousName(), c.getOwnerId(), c.getPath())) + .filter(c->!addEntry(componentsCache, toscaCapabilities, component, new SubstitutionEntry(c.getName(), c.getParentName(), ""), c.getPreviousName(), c.getOwnerId(), c.getPath())) .findAny(); if(failedToAddRequirement.isPresent()){ - logger.debug("Failed to convert capalility {} for substitution mappings section of a tosca template of the component {}. ", + logger.debug("Failed to convert capability {} for substitution mappings section of a tosca template of the component {}. ", failedToAddRequirement.get().getName(), component.getName()); result = Either.right(ToscaError.NODE_TYPE_CAPABILITY_ERROR); } - logger.debug("Finish convert capalilities for the component {}. ", component.getName()); + logger.debug("Finish convert capabilities for the component {}. ", component.getName()); } if(result == null){ - result = Either.left(toscaRequirements); + result = Either.left(toscaCapabilities); } return result; } @@ -284,7 +284,7 @@ public class CapabilityRequirementConverter { return false; } logger.debug("The requirement/capability {} belongs to the component {} ", entry.getFullName(), component.getUniqueId()); - if (entry.getSourceName() != null) { + if (StringUtils.isNotEmpty(entry.getSourceName())) { addEntry(capReqMap, component, path, entry); } logger.debug("Finish convert the requirement/capability {} for the component {}. ", entry.getFullName(), component.getName()); @@ -318,14 +318,15 @@ public class CapabilityRequirementConverter { } } - Optional ci = component.getComponentInstances().stream().filter(c->c.getUniqueId().equals(Iterables.getLast(path))).findFirst(); + Optional ci = + component.safeGetComponentInstances().stream().filter(c->c.getUniqueId().equals(Iterables.getLast(path))).findFirst(); if(!ci.isPresent()){ logger.debug("Failed to find ci in the path is {} component {}", path, component.getUniqueId()); Collections.reverse(path); logger.debug("try to reverse path {} component {}", path, component.getUniqueId()); - ci = component.getComponentInstances().stream().filter(c->c.getUniqueId().equals(Iterables.getLast(path))).findFirst(); + ci = component.safeGetComponentInstances().stream().filter(c->c.getUniqueId().equals(Iterables.getLast(path))).findFirst(); } if(ci.isPresent()){ prefix = buildCapReqNamePrefix(ci.get().getNormalizedName()); @@ -352,10 +353,10 @@ public class CapabilityRequirementConverter { private void addEntry(Map toscaRequirements, Component component, List capPath, SubstitutionEntry entry) { Optional findFirst = component.safeGetComponentInstances().stream().filter(ci -> ci.getUniqueId().equals(Iterables.getLast(capPath))).findFirst(); - if (findFirst.isPresent()) { - entry.setOwner(findFirst.get().getNormalizedName()); + findFirst.ifPresent(componentInstance -> entry.setOwner(componentInstance.getName())); + if (StringUtils.isNotEmpty(entry.getOwner()) && StringUtils.isNotEmpty(entry.getSourceName())) { + toscaRequirements.put(entry.getFullName(), new String[] { entry.getOwner(), entry.getSourceName() }); } - toscaRequirements.put(entry.getFullName(), new String[] { entry.getOwner(), entry.getSourceName() }); } public Either buildSubstitutedName(Map componentsCache, String name, String previousName, List path, String ownerId, ComponentInstance instance) { @@ -469,31 +470,9 @@ public class CapabilityRequirementConverter { return buildCapReqNamePerOwnerByPath(componentsCache, component, c.getName(), c.getPreviousName(), c.getPath()); } - private void convertProxyCapability(Map toscaCapabilities, CapabilityDefinition c, Map dataTypes, String capabilityName) { - ToscaCapability toscaCapability = new ToscaCapability(); - toscaCapability.setDescription(c.getDescription()); - toscaCapability.setType(c.getType()); - - List occurrences = new ArrayList<>(); - occurrences.add(Integer.valueOf(c.getMinOccurrences())); - if (c.getMaxOccurrences().equals(CapabilityDataDefinition.MAX_OCCURRENCES)) { - occurrences.add(c.getMaxOccurrences()); - } else { - occurrences.add(Integer.valueOf(c.getMaxOccurrences())); - } - toscaCapability.setOccurrences(occurrences); - - toscaCapability.setValid_source_types(c.getValidSourceTypes()); - List properties = c.getProperties(); - if (isNotEmpty(properties)) { - Map toscaProperties = new HashMap<>(); - for (PropertyDefinition property : properties) { - ToscaProperty toscaProperty = PropertyConvertor.getInstance().convertProperty(dataTypes, property, PropertyConvertor.PropertyType.CAPABILITY); - toscaProperties.put(property.getName(), toscaProperty); - } - toscaCapability.setProperties(toscaProperties); - } - toscaCapabilities.put(capabilityName, toscaCapability); + private void convertProxyCapability(Map toscaCapabilities, CapabilityDefinition c, + Map dataTypes, String capabilityName) { + createToscaCapability(toscaCapabilities, c, dataTypes, capabilityName); } private void convertCapability(Map componentsCache, Component component, Map toscaCapabilities, boolean isNodeType, CapabilityDefinition c, Map dataTypes , String capabilityName) { @@ -502,6 +481,11 @@ public class CapabilityRequirementConverter { name = buildCapNamePerOwnerByPath(componentsCache, c, component); } logger.debug("The capability {} belongs to resource {} ", name, component.getUniqueId()); + createToscaCapability(toscaCapabilities, c, dataTypes, name); + } + + private void createToscaCapability(Map toscaCapabilities, CapabilityDefinition c, + Map dataTypes, String name) { ToscaCapability toscaCapability = new ToscaCapability(); toscaCapability.setDescription(c.getDescription()); toscaCapability.setType(c.getType()); @@ -529,6 +513,9 @@ public class CapabilityRequirementConverter { } private String buildCapReqNamePerOwnerByPath(Map componentsCache, Component component, String name, String previousName, List path) { + if (CollectionUtils.isEmpty(path)) { + return name; + } String ownerId = path.get(path.size() - 1); String prefix; if(CollectionUtils.isNotEmpty(component.getGroups())) { @@ -541,14 +528,14 @@ public class CapabilityRequirementConverter { return name; } } - Optional ci = component.getComponentInstances().stream().filter(c->c.getUniqueId().equals(Iterables.getLast(path))).findFirst(); + Optional ci = component.safeGetComponentInstances().stream().filter(c->c.getUniqueId().equals(Iterables.getLast(path))).findFirst(); if(!ci.isPresent()){ logger.debug("Failed to find ci in the path is {} component {}", path, component.getUniqueId()); Collections.reverse(path); logger.debug("try to reverse path {} component {}", path, component.getUniqueId()); - ci = component.getComponentInstances().stream().filter(c->c.getUniqueId().equals(Iterables.getLast(path))).findFirst(); + ci = component.safeGetComponentInstances().stream().filter(c->c.getUniqueId().equals(Iterables.getLast(path))).findFirst(); } if(ci.isPresent()){ prefix = buildCapReqNamePrefix(ci.get().getNormalizedName()); diff --git a/catalog-be/src/main/resources/import/tosca/relationship-types/relationshipTypes.yml b/catalog-be/src/main/resources/import/tosca/relationship-types/relationshipTypes.yml index 4506fa1b97..f446f21a62 100644 --- a/catalog-be/src/main/resources/import/tosca/relationship-types/relationshipTypes.yml +++ b/catalog-be/src/main/resources/import/tosca/relationship-types/relationshipTypes.yml @@ -15,18 +15,22 @@ tosca.relationships.Root: Configure: type: tosca.interfaces.relationship.Configure +tosca.relationships.ConnectsTo: + derived_from: tosca.relationships.Root + description: This type represents a network connection relationship between two nodes. + valid_target_types: + - tosca.capabilities.Endpoint + properties: + credential: + type: tosca.datatypes.Credential + required: false + tosca.relationships.RoutesTo: derived_from: tosca.relationships.ConnectsTo description: This type represents an intentional network routing between two Endpoints in different networks. valid_target_types: - tosca.capabilities.Endpoint -tosca.relationships.network.LinksTo: - derived_from: tosca.relationships.DependsOn - description: This relationship type represents an association relationship between Port and Network node types. - valid_target_types: - - tosca.capabilities.network.Linkable - tosca.relationships.AttachesTo: derived_from: tosca.relationships.Root description: This type represents an attachment relationship between two nodes. For example, an AttachesTo relationship type would be used for attaching a storage node to a Compute node. @@ -52,12 +56,6 @@ tosca.relationships.AttachesTo: orchestrator.' type: string -tosca.relationships.network.BindsTo: - derived_from: tosca.relationships.DependsOn - description: This type represents a network association relationship between Port and Compute node types. - valid_target_types: - - tosca.capabilities.network.Bindable - tosca.relationships.HostedOn: derived_from: tosca.relationships.Root description: This type represents a hosting relationship between two nodes. @@ -70,15 +68,27 @@ tosca.relationships.DependsOn: valid_target_types: - tosca.capabilities.Node -tosca.relationships.ConnectsTo: - derived_from: tosca.relationships.Root - description: This type represents a network connection relationship between two nodes. +tosca.relationships.network.LinksTo: + derived_from: tosca.relationships.DependsOn + description: This relationship type represents an association relationship between Port and Network node types. valid_target_types: - - tosca.capabilities.Endpoint - properties: - credential: - type: tosca.datatypes.Credential - required: false + - tosca.capabilities.network.Linkable + +tosca.relationships.network.BindsTo: + derived_from: tosca.relationships.DependsOn + description: This type represents a network association relationship between Port and Compute node types. + valid_target_types: + - tosca.capabilities.network.Bindable + +org.openecomp.relationships.AttachesTo: + derived_from: tosca.relationships.AttachesTo + description: This type represents an attachment relationship + properties: + location: + description: The relative location (e.g., path on the file system), which provides the root location to address an attached node. + type: string + status: SUPPORTED + required: false org.openecomp.relationships.VolumeAttachesTo: derived_from: org.openecomp.relationships.AttachesTo @@ -100,15 +110,6 @@ org.openecomp.relationships.VolumeAttachesTo: type: string status: SUPPORTED -org.openecomp.relationships.AttachesTo: - derived_from: tosca.relationships.AttachesTo - description: This type represents an attachment relationship - properties: - location: - description: The relative location (e.g., path on the file system), which provides the root location to address an attached node. - type: string - status: SUPPORTED - required: false org.openecomp.relationships.ForwardsTo: derived_from: tosca.relationships.Root valid_target_types: [org.openecomp.capabilities.Forwarder] diff --git a/catalog-be/src/main/resources/scripts/import/tosca/importNormativeAll.py b/catalog-be/src/main/resources/scripts/import/tosca/importNormativeAll.py index 8a8329027f..19ffc1762f 100644 --- a/catalog-be/src/main/resources/scripts/import/tosca/importNormativeAll.py +++ b/catalog-be/src/main/resources/scripts/import/tosca/importNormativeAll.py @@ -8,6 +8,7 @@ from importNormativeElements import * from importNormativeTypes import importNormativeTypes from importHeatTypes import importHeatTypes from importNormativeCapabilities import importNormativeCapabilities +from importNormativeRelationships import importNormativeRelationships from importCategoryTypes import importCategories from importNormativeInterfaceLifecycleTypes import importNormativeInterfaceLifecycleType from importDataTypes import importDataTypes @@ -116,6 +117,9 @@ def main(argv): fileLocation = baseFileLocation + "capability-types/" importNormativeCapabilities(scheme, beHost, bePort, adminUser, False, fileLocation) + fileLocation = baseFileLocation + "relationship-types/" + importNormativeRelationships(scheme, beHost, bePort, adminUser, False, fileLocation) + fileLocation = baseFileLocation + "interface-lifecycle-types/" importNormativeInterfaceLifecycleType(scheme, beHost, bePort, adminUser, False, fileLocation) diff --git a/catalog-be/src/main/resources/scripts/import/tosca/importNormativeRelationships.py b/catalog-be/src/main/resources/scripts/import/tosca/importNormativeRelationships.py new file mode 100644 index 0000000000..a86e520558 --- /dev/null +++ b/catalog-be/src/main/resources/scripts/import/tosca/importNormativeRelationships.py @@ -0,0 +1,83 @@ +import pycurl +import sys, getopt +from StringIO import StringIO +import json +import copy +from importNormativeElements import createNormativeElement +from importCommon import * +import importCommon + +################################################################################################################################################################################################# +# # +# Import normative relationships +# # +# # +# activation : # +# python importNormativeRelationships.py [-s | --scheme= ] [-i | --ip=] [-p +# | --port= ] [-f | --ifile= ] # +# # +# shortest activation (be host = localhost, be port = 8080): # +# python importNormativeRelationships.py [-f | --ifile= ] +# # +# # +################################################################################################################################################################################################# + + +def usage(): + print sys.argv[0], '[optional -s | --scheme=, default http] [-i | --ip=] [-p | --port= ] [-u | --user= ]' + + +def importNormativeRelationships(scheme, beHost, bePort, adminUser, exitOnSuccess, fileDir): + result = createNormativeElement(scheme, beHost, bePort, adminUser, fileDir, "/sdc2/rest/v1/catalog/uploadType/relationship", "relationshipTypes", "relationshipTypeZip") + + print_frame_line() + print_name_and_return_code(result[0], result[1]) + print_frame_line() + + if ( result[1] == None or result[1] not in [200, 201, 409] ): + importCommon.error_and_exit(1, None) + else: + if (exitOnSuccess == True): + importCommon.error_and_exit(0, None) + + +def main(argv): + print 'Number of arguments:', len(sys.argv), 'arguments.' + + beHost = 'localhost' + bePort = '8080' + adminUser = 'jh0003' + scheme = 'http' + + try: + opts, args = getopt.getopt(argv,"i:p:u:h:s:",["ip=","port=","user=","scheme="]) + except getopt.GetoptError: + usage() + importCommon.error_and_exit(2, 'Invalid input') + + for opt, arg in opts: + #print opt, arg + if opt == '-h': + usage() + sys.exit(3) + elif opt in ("-i", "--ip"): + beHost = arg + elif opt in ("-p", "--port"): + bePort = arg + elif opt in ("-u", "--user"): + adminUser = arg + elif opt in ("-s", "--scheme"): + scheme = arg + + print 'scheme =',scheme,', be host =',beHost,', be port =', bePort,', user =', adminUser + + if ( beHost == None ): + usage() + sys.exit(3) + + importNormativeRelationships(scheme, beHost, bePort, adminUser, True, "../../../import/tosca/relationship-types/") + + +if __name__ == "__main__": + main(sys.argv[1:]) + diff --git a/catalog-be/src/main/resources/scripts/import/tosca/importONAPNormativeAll.py b/catalog-be/src/main/resources/scripts/import/tosca/importONAPNormativeAll.py index ef1fe4d3b9..30b5a5435d 100644 --- a/catalog-be/src/main/resources/scripts/import/tosca/importONAPNormativeAll.py +++ b/catalog-be/src/main/resources/scripts/import/tosca/importONAPNormativeAll.py @@ -12,6 +12,7 @@ from importNfvTypes import importNfvTypes from importOnapTypes import importOnapTypes from importSolTypes import importSolTypes from importNormativeCapabilities import importNormativeCapabilities +from importNormativeRelationships import importNormativeRelationships from importCategoryTypes import importCategories from importNormativeInterfaceLifecycleTypes import importNormativeInterfaceLifecycleType from importDataTypes import importDataTypes @@ -111,12 +112,15 @@ def main(argv): print 'sleep until data type cache is updated' time.sleep( 70 ) - + fileLocation = baseFileLocation + "capability-types/" importNormativeCapabilities(scheme, beHost, bePort, adminUser, False, fileLocation) + + fileLocation = baseFileLocation + "relationship-types/" + importNormativeRelationships(scheme, beHost, bePort, adminUser, False, fileLocation) fileLocation = baseFileLocation + "interface-lifecycle-types/" - importNormativeInterfaceLifecycleType(scheme, beHost, bePort, adminUser, False, fileLocation) + importNormativeInterfaceLifecycleType(scheme, beHost, bePort, adminUser, False, fileLocation) fileLocation = baseFileLocation + "categories/" importCategories(scheme, beHost, bePort, adminUser, False, fileLocation) diff --git a/catalog-be/src/main/resources/scripts/import/tosca/upgradeNormative.py b/catalog-be/src/main/resources/scripts/import/tosca/upgradeNormative.py index bbeb3d6972..36a5d1181a 100644 --- a/catalog-be/src/main/resources/scripts/import/tosca/upgradeNormative.py +++ b/catalog-be/src/main/resources/scripts/import/tosca/upgradeNormative.py @@ -10,6 +10,7 @@ from importDataTypes import importDataTypes from importPolicyTypes import importPolicyTypes from importGroupTypes import importGroupTypes from importNormativeCapabilities import importNormativeCapabilities +from importNormativeRelationships import importNormativeRelationships from importNormativeInterfaceLifecycleTypes import importNormativeInterfaceLifecycleType from importAnnotationTypes import import_annotation_types @@ -96,6 +97,9 @@ def main(argv): fileLocation = baseFileLocation + "categories/" importCategories(scheme, beHost, bePort, adminUser, False, fileLocation) + fileLocation = baseFileLocation + "relationship-types/" + importNormativeRelationships(scheme, beHost, bePort, adminUser, False, fileLocation) + fileLocation = baseFileLocation + "data-types/" importDataTypes(scheme, beHost, bePort, adminUser, False, fileLocation) diff --git a/catalog-be/src/main/resources/scripts/import/tosca/upgradeONAPNormative.py b/catalog-be/src/main/resources/scripts/import/tosca/upgradeONAPNormative.py index bebba6c2cb..c6d217f986 100644 --- a/catalog-be/src/main/resources/scripts/import/tosca/upgradeONAPNormative.py +++ b/catalog-be/src/main/resources/scripts/import/tosca/upgradeONAPNormative.py @@ -10,6 +10,7 @@ from importDataTypes import importDataTypes from importPolicyTypes import importPolicyTypes from importGroupTypes import importGroupTypes from importNormativeCapabilities import importNormativeCapabilities +from importNormativeRelationships import importNormativeRelationships from importNormativeInterfaceLifecycleTypes import importNormativeInterfaceLifecycleType from upgradeNfvTypes import upgradeNfvTypesPerConfigFile from upgradeONAPTypes import upgradeOnapTypesPerConfigFile @@ -101,6 +102,9 @@ def main(argv): fileLocation = baseFileLocation + "categories/" importCategories(scheme, beHost, bePort, adminUser, False, fileLocation) + fileLocation = baseFileLocation + "relationship-types/" + importNormativeRelationships(scheme, beHost, bePort, adminUser, False, fileLocation) + fileLocation = baseFileLocation + "data-types/" importDataTypes(scheme, beHost, bePort, adminUser, False, fileLocation) diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/CapabilitiesBusinessLogicTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/CapabilitiesBusinessLogicTest.java new file mode 100644 index 0000000000..393ef58d1d --- /dev/null +++ b/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/CapabilitiesBusinessLogicTest.java @@ -0,0 +1,443 @@ +/* + * Copyright © 2016-2018 European Support Limited + * + * 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. + */ + +package org.openecomp.sdc.be.components.impl; + +import fj.data.Either; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.mockito.InjectMocks; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; +import org.openecomp.sdc.be.auditing.impl.AuditingManager; +import org.openecomp.sdc.be.components.validation.CapabilitiesValidation; +import org.openecomp.sdc.be.components.validation.UserValidations; +import org.openecomp.sdc.be.config.ConfigurationManager; +import org.openecomp.sdc.be.dao.api.ActionStatus; +import org.openecomp.sdc.be.dao.jsongraph.TitanDao; +import org.openecomp.sdc.be.dao.titan.TitanOperationStatus; +import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum; +import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum; +import org.openecomp.sdc.be.impl.ComponentsUtils; +import org.openecomp.sdc.be.model.CapabilityDefinition; +import org.openecomp.sdc.be.model.CapabilityRequirementRelationship; +import org.openecomp.sdc.be.model.ComponentParametersView; +import org.openecomp.sdc.be.model.LifecycleStateEnum; +import org.openecomp.sdc.be.model.RelationshipInfo; +import org.openecomp.sdc.be.model.RequirementCapabilityRelDef; +import org.openecomp.sdc.be.model.Resource; +import org.openecomp.sdc.be.model.Service; +import org.openecomp.sdc.be.model.User; +import org.openecomp.sdc.be.model.jsontitan.operations.CapabilitiesOperation; +import org.openecomp.sdc.be.model.jsontitan.operations.ToscaOperationFacade; +import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus; +import org.openecomp.sdc.be.model.operations.impl.GraphLockOperation; +import org.openecomp.sdc.be.user.Role; +import org.openecomp.sdc.be.user.UserBusinessLogic; +import org.openecomp.sdc.common.api.ConfigurationSource; +import org.openecomp.sdc.common.impl.ExternalConfiguration; +import org.openecomp.sdc.common.impl.FSConfigurationSource; +import org.openecomp.sdc.exception.ResponseFormat; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.anyCollection; +import static org.mockito.ArgumentMatchers.anyObject; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.when; + +public class CapabilitiesBusinessLogicTest { + private final String componentId = "resourceId1"; + private final String capabilityId = "uniqueId1"; + + private final TitanDao mockTitanDao = Mockito.mock(TitanDao.class); + private final UserBusinessLogic mockUserAdmin = Mockito.mock(UserBusinessLogic.class); + private final ToscaOperationFacade toscaOperationFacade = Mockito.mock(ToscaOperationFacade.class); + private final UserValidations userValidations = Mockito.mock(UserValidations.class); + private final CapabilitiesOperation capabilitiesOperation = Mockito.mock(CapabilitiesOperation.class); + private final CapabilitiesValidation capabilitiesValidation = Mockito.mock(CapabilitiesValidation.class); + + private final GraphLockOperation graphLockOperation = Mockito.mock(GraphLockOperation.class); + private User user = null; + + @InjectMocks + private CapabilitiesBusinessLogic capabilitiesBusinessLogicMock = new CapabilitiesBusinessLogic(); + + @Before + public void setup() { + MockitoAnnotations.initMocks(this); + ExternalConfiguration.setAppName("catalog-be"); + + // init Configuration + String appConfigDir = "src/test/resources/config/catalog-be"; + ConfigurationSource configurationSource = new FSConfigurationSource(ExternalConfiguration.getChangeListener(), appConfigDir); + ConfigurationManager configurationManager = new ConfigurationManager(configurationSource); + + ComponentsUtils componentsUtils = new ComponentsUtils(Mockito.mock(AuditingManager.class)); + + // User data and management + user = new User(); + user.setUserId("jh0003"); + user.setFirstName("Jimmi"); + user.setLastName("Hendrix"); + user.setRole(Role.ADMIN.name()); + + Either eitherGetUser = Either.left(user); + when(mockUserAdmin.getUser("jh0003", false)).thenReturn(eitherGetUser); + when(graphLockOperation.lockComponent(Mockito.anyString(), eq(NodeTypeEnum.Resource))) + .thenReturn(StorageOperationStatus.OK); + + //CapabilityOperation + when(capabilitiesValidation.validateCapabilities(anyCollection(), anyObject(), anyBoolean()) + ).thenReturn(Either.left(true)); + when(capabilitiesOperation.addCapabilities(anyString(), anyObject())) + .thenReturn(Either.left(createMockCapabilityListToReturn( + createCapability("capName", "capDesc", "capType", "source1", + "0", "10")))); + + when(capabilitiesOperation.updateCapabilities(anyString(), anyObject())) + .thenReturn(Either.left(createMockCapabilityListToReturn( + createCapability("capName", "capDesc", "capType", "source1", + "0", "10")))); + when(capabilitiesOperation.deleteCapabilities( anyObject(), anyString())) + .thenReturn(StorageOperationStatus.OK); + when(mockTitanDao.commit()).thenReturn(TitanOperationStatus.OK); + + capabilitiesBusinessLogicMock = new CapabilitiesBusinessLogic(); + capabilitiesBusinessLogicMock.setComponentsUtils(componentsUtils); + capabilitiesBusinessLogicMock.setUserAdmin(mockUserAdmin); + capabilitiesBusinessLogicMock.setGraphLockOperation(graphLockOperation); + capabilitiesBusinessLogicMock.setTitanGenericDao(mockTitanDao); + capabilitiesBusinessLogicMock.setToscaOperationFacade(toscaOperationFacade); + capabilitiesBusinessLogicMock.setUserValidations(userValidations); + capabilitiesBusinessLogicMock.setCapabilitiesOperation(capabilitiesOperation); + capabilitiesBusinessLogicMock.setCapabilitiesValidation(capabilitiesValidation); + } + + @Test + public void shouldPassCreateCapabilitiesFirstTimeInComponentForHappyScenario(){ + List capabilityDefinitions = createMockCapabilityListToReturn( + createCapability("capName", "capDesc", "capType", "source1", + "0", "10")); + Resource resource = createComponent(false); + resource.setComponentType(ComponentTypeEnum.RESOURCE); + validateUserRoles(Role.ADMIN, Role.DESIGNER); + when(toscaOperationFacade.getToscaElement(anyString(), any(ComponentParametersView.class))) + .thenReturn(Either.left(resource)); + Either, ResponseFormat> capabilities = capabilitiesBusinessLogicMock + .createCapabilities(componentId, capabilityDefinitions, user, + "createCapabilities", true); + Assert.assertTrue(capabilities.isLeft()); + Assert.assertTrue(capabilities.left().value().stream().anyMatch(capabilityDefinition -> + capabilityDefinition.getName().equals("capName"))); + } + + @Test + public void shouldPassCreateCapabilitiesForHappyScenario(){ + List capabilityDefinitions = createMockCapabilityListToReturn( + createCapability("capName2", "capDesc", "capType", "source1", + "0", "10")); + Resource resource = createComponent(true); + resource.setComponentType(ComponentTypeEnum.RESOURCE); + validateUserRoles(Role.ADMIN, Role.DESIGNER); + when(toscaOperationFacade.getToscaElement(anyString(), any(ComponentParametersView.class))) + .thenReturn(Either.left(resource)); + Either, ResponseFormat> capabilities = capabilitiesBusinessLogicMock + .createCapabilities(componentId, capabilityDefinitions, user, + "createCapabilities", false); + + Assert.assertTrue(capabilities.isLeft()); + Assert.assertTrue(capabilities.left().value().stream().anyMatch(capabilityDefinition -> + capabilityDefinition.getName().equals("capName2"))); + } + + @Test + public void shouldFailCreateCapabilitiesWhenOperationFailedInTitan(){ + List capabilityDefinitions = createMockCapabilityListToReturn( + createCapability("capName2", "capDesc", "capType", "source1", + "0", "10")); + Resource resource = createComponent(true); + resource.setComponentType(ComponentTypeEnum.RESOURCE); + validateUserRoles(Role.ADMIN, Role.DESIGNER); + when(capabilitiesOperation.addCapabilities(anyString(), anyObject())) + .thenReturn(Either.right(StorageOperationStatus.GENERAL_ERROR)); + when(capabilitiesOperation.updateCapabilities(anyString(), anyObject())) + .thenReturn(Either.right(StorageOperationStatus.GENERAL_ERROR)); + when(toscaOperationFacade.getToscaElement(anyString(), any(ComponentParametersView.class))) + .thenReturn(Either.left(resource)); + Either, ResponseFormat> capabilities = capabilitiesBusinessLogicMock + .createCapabilities(componentId, capabilityDefinitions, user, + "createCapabilities", true); + + Assert.assertTrue(capabilities.isRight()); + } + @Test + public void shouldPassUpdateCapabilitiesForHappyScenario(){ + + List capabilityDefinitions = createMockCapabilityListToReturn( + createCapability("capName", "capDesc updated", "capType", "source1", + "6", "11")); + Resource resource = createComponent(true); + resource.setComponentType(ComponentTypeEnum.RESOURCE); + validateUserRoles(Role.ADMIN, Role.DESIGNER); + when(toscaOperationFacade.getToscaElement(anyString(), any(ComponentParametersView.class))) + .thenReturn(Either.left(resource)); + when(toscaOperationFacade.getParentComponents(anyString())) + .thenReturn(Either.right(StorageOperationStatus.NOT_FOUND)); + Either, ResponseFormat> capabilities = capabilitiesBusinessLogicMock + .updateCapabilities(componentId, capabilityDefinitions, user + , "updateCapabilities", true); + Assert.assertTrue(capabilities.isLeft()); + Assert.assertTrue(capabilities.left().value().stream().anyMatch(capabilityDefinition -> + capabilityDefinition.getMaxOccurrences().equals("11"))); + } + + @Test + public void shouldPassUpdateCapabilityTypeUpdateWhenTypeIsNotAvailable(){ + + List capabilityDefinitions = createMockCapabilityListToReturn( + createCapability("capName", "capDesc updated", "capTypeUpdate", "source1", + "6", "11")); + Resource resource = createComponent(true); + resource.setComponentType(ComponentTypeEnum.RESOURCE); + validateUserRoles(Role.ADMIN, Role.DESIGNER); + when(toscaOperationFacade.getToscaElement(anyString(), any(ComponentParametersView.class))) + .thenReturn(Either.left(resource)); + when(toscaOperationFacade.getParentComponents(anyString())) + .thenReturn(Either.right(StorageOperationStatus.NOT_FOUND)); + Either, ResponseFormat> capabilities = capabilitiesBusinessLogicMock + .updateCapabilities(componentId, capabilityDefinitions, user, + "updateCapabilities",true); + Assert.assertTrue(capabilities.isLeft()); + Assert.assertTrue(capabilities.left().value().stream().anyMatch(capabilityDefinition -> + capabilityDefinition.getMaxOccurrences().equals("11"))); + } + + @Test + public void shouldPassUpdateCapabilityTypeUpdateWhenTypeIsAvailable(){ + + List capabilityDefinitions = createMockCapabilityListToReturn( + createCapability("capName", "capDesc updated", "capTypeUpdate1", "source1", + "6", "11")); + Resource resource = createComponent(true); + resource.setComponentType(ComponentTypeEnum.RESOURCE); + + CapabilityDefinition capability = createCapability("capName", "capDesc", "capTypeUpdate1", + "source1", "0", "10"); + capability.setUniqueId("unique2"); + List capabilityDefinitions1 = createMockCapabilityListToReturn(capability); + Map> capabilityMap = new HashMap<>(); + capabilityMap.put("capTypeUpdate1", capabilityDefinitions1); + resource.getCapabilities().putAll(capabilityMap); + + validateUserRoles(Role.ADMIN, Role.DESIGNER); + when(toscaOperationFacade.getToscaElement(anyString(), any(ComponentParametersView.class))) + .thenReturn(Either.left(resource)); + when(toscaOperationFacade.getParentComponents(anyString())) + .thenReturn(Either.right(StorageOperationStatus.NOT_FOUND)); + Either, ResponseFormat> capabilities = capabilitiesBusinessLogicMock + .updateCapabilities(componentId, capabilityDefinitions, user, + "updateCapabilities",true); + Assert.assertTrue(capabilities.isLeft()); + Assert.assertTrue(capabilities.left().value().stream().anyMatch(capabilityDefinition -> + capabilityDefinition.getMaxOccurrences().equals("11"))); + } + + @Test + public void shouldFailUpdateCapabilitiesWhenOperaitonFailedInTitan(){ + List capabilityDefinitions = createMockCapabilityListToReturn( + createCapability("capName2", "capDesc", "capType", "source1", + "0", "10")); + Resource resource = createComponent(true); + resource.setComponentType(ComponentTypeEnum.RESOURCE); + validateUserRoles(Role.ADMIN, Role.DESIGNER); + when(capabilitiesOperation.addCapabilities(anyString(), anyObject())) + .thenReturn(Either.right(StorageOperationStatus.GENERAL_ERROR)); + when(capabilitiesOperation.updateCapabilities(anyString(), anyObject())) + .thenReturn(Either.right(StorageOperationStatus.GENERAL_ERROR)); + when(toscaOperationFacade.getToscaElement(anyString(), any(ComponentParametersView.class))) + .thenReturn(Either.left(resource)); + Either, ResponseFormat> capabilities = capabilitiesBusinessLogicMock + .updateCapabilities(componentId, capabilityDefinitions, user, + "updateCapabilities", true); + + Assert.assertTrue(capabilities.isRight()); + } + + @Test + public void shouldPassDeleteCapabilitiesForHappyScenario(){ + Resource resource = createComponent(true); + resource.setComponentType(ComponentTypeEnum.RESOURCE); + validateUserRoles(Role.ADMIN, Role.DESIGNER); + when(toscaOperationFacade.getToscaElement(anyString(), any(ComponentParametersView.class))) + .thenReturn(Either.left(resource)); + when(toscaOperationFacade.getParentComponents(anyString())) + .thenReturn(Either.right(StorageOperationStatus.NOT_FOUND)); + Either deleteCapabilityEither = + capabilitiesBusinessLogicMock.deleteCapability(componentId, capabilityId, user, true); + Assert.assertTrue(deleteCapabilityEither.isLeft()); + + } + + @Test + public void shouldFailDeleteCapabilitiesWhenOperationFailedInTitan(){ + Resource resource = createComponent(true); + resource.setComponentType(ComponentTypeEnum.RESOURCE); + validateUserRoles(Role.ADMIN, Role.DESIGNER); + when(toscaOperationFacade.getToscaElement(anyString(), any(ComponentParametersView.class))) + .thenReturn(Either.left(resource)); + when(toscaOperationFacade.getParentComponents(anyString())) + .thenReturn(Either.right(StorageOperationStatus.NOT_FOUND)); + when(capabilitiesOperation.deleteCapabilities(anyObject(), anyString())) + .thenReturn(StorageOperationStatus.GENERAL_ERROR); + Either deleteCapabilityEither + = capabilitiesBusinessLogicMock.deleteCapability(componentId, capabilityId, user, true); + Assert.assertTrue(deleteCapabilityEither.isRight()); + } + + @Test + public void shouldFailDeleteCapabilitiesWhenCapabilityUsedInServiceComposition(){ + Resource resource = createComponent(true); + resource.setComponentType(ComponentTypeEnum.RESOURCE); + validateUserRoles(Role.ADMIN, Role.DESIGNER); + when(toscaOperationFacade.getToscaElement(anyString(), any(ComponentParametersView.class))) + .thenReturn(Either.left(resource)); + when(toscaOperationFacade.getParentComponents(anyString())) + .thenReturn(Either.left(Collections.singletonList(createParentService()))); + Either deleteCapabilityEither + = capabilitiesBusinessLogicMock.deleteCapability(componentId, capabilityId, user, true); + Assert.assertTrue(deleteCapabilityEither.isRight()); + } + + @Test + public void shouldPassGetCapabilitiesForHappyScenario(){ + Resource resource = createComponent(true); + resource.setComponentType(ComponentTypeEnum.RESOURCE); + validateUserRoles(Role.ADMIN, Role.DESIGNER); + when(toscaOperationFacade.getToscaElement(anyString(), any(ComponentParametersView.class))) + .thenReturn(Either.left(resource)); + when(toscaOperationFacade.getParentComponents(anyString())) + .thenReturn(Either.right(StorageOperationStatus.NOT_FOUND)); + Either getCapabilityEither + = capabilitiesBusinessLogicMock.getCapability(componentId, capabilityId, user, true); + Assert.assertTrue(getCapabilityEither.isLeft()); + + } + + @Test + public void shouldFailGetCapabilitiesWhenCapabilityNotExist(){ + Resource resource = createComponent(true); + resource.setComponentType(ComponentTypeEnum.RESOURCE); + validateUserRoles(Role.ADMIN, Role.DESIGNER); + when(toscaOperationFacade.getToscaElement(anyString(), any(ComponentParametersView.class))) + .thenReturn(Either.left(resource)); + when(toscaOperationFacade.getParentComponents(anyString())) + .thenReturn(Either.right(StorageOperationStatus.NOT_FOUND)); + Either getCapabilityEither + = capabilitiesBusinessLogicMock.getCapability(componentId, "capId1", user, true); + Assert.assertTrue(getCapabilityEither.isRight()); + + } + + private Resource createComponent(boolean needCapability) { + Resource resource = new Resource(); + resource.setName("Resource1"); + resource.addCategory("Network Layer 2-3", "Router"); + resource.setDescription("My short description"); + List tgs = new ArrayList<>(); + tgs.add("test"); + tgs.add(resource.getName()); + resource.setTags(tgs); + + if(needCapability) { + List capabilityDefinitions = createMockCapabilityListToReturn( + createCapability("capName", "capDesc", "capType", "source1", + "0", "10")); + Map> capabilityMap = new HashMap<>(); + capabilityMap.put("capType", capabilityDefinitions); + resource.setCapabilities(capabilityMap); + } + resource.setName(resource.getName()); + resource.setVersion("0.1"); + resource.setUniqueId(resource.getName().toLowerCase() + ":" + resource.getVersion()); + resource.setCreatorUserId(user.getUserId()); + resource.setCreatorFullName(user.getFirstName() + " " + user.getLastName()); + resource.setLifecycleState(LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT); + return resource; + } + + private List createMockCapabilityListToReturn(CapabilityDefinition capabilityDefinition) { + List capabilityDefinitions = new ArrayList<>(); + capabilityDefinitions.add(capabilityDefinition); + return capabilityDefinitions; + } + + private void validateUserRoles(Role... roles) { + List listOfRoles = Stream.of(roles).collect(Collectors.toList()); + } + + private CapabilityDefinition createCapability(String name, String description, String type, + String validSourceTypes, String minOccurrences, + String maxOccurrences) { + CapabilityDefinition capabilityDefinition = new CapabilityDefinition(); + capabilityDefinition.setName(name); + capabilityDefinition.setDescription(description); + capabilityDefinition.setType(type); + capabilityDefinition.setValidSourceTypes(Collections.singletonList(validSourceTypes)); + capabilityDefinition.setMaxOccurrences(maxOccurrences); + capabilityDefinition.setMinOccurrences(minOccurrences); + capabilityDefinition.setUniqueId(capabilityId); + + return capabilityDefinition; + } + + private Service createParentService() { + Service service = new Service(); + service.setUniqueId("serviceUniqueId"); + + List resourceInstancesRelations = new ArrayList<>(); + RequirementCapabilityRelDef relationDef = new RequirementCapabilityRelDef(); + relationDef.setFromNode("fromNode"); + relationDef.setToNode("toNode"); + + List relationships = new ArrayList<>(); + CapabilityRequirementRelationship capabilityRequirementRelationship = new CapabilityRequirementRelationship(); + + RelationshipInfo relation = new RelationshipInfo(); + relation.setCapabilityUid(capabilityId); + relation.setRequirementUid("reqUniqueId1"); + capabilityRequirementRelationship.setRelation(relation); + + relationships.add(capabilityRequirementRelationship); + relationDef.setRelationships(relationships); + resourceInstancesRelations.add(relationDef); + + service.setComponentInstancesRelations(resourceInstancesRelations); + + return service; + } + +} \ No newline at end of file diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/RequirementBusinessLogicTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/RequirementBusinessLogicTest.java new file mode 100644 index 0000000000..3cac5f5b15 --- /dev/null +++ b/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/RequirementBusinessLogicTest.java @@ -0,0 +1,412 @@ +/* + * Copyright © 2016-2018 European Support Limited + * + * 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. + */ + +package org.openecomp.sdc.be.components.impl; + +import fj.data.Either; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.mockito.InjectMocks; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; +import org.openecomp.sdc.be.auditing.impl.AuditingManager; +import org.openecomp.sdc.be.components.validation.RequirementValidation; +import org.openecomp.sdc.be.components.validation.UserValidations; +import org.openecomp.sdc.be.config.ConfigurationManager; +import org.openecomp.sdc.be.dao.api.ActionStatus; +import org.openecomp.sdc.be.dao.jsongraph.TitanDao; +import org.openecomp.sdc.be.dao.titan.TitanOperationStatus; +import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum; +import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum; +import org.openecomp.sdc.be.impl.ComponentsUtils; +import org.openecomp.sdc.be.model.CapabilityRequirementRelationship; +import org.openecomp.sdc.be.model.ComponentParametersView; +import org.openecomp.sdc.be.model.LifecycleStateEnum; +import org.openecomp.sdc.be.model.RelationshipInfo; +import org.openecomp.sdc.be.model.RequirementCapabilityRelDef; +import org.openecomp.sdc.be.model.RequirementDefinition; +import org.openecomp.sdc.be.model.Resource; +import org.openecomp.sdc.be.model.Service; +import org.openecomp.sdc.be.model.User; +import org.openecomp.sdc.be.model.jsontitan.operations.RequirementOperation; +import org.openecomp.sdc.be.model.jsontitan.operations.ToscaOperationFacade; +import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus; +import org.openecomp.sdc.be.model.operations.impl.GraphLockOperation; +import org.openecomp.sdc.be.user.Role; +import org.openecomp.sdc.be.user.UserBusinessLogic; +import org.openecomp.sdc.common.api.ConfigurationSource; +import org.openecomp.sdc.common.impl.ExternalConfiguration; +import org.openecomp.sdc.common.impl.FSConfigurationSource; +import org.openecomp.sdc.exception.ResponseFormat; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.anyCollection; +import static org.mockito.ArgumentMatchers.anyObject; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.when; + +public class RequirementBusinessLogicTest { + private final String componentId = "resourceId1"; + private final String requirementId = "uniqueId1"; + + private final TitanDao mockTitanDao = Mockito.mock(TitanDao.class); + private final UserBusinessLogic mockUserAdmin = Mockito.mock(UserBusinessLogic.class); + private final ToscaOperationFacade toscaOperationFacade = Mockito.mock(ToscaOperationFacade.class); + private final UserValidations userValidations = Mockito.mock(UserValidations.class); + private final RequirementOperation requirementOperation = Mockito.mock(RequirementOperation.class); + private final RequirementValidation requirementValidation = Mockito.mock(RequirementValidation.class); + + private final GraphLockOperation graphLockOperation = Mockito.mock(GraphLockOperation.class); + private User user = null; + + @InjectMocks + private RequirementBusinessLogic requirementsBusinessLogicMock = new RequirementBusinessLogic(); + + @Before + public void setup() { + MockitoAnnotations.initMocks(this); + ExternalConfiguration.setAppName("catalog-be"); + + // init Configuration + String appConfigDir = "src/test/resources/config/catalog-be"; + ConfigurationSource configurationSource = new FSConfigurationSource(ExternalConfiguration + .getChangeListener(), appConfigDir); + ConfigurationManager configurationManager = new ConfigurationManager(configurationSource); + + ComponentsUtils componentsUtils = new ComponentsUtils(Mockito.mock(AuditingManager.class)); + // User data and management + user = new User(); + user.setUserId("jh0003"); + user.setFirstName("Jimmi"); + user.setLastName("Hendrix"); + user.setRole(Role.ADMIN.name()); + + Either eitherGetUser = Either.left(user); + when(mockUserAdmin.getUser("jh0003", false)).thenReturn(eitherGetUser); + when(graphLockOperation.lockComponent(Mockito.anyString(), eq(NodeTypeEnum.Resource))) + .thenReturn(StorageOperationStatus.OK); + + //CapabilityOperation + when(requirementValidation.validateRequirements(anyCollection(), anyObject(), anyBoolean())) + .thenReturn(Either.left(true)); + when(requirementOperation.addRequirement(anyString(), anyObject())) + .thenReturn(Either.left(createMockRequirementListToReturn(createRequirement( + "reqName", "capType", "node", "source1", + "0", "10")))); + + when(requirementOperation.updateRequirement(anyString(), anyObject())) + .thenReturn(Either.left(createMockRequirementListToReturn(createRequirement( + "reqName", "capType", "node", "source1", + "0", "10")))); + when(requirementOperation.deleteRequirements( anyObject(), anyString())) + .thenReturn(StorageOperationStatus.OK); + when(mockTitanDao.commit()).thenReturn(TitanOperationStatus.OK); + + requirementsBusinessLogicMock = new RequirementBusinessLogic(); + + requirementsBusinessLogicMock.setComponentsUtils(componentsUtils); + requirementsBusinessLogicMock.setUserAdmin(mockUserAdmin); + requirementsBusinessLogicMock.setGraphLockOperation(graphLockOperation); + requirementsBusinessLogicMock.setTitanGenericDao(mockTitanDao); + requirementsBusinessLogicMock.setToscaOperationFacade(toscaOperationFacade); + requirementsBusinessLogicMock.setUserValidations(userValidations); + requirementsBusinessLogicMock.setRequirementOperation(requirementOperation); + requirementsBusinessLogicMock.setRequirementValidation(requirementValidation); + } + + @Test + public void shouldPassCreateRequirementsFirstTimeInComponentForHappyScenario(){ + List requirementDefinitions = createMockRequirementListToReturn( + createRequirement("reqName", "reqDesc", "capType", "source1", + "0", "10")); + Resource resource = createComponent(false); + resource.setComponentType(ComponentTypeEnum.RESOURCE); + validateUserRoles(Role.ADMIN, Role.DESIGNER); + when(toscaOperationFacade.getToscaElement(anyString(), any(ComponentParametersView.class))) + .thenReturn(Either.left(resource)); + Either, ResponseFormat> requirements = requirementsBusinessLogicMock + .createRequirements(componentId, requirementDefinitions, user, + "createRequirements", true); + Assert.assertTrue(requirements.isLeft()); + Assert.assertTrue(requirements.left().value().stream().anyMatch(requirementDefinition -> + requirementDefinition.getName().equals("reqName"))); + } + + @Test + public void shouldPassCreateRequirementsForHappyScenario(){ + List requirementDefinitions = createMockRequirementListToReturn( + createRequirement("reqName2", "capType", "node", "source1", + "0", "10")); + Resource resource = createComponent(true); + resource.setComponentType(ComponentTypeEnum.RESOURCE); + validateUserRoles(Role.ADMIN, Role.DESIGNER); + when(toscaOperationFacade.getToscaElement(anyString(), any(ComponentParametersView.class))) + .thenReturn(Either.left(resource)); + Either, ResponseFormat> requirements = requirementsBusinessLogicMock + .createRequirements(componentId, requirementDefinitions, user, + "createRequirements", true); + + Assert.assertTrue(requirements.isLeft()); + Assert.assertTrue(requirements.left().value().stream().anyMatch(requirementDefinition -> + requirementDefinition.getName().equals("reqName2"))); + } + + @Test + public void shouldPassUpdateRequirementsForHappyScenario(){ + + List requirementDefinitions = createMockRequirementListToReturn( + createRequirement("reqName", "capType", "node", "source1", + "6", "11")); + Resource resource = createComponent(true); + resource.setComponentType(ComponentTypeEnum.RESOURCE); + validateUserRoles(Role.ADMIN, Role.DESIGNER); + when(toscaOperationFacade.getToscaElement(anyString(), any(ComponentParametersView.class))) + .thenReturn(Either.left(resource)); + when(toscaOperationFacade.getParentComponents(anyString())) + .thenReturn(Either.right(StorageOperationStatus.NOT_FOUND)); + Either, ResponseFormat> capabilities = requirementsBusinessLogicMock + .updateRequirements(componentId, requirementDefinitions, user, + "updateRequirements", true); + Assert.assertTrue(capabilities.isLeft()); + Assert.assertTrue(capabilities.left().value().stream().anyMatch(requirementDefinition -> + requirementDefinition.getMaxOccurrences().equals("11"))); + } + + @Test + public void shouldPassDeleteRequirementsForHappyScenario(){ + Resource resource = createComponent(true); + resource.setComponentType(ComponentTypeEnum.RESOURCE); + validateUserRoles(Role.ADMIN, Role.DESIGNER); + when(toscaOperationFacade.getToscaElement(anyString(), any(ComponentParametersView.class))) + .thenReturn(Either.left(resource)); + when(toscaOperationFacade.getParentComponents(anyString())) + .thenReturn(Either.right(StorageOperationStatus.NOT_FOUND)); + Either deleteRequirementEither + = requirementsBusinessLogicMock.deleteRequirement(componentId, requirementId, user, true); + Assert.assertTrue(deleteRequirementEither.isLeft()); + + } + + @Test + public void shouldPassUpdateRequirementCapabilityUpdateWhenCapabilityNotExist(){ + + List requirementDefinitions + = createMockRequirementListToReturn(createRequirement( + "reqName", "capTypeUpdate", "node", "source1", + "6", "11")); + Resource resource = createComponent(true); + resource.setComponentType(ComponentTypeEnum.RESOURCE); + validateUserRoles(Role.ADMIN, Role.DESIGNER); + when(toscaOperationFacade.getToscaElement(anyString(), any(ComponentParametersView.class))) + .thenReturn(Either.left(resource)); + when(toscaOperationFacade.getParentComponents(anyString())) + .thenReturn(Either.right(StorageOperationStatus.NOT_FOUND)); + Either, ResponseFormat> updateRequirements + = requirementsBusinessLogicMock.updateRequirements(componentId, requirementDefinitions, + user, "updateRequirements", true); + Assert.assertTrue(updateRequirements.isLeft()); + Assert.assertTrue(updateRequirements.left().value().stream().anyMatch(requirementDefinition -> + requirementDefinition.getMaxOccurrences().equals("11"))); + } + + @Test + public void shouldPassUpdateRequirementTypeWhenCapabilityExist(){ + + List requirementDefinitions = createMockRequirementListToReturn( + createRequirement("reqName", "capTypeUpdate1", "node", + "source1","6", "11")); + Resource resource = createComponent(true); + resource.setComponentType(ComponentTypeEnum.RESOURCE); + + RequirementDefinition requirement = createRequirement("reqName", + "capTypeUpdate1", "node", "source1", + "6", "11"); + requirement.setUniqueId("unique2"); + List requirementDefinitions1 = createMockRequirementListToReturn(requirement); + Map> requirementMap = new HashMap<>(); + requirementMap.put("capTypeUpdate1", requirementDefinitions1); + resource.getRequirements().putAll(requirementMap); + + validateUserRoles(Role.ADMIN, Role.DESIGNER); + when(toscaOperationFacade.getToscaElement(anyString(), any(ComponentParametersView.class))) + .thenReturn(Either.left(resource)); + when(toscaOperationFacade.getParentComponents(anyString())) + .thenReturn(Either.right(StorageOperationStatus.NOT_FOUND)); + Either, ResponseFormat> capabilities + = requirementsBusinessLogicMock.updateRequirements(componentId, requirementDefinitions, + user, "updateRequirements", true); + Assert.assertTrue(capabilities.isLeft()); + Assert.assertTrue(capabilities.left().value().stream().anyMatch(capabilityDefinition -> + capabilityDefinition.getMaxOccurrences().equals("11"))); + } + + @Test + public void shouldFailUpdateRequirementWhenOperationFailedInTitan(){ + List requirementDefinitions = createMockRequirementListToReturn( + createRequirement("reqName", "capType", "node", "source1", + "6", "11")); + Resource resource = createComponent(true); + resource.setComponentType(ComponentTypeEnum.RESOURCE); + validateUserRoles(Role.ADMIN, Role.DESIGNER); + when(requirementOperation.addRequirement(anyString(), anyObject())) + .thenReturn(Either.right(StorageOperationStatus.GENERAL_ERROR)); + when(requirementOperation.updateRequirement(anyString(), anyObject())) + .thenReturn(Either.right(StorageOperationStatus.GENERAL_ERROR)); + when(toscaOperationFacade.getToscaElement(anyString(), any(ComponentParametersView.class))) + .thenReturn(Either.left(resource)); + Either, ResponseFormat> capabilities = requirementsBusinessLogicMock + .updateRequirements(componentId, requirementDefinitions, user, + "updateRequirements", true); + + Assert.assertTrue(capabilities.isRight()); + } + + + @Test + public void shouldFailDeleteRequirementWhenOperationFailedInTitan(){ + Resource resource = createComponent(true); + resource.setComponentType(ComponentTypeEnum.RESOURCE); + validateUserRoles(Role.ADMIN, Role.DESIGNER); + when(toscaOperationFacade.getToscaElement(anyString(), any(ComponentParametersView.class))) + .thenReturn(Either.left(resource)); + when(toscaOperationFacade.getParentComponents(anyString())) + .thenReturn(Either.right(StorageOperationStatus.NOT_FOUND)); + when(requirementOperation.deleteRequirements(anyObject(), anyString())) + .thenReturn(StorageOperationStatus.GENERAL_ERROR); + Either deleteRequirementEither + = requirementsBusinessLogicMock.deleteRequirement(componentId, requirementId, user, true); + Assert.assertTrue(deleteRequirementEither.isRight()); + } + + @Test + public void shouldFailDeleteRequirementWhenRequirementUsedInServiceComposition(){ + Resource resource = createComponent(true); + resource.setComponentType(ComponentTypeEnum.RESOURCE); + validateUserRoles(Role.ADMIN, Role.DESIGNER); + when(toscaOperationFacade.getToscaElement(anyString(), any(ComponentParametersView.class))) + .thenReturn(Either.left(resource)); + when(toscaOperationFacade.getParentComponents(anyString())) + .thenReturn(Either.left(Collections.singletonList(createParentService()))); + Either deleteRequirementEither + = requirementsBusinessLogicMock.deleteRequirement(componentId, requirementId, user, true); + Assert.assertTrue(deleteRequirementEither.isRight()); + } + + @Test + public void shouldPassGetRequirementsForHappyScenario(){ + Resource resource = createComponent(true); + resource.setComponentType(ComponentTypeEnum.RESOURCE); + validateUserRoles(Role.ADMIN, Role.DESIGNER); + when(toscaOperationFacade.getToscaElement(anyString(), any(ComponentParametersView.class))) + .thenReturn(Either.left(resource)); + when(toscaOperationFacade.getParentComponents(anyString())) + .thenReturn(Either.right(StorageOperationStatus.NOT_FOUND)); + Either getRequirementEither + = requirementsBusinessLogicMock.getRequirement(componentId, requirementId, user, true); + Assert.assertTrue(getRequirementEither.isLeft()); + + } + + private Resource createComponent(boolean needRequirements) { + Resource resource = new Resource(); + resource.setName("Resource1"); + resource.addCategory("Network Layer 2-3", "Router"); + resource.setDescription("My short description"); + List tgs = new ArrayList<>(); + tgs.add("test"); + tgs.add(resource.getName()); + resource.setTags(tgs); + + if(needRequirements) { + List requirementDefinitions = createMockRequirementListToReturn( + createRequirement("reqName", "capType", "node", "source1", + "0", "10")); + Map> requirementsMap = new HashMap<>(); + requirementsMap.put("capType", requirementDefinitions); + resource.setRequirements(requirementsMap); + } + resource.setName(resource.getName()); + resource.setVersion("0.1"); + resource.setUniqueId(resource.getName().toLowerCase() + ":" + resource.getVersion()); + resource.setCreatorUserId(user.getUserId()); + resource.setCreatorFullName(user.getFirstName() + " " + user.getLastName()); + resource.setLifecycleState(LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT); + return resource; + } + + private List createMockRequirementListToReturn(RequirementDefinition requirementDefinition) { + List requirementDefinitions = new ArrayList<>(); + requirementDefinitions.add(requirementDefinition); + return requirementDefinitions; + } + + private void validateUserRoles(Role... roles) { + List listOfRoles = Stream.of(roles).collect(Collectors.toList()); + } + + private RequirementDefinition createRequirement(String name, String capability, String node, + String relationship, String minOccurrences, + String maxOccurrences) { + RequirementDefinition requirementDefinition = new RequirementDefinition(); + requirementDefinition.setName(name); + requirementDefinition.setCapability(capability); + requirementDefinition.setNode(node); + requirementDefinition.setRelationship(relationship); + requirementDefinition.setMaxOccurrences(maxOccurrences); + requirementDefinition.setMinOccurrences(minOccurrences); + requirementDefinition.setUniqueId(requirementId); + + return requirementDefinition; + } + + private Service createParentService() { + Service service = new Service(); + service.setUniqueId("serviceUniqueId"); + + List resourceInstancesRelations = new ArrayList<>(); + RequirementCapabilityRelDef relationDef = new RequirementCapabilityRelDef(); + relationDef.setFromNode("fromNode"); + relationDef.setToNode("toNode"); + + List relationships = new ArrayList<>(); + CapabilityRequirementRelationship capabilityRequirementRelationship = new CapabilityRequirementRelationship(); + + RelationshipInfo relation = new RelationshipInfo(); + relation.setCapabilityUid("capabilityId"); + relation.setRequirementUid(requirementId); + capabilityRequirementRelationship.setRelation(relation); + + relationships.add(capabilityRequirementRelationship); + relationDef.setRelationships(relationships); + resourceInstancesRelations.add(relationDef); + + service.setComponentInstancesRelations(resourceInstancesRelations); + + return service; + } + +} \ No newline at end of file diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/components/validation/CapabilitiesValidationTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/components/validation/CapabilitiesValidationTest.java new file mode 100644 index 0000000000..b4856b96b4 --- /dev/null +++ b/catalog-be/src/test/java/org/openecomp/sdc/be/components/validation/CapabilitiesValidationTest.java @@ -0,0 +1,159 @@ +/* + * Copyright © 2016-2018 European Support Limited + * + * 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. + */ + +package org.openecomp.sdc.be.components.validation; + + +import fj.data.Either; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; +import org.openecomp.sdc.be.components.impl.ResponseFormatManager; +import org.openecomp.sdc.be.model.CapabilityDefinition; +import org.openecomp.sdc.be.model.Component; +import org.openecomp.sdc.be.model.Resource; +import org.openecomp.sdc.exception.ResponseFormat; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.when; + +public class CapabilitiesValidationTest { + private ResponseFormatManager responseFormatManagerMock; + private final Component component = createComponent(); + private final CapabilitiesValidationUtilTest capabilitiesValidationUtilTest = new CapabilitiesValidationUtilTest(); + @Before + public void init() { + MockitoAnnotations.initMocks(this); + responseFormatManagerMock = Mockito.mock(ResponseFormatManager.class); + when(responseFormatManagerMock.getResponseFormat(any())).thenReturn(new ResponseFormat()); + when(responseFormatManagerMock.getResponseFormat(any(), any())).thenReturn(new ResponseFormat()); + when(responseFormatManagerMock.getResponseFormat(any(), any(), any())).thenReturn(new ResponseFormat()); + } + + @Test + public void shouldPassCapabilitiesValidationForHappyScenario() { + List capabilityDefinitions = new ArrayList<>(); + capabilityDefinitions.add(createCapability("capName", "capDesc", "capType", "source1", + "0", "10")); + Either validateCapabilitiesResponseEither = capabilitiesValidationUtilTest + .validateCapabilities(capabilityDefinitions, component, false); + Assert.assertTrue(validateCapabilitiesResponseEither.isLeft()); + } + + @Test + public void shouldFailWhenCapabilityNameAlreadyExist() { + List capabilityDefinitions = new ArrayList<>(); + capabilityDefinitions.add(createCapability("capNameC", "capDesc", "capType", "source1", + "0", "10")); + Either validateCapabilitiesResponseEither = capabilitiesValidationUtilTest + .validateCapabilities(capabilityDefinitions, component, false); + Assert.assertTrue(validateCapabilitiesResponseEither.isRight()); + } + + @Test + public void shouldFailWhenCapabilityNameEmpty() { + List capabilityDefinitions = new ArrayList<>(); + capabilityDefinitions.add(createCapability("", "capDesc", "capType", "source1", + "0", "10")); + Either validateCapabilitiesResponseEither = capabilitiesValidationUtilTest + .validateCapabilities(capabilityDefinitions, component, false); + Assert.assertTrue(validateCapabilitiesResponseEither.isRight()); + } + + @Test + public void shouldFailWhenCapabilityTypeEmpty() { + List capabilityDefinitions = new ArrayList<>(); + capabilityDefinitions.add(createCapability("capName1", "capDesc", "", "source1", + "0", "10")); + Either validateCapabilitiesResponseEither = capabilitiesValidationUtilTest + .validateCapabilities(capabilityDefinitions, component, false); + Assert.assertTrue(validateCapabilitiesResponseEither.isRight()); + } + + @Test + public void shouldFailWhenCapabilityMaxOccurrencesLessThanMinOccurrences() { + List capabilityDefinitions = new ArrayList<>(); + capabilityDefinitions.add(createCapability("capName1", "capDesc", "capType", "source1", + "111", "3")); + Either validateCapabilitiesResponseEither = capabilitiesValidationUtilTest + .validateCapabilities(capabilityDefinitions, component, false); + Assert.assertTrue(validateCapabilitiesResponseEither.isRight()); + } + + @Test + public void shouldFailWhenCapabilityNotFoundForUpdate() { + List capabilityDefinitions = new ArrayList<>(); + CapabilityDefinition capabilityToUpdate = createCapability("capName1", "capDesc", "capType", "source1", + "1", "3"); + capabilityToUpdate.setUniqueId("uniqueId2"); + + capabilityDefinitions.add(capabilityToUpdate); + Either validateCapabilitiesResponseEither = capabilitiesValidationUtilTest + .validateCapabilities(capabilityDefinitions, component, true); + Assert.assertTrue(validateCapabilitiesResponseEither.isRight()); + } + + private CapabilityDefinition createCapability(String name, String description, String type, + String validSourceTypes, String minOccurrences, + String maxOccurrences) { + CapabilityDefinition capabilityDefinition = new CapabilityDefinition(); + capabilityDefinition.setName(name); + capabilityDefinition.setDescription(description); + capabilityDefinition.setType(type); + capabilityDefinition.setValidSourceTypes(Collections.singletonList(validSourceTypes)); + capabilityDefinition.setMaxOccurrences(maxOccurrences); + capabilityDefinition.setMinOccurrences(minOccurrences); + capabilityDefinition.setUniqueId("uniqueId"); + + + return capabilityDefinition; + } + + private Resource createComponent() { + Resource resource = new Resource(); + resource.setName("Resource1"); + resource.addCategory("Network Layer 2-3", "Router"); + resource.setDescription("My short description"); + List tgs = new ArrayList<>(); + tgs.add("test"); + tgs.add(resource.getName()); + resource.setTags(tgs); + + List capabilityDefinitions = new ArrayList<>(); + capabilityDefinitions.add(createCapability("capNameC", "capDesc", "capType", "source1", + "0", "10")); + Map> capabilityMap = new HashMap<>(); + capabilityMap.put("capTypeC", capabilityDefinitions); + resource.setCapabilities(capabilityMap); + + return resource; + } + + private class CapabilitiesValidationUtilTest extends CapabilitiesValidation { + + protected ResponseFormatManager getResponseFormatManager() { + return responseFormatManagerMock; + } + } +} \ No newline at end of file diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/components/validation/RequirementValidationTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/components/validation/RequirementValidationTest.java new file mode 100644 index 0000000000..ff9bcd1bac --- /dev/null +++ b/catalog-be/src/test/java/org/openecomp/sdc/be/components/validation/RequirementValidationTest.java @@ -0,0 +1,156 @@ +/* + * Copyright © 2016-2018 European Support Limited + * + * 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. + */ + +package org.openecomp.sdc.be.components.validation; + +import fj.data.Either; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; +import org.openecomp.sdc.be.components.impl.ResponseFormatManager; +import org.openecomp.sdc.be.model.Component; +import org.openecomp.sdc.be.model.RequirementDefinition; +import org.openecomp.sdc.be.model.Resource; +import org.openecomp.sdc.exception.ResponseFormat; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.when; + +public class RequirementValidationTest { + private ResponseFormatManager responseFormatManagerMock; + private final Component component = createComponent(); + private final RequirementValidationUtilTest requirementValidationUtilTest = new RequirementValidationUtilTest(); + @Before + public void init() { + MockitoAnnotations.initMocks(this); + responseFormatManagerMock = Mockito.mock(ResponseFormatManager.class); + when(responseFormatManagerMock.getResponseFormat(any())).thenReturn(new ResponseFormat()); + when(responseFormatManagerMock.getResponseFormat(any(), any())).thenReturn(new ResponseFormat()); + when(responseFormatManagerMock.getResponseFormat(any(), any(), any())).thenReturn(new ResponseFormat()); + } + + @Test + public void shouldPassRequirementsValidationForHappyScenario() { + List requirementsDefinitions = new ArrayList<>(); + requirementsDefinitions.add(createRequirement("reqName", "capType", "node", "source1", + "0", "10")); + Either validateRequirementsResponseEither = requirementValidationUtilTest + .validateRequirements(requirementsDefinitions, component, false); + Assert.assertTrue(validateRequirementsResponseEither.isLeft()); + } + + @Test + public void shouldFailWhenRequirementNameAlreadyExist() { + List requirementsDefinitions = new ArrayList<>(); + requirementsDefinitions.add(createRequirement("ReqNameC", "capType", "node", "source1", + "0", "10")); + Either validateRequirementsResponseEither = requirementValidationUtilTest + .validateRequirements(requirementsDefinitions, component, false); + Assert.assertTrue(validateRequirementsResponseEither.isRight()); + } + + @Test + public void shouldFailWhenRequirementNameEmpty() { + List requirementsDefinitions = new ArrayList<>(); + requirementsDefinitions.add(createRequirement("", "capType", "node", "source1", + "0", "10")); + Either validateRequirementsResponseEither = requirementValidationUtilTest + .validateRequirements(requirementsDefinitions, component, false); + Assert.assertTrue(validateRequirementsResponseEither.isRight()); + } + + @Test + public void shouldFailWhenRequirementCapabilityEmpty() { + List requirementsDefinitions = new ArrayList<>(); + requirementsDefinitions.add(createRequirement("reqName1", "", "node", "source1", + "0", "10")); + Either validateRequirementsResponseEither = requirementValidationUtilTest + .validateRequirements(requirementsDefinitions, component, false); + Assert.assertTrue(validateRequirementsResponseEither.isRight()); + } + + @Test + public void shouldFailWhenRequirementMaxOccurrencesLessThanMinOccurrences() { + List requirementsDefinitions = new ArrayList<>(); + requirementsDefinitions.add(createRequirement("reqName1", "capType", "node", "source1", + "111", "3")); + Either validateRequirementsResponseEither = requirementValidationUtilTest + .validateRequirements(requirementsDefinitions, component, false); + Assert.assertTrue(validateRequirementsResponseEither.isRight()); + } + + @Test + public void shouldFailWhenRequirementNotFoundForUpdate() { + List requirementsDefinitions = new ArrayList<>(); + RequirementDefinition requirementsToUpdate = createRequirement("reqName1", "capType", "node", "source1", + "1", "3"); + requirementsToUpdate.setUniqueId("uniqueId2"); + + requirementsDefinitions.add(requirementsToUpdate); + Either validateRequirementsResponseEither = requirementValidationUtilTest + .validateRequirements(requirementsDefinitions, component, true); + Assert.assertTrue(validateRequirementsResponseEither.isRight()); + } + + private RequirementDefinition createRequirement(String name, String capability, String node, + String relationship, String minOccurrences, + String maxOccurrences) { + RequirementDefinition requirementDefinition = new RequirementDefinition(); + requirementDefinition.setName(name); + requirementDefinition.setCapability(capability); + requirementDefinition.setNode(node); + requirementDefinition.setRelationship(relationship); + requirementDefinition.setMaxOccurrences(maxOccurrences); + requirementDefinition.setMinOccurrences(minOccurrences); + requirementDefinition.setUniqueId("uniqueId"); + + return requirementDefinition; + } + + private Resource createComponent() { + Resource resource = new Resource(); + resource.setName("Resource1"); + resource.addCategory("Network Layer 2-3", "Router"); + resource.setDescription("My short description"); + List tgs = new ArrayList<>(); + tgs.add("test"); + tgs.add(resource.getName()); + resource.setTags(tgs); + + List requirementsDefinitions = new ArrayList<>(); + requirementsDefinitions.add(createRequirement("ReqNameC", "reqDesc", "capType", "source1", + "0", "10")); + Map> requirementsMap = new HashMap<>(); + requirementsMap.put("capTypeC", requirementsDefinitions); + resource.setRequirements(requirementsMap); + + return resource; + } + + private class RequirementValidationUtilTest extends RequirementValidation { + + protected ResponseFormatManager getResponseFormatManager() { + return responseFormatManagerMock; + } + } +} \ No newline at end of file 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 e97f13c716..807ded8f5c 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 @@ -125,7 +125,7 @@ public class TypesUploadServletTest extends JerseyTest { protected ResourceConfig configure() { ResourceConfig resourceConfig = new ResourceConfig() - .register(new TypesUploadServlet(importManager, null, null, null, null, null)); + .register(new TypesUploadServlet(importManager, null, null, null, null, null, null)); resourceConfig.register(MultiPartFeature.class); resourceConfig.register(new AbstractBinder() { 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 ff6e0481f6..15a7fa72c7 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 @@ -145,5 +145,18 @@ public enum ActionStatus { //InterfaceLifeCycleType - INTERFACE_LIFECYCLE_TYPES_NOT_FOUND + INTERFACE_LIFECYCLE_TYPES_NOT_FOUND, + + //Capability related + CAPABILITY_NOT_FOUND, CAPABILITY_NAME_MANDATORY, CAPABILITY_TYPE_MANDATORY,CAPABILITY_NAME_ALREADY_IN_USE, + MAX_OCCURRENCES_SHOULD_BE_GREATER_THAN_MIN_OCCURRENCES, CAPABILITY_DELETION_NOT_ALLOWED_USED_IN_COMPOSITION, + CAPABILITY_UPDATE_NOT_ALLOWED_USED_IN_COMPOSITION,INVALID_CAPABILITY_NAME, + + RELATIONSHIP_TYPE_ALREADY_EXIST, MISSING_RELATIONSHIP_TYPE, CAPABILITY_TYPE_CANNOT_BE_EMPTY, + + + //Requirement related + REQUIREMENT_NOT_FOUND, REQUIREMENT_NAME_MANDATORY, REQUIREMENT_CAPABILITY_MANDATORY,REQUIREMENT_NAME_ALREADY_IN_USE, + REQUIREMENT_DELETION_NOT_ALLOWED_USED_IN_COMPOSITION, REQUIREMENT_UPDATE_NOT_ALLOWED_USED_IN_COMPOSITION, INVALID_REQUIREMENT_NAME + ; } 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 a6bb026a71..350909e66d 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 @@ -172,6 +172,7 @@ public class GraphElementFactory { element = clazz.cast(new InputValueData(properties)); break; case RelationshipType: + element = clazz.cast(new RelationshipTypeData(properties)); break; case LockNode: element = clazz.cast(new GraphNodeLock(properties)); diff --git a/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/jsongraph/types/VertexTypeEnum.java b/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/jsongraph/types/VertexTypeEnum.java index 108d5e7201..9ba7048dd7 100644 --- a/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/jsongraph/types/VertexTypeEnum.java +++ b/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/jsongraph/types/VertexTypeEnum.java @@ -33,7 +33,7 @@ public enum VertexTypeEnum { INTERFACE_ARTIFACTS ("interface_artifacts", InterfaceDataDefinition.class), INSTANCE_ARTIFACTS ("instance_artifacts", MapArtifactDataDefinition.class), PROPERTIES ("properties", PropertyDataDefinition.class), - CAPABILTIES ("capabilities", ListCapabilityDataDefinition.class), + CAPABILITIES ("capabilities", ListCapabilityDataDefinition.class), CAPABILITIES_PROPERTIES ("capabilities_properties", MapPropertiesDataDefinition.class), REQUIREMENTS ("requirements", ListRequirementDataDefinition.class), ATTRIBUTES ("attributes", PropertyDataDefinition.class), diff --git a/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/neo4j/GraphPropertiesDictionary.java b/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/neo4j/GraphPropertiesDictionary.java index 1da09e0cc5..b3f9037ea6 100644 --- a/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/neo4j/GraphPropertiesDictionary.java +++ b/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/neo4j/GraphPropertiesDictionary.java @@ -21,161 +21,162 @@ package org.openecomp.sdc.be.dao.neo4j; public enum GraphPropertiesDictionary { -// field name class type unique indexed +// field name class type unique indexed // stored in graph index - // Common - LABEL ("nodeLabel", String.class, false, true), - HEALTH_CHECK ("healthcheckis", String.class, true, true), - // Resource - NAME ("name", String.class, false, true), - TOSCA_RESOURCE_NAME ("toscaResourceName", String.class, false, true), - CATEGORY_NAME ("categoryName", String.class, false, true), - VERSION ("version", String.class, false, true), - CREATION_DATE ("creationDate", Long.class, false, false), - LAST_UPDATE_DATE ("modificationDate", Long.class, false, false), - IS_HIGHEST_VERSION ("highestVersion", Boolean.class, false, true), - IS_ABSTRACT ("abstract", Boolean.class, false, true), - DESCRIPTION ("description", String.class, false, false), - UNIQUE_ID ("uid", String.class, true, true), - STATE ("state", String.class, false, true), - TYPE ("type", String.class, false, true), - REQUIRED ("required", Boolean.class, false, false), - DEFAULT_VALUE ("defaultValue", String.class, false, false), - CONSTRAINTS ("constraints", String.class, false, false), - CONTACT_ID ("contactId", String.class, false, false), - VENDOR_NAME ("vendorName", String.class, false, false), - VENDOR_RELEASE ("vendorRelease", String.class, false, false), - CONFORMANCE_LEVEL ("conformanceLevel", String.class, false, false), - ICON ("icon", String.class, false, false), - TAGS ("tags", String.class, false, false), - UUID ("uuid", String.class, false, true), - COST ("cost", String.class, false, false), - LICENSE_TYPE ("licenseType", String.class, false, false), - NORMALIZED_NAME ("normalizedName", String.class, false, true), - SYSTEM_NAME ("systemName", String.class, false, true), - IS_DELETED ("deleted", Boolean.class, false, true), - RESOURCE_TYPE ("resourceType", String.class, false, true), - ENTRY_SCHEMA ("entry_schema", String.class, false, false), - CSAR_UUID ("csarUuid", String.class, false, true), - CSAR_VERSION ("csarVersion", String.class, false, true), - IMPORTED_TOSCA_CHECKSUM ("importedToscaChecksum", String.class, false, true), - GENERATED ("generated", Boolean.class, false, false), - // User - USERID ("userId", String.class, true, true), - EMAIL ("email", String.class, false, false), - FIRST_NAME ("firstName", String.class, false, false), - LAST_NAME ("lastName", String.class, false, false), - ROLE ("role", String.class, false, true), - USER_STATUS ("status", String.class, false, true), - VALID_SOURCE_TYPES ("validSourceTypes", String.class, false, false), - NODE ("node", String.class, false, false), - VALUE ("value", String.class, false, false), - HIDDEN ("Hidden", Boolean.class, false, false), - PROPERTIES ("properties", String.class, false, false), - POSITION_X ("positionX", String.class, false, false), - POSITION_Y ("positionY", String.class, false, false), - RELATIONSHIP_TYPE ("relationshipType", String.class, false, false), - ARTIFACT_TYPE ("artifactType", String.class, false, true), - ARTIFACT_REF ("artifactRef", String.class, false, false), - ARTIFACT_REPOSITORY ("artifactRepository", String.class, false, false), - ARTIFACT_CHECKSUM ("artifactChecksum", String.class, false, false), - CREATOR ("creator", String.class, false, false), - CREATOR_ID ("creatorId", String.class, false, false), - LAST_UPDATER ("lastUpdater", String.class, false, false), - CREATOR_FULL_NAME ("creatorFullName", String.class, false, false), - UPDATER_FULL_NAME ("updaterFullName", String.class, false, false), - ES_ID ("esId", String.class, false, false), - ARTIFACT_LABEL ("artifactLabel", String.class, false, true), - ARTIFACT_DISPLAY_NAME("artifactDisplayName", String.class, false, true), - INSTANCE_COUNTER ("instanceCounter", Integer.class, false, false), - PROJECT_CODE ("projectCode", String.class, false, false), - DISTRIBUTION_STATUS ("distributionStatus", String.class, false, false), - IS_VNF ("isVNF", Boolean.class, false, false), - LAST_LOGIN_TIME ("lastLoginTime", Long.class, false, true), - ATTRIBUTE_COUNTER ("attributeCounter", Integer.class, false, false), - INPUT_COUNTER ("inputCounter", Integer.class, false, false), - PROPERTY_COUNTER ("propertyCounter", Integer.class, false, false), - API_URL ("apiUrl", String.class, false, false), - SERVICE_API ("serviceApi", Boolean.class, false, true), - ADDITIONAL_INFO_PARAMS ("additionalInfo", String.class, false, false), - ADDITIONAL_INFO_ID_TO_KEY ("idToKey", String.class, false, false), - ARTIFACT_GROUP_TYPE ("artifactGroupType", String.class, false, true), - ARTIFACT_TIMEOUT ("timeout", Integer.class, false, false), - IS_ACTIVE ("isActive", Boolean.class, false, true), - PROPERTY_VALUE_RULES ("propertyValueRules", String.class, false, false), - //authantication - CONSUMER_NAME ("consumerName", String.class, true, true), - CONSUMER_PASSWORD ("consumerPassword", String.class, false, false), - CONSUMER_SALT ("consumerSalt", String.class, false, false), - CONSUMER_LAST_AUTHENTICATION_TIME ("consumerLastAuthenticationTime", Long.class, false, false), - CONSUMER_DETAILS_LAST_UPDATED_TIME ("consumerDetailsLastupdatedtime", Long.class, false, false), - LAST_MODIFIER_USER_ID("lastModfierUserId", String.class, false, false), - ARTIFACT_VERSION ("artifactVersion", String.class, false, false), - ARTIFACT_UUID ("artifactUUID", String.class, false, false), - PAYLOAD_UPDATE_DATE ("payloadUpdateDate", Long.class, false, false), - HEAT_PARAMS_UPDATE_DATE ("heatParamsUpdateDate",Long.class, false, false), - //product - FULL_NAME ("fullName", String.class, false, true), - //was changed as part of migration from 1602 to 1602 ( in 1602 was defined as unique. it's problem to reconfigure the index ) - CONSTANT_UUID ("constantUuidNew", String.class, false, true), - CONTACTS ("contacts", String.class, false, false), - //categorys - ICONS ("icons", String.class, false, false), - //relation - CAPABILITY_OWNER_ID ("capOwnerId", String.class, false, false), - REQUIREMENT_OWNER_ID ("reqOwnerId", String.class, false, false), - CAPABILITY_ID ("capabiltyId", String.class, false, false), - REQUIREMENT_ID ("requirementId", String.class, false, false), - PROPERTY_ID ("propertyId", String.class, false, false), - PROPERTY_NAME ("propertyName", String.class, false, false), - //component instance - ORIGIN_TYPE ("originType", String.class, false, false), - //requirement & capabilty - MIN_OCCURRENCES ("minOccurrences", String.class, false, false), - MAX_OCCURRENCES ("maxOccurrences", String.class, false, false), - //Data type - DERIVED_FROM ("derivedFrom", String.class, false, false), - MEMBERS ("members", String.class, false, false), - TARGETS ("targets ", String.class, false, false), - METADATA ("metadata", String.class, false, false), - INVARIANT_UUID ("invariantUuid", String.class, false, true), - IS_BASE ("isBase", Boolean.class, false, true), - GROUP_UUID ("groupUuid", String.class, false, true), - STATUS ("status", String.class, false, false), - FUNCTIONAL_MENU ("functionalMenu", String.class, false, false), - REQUIRED_ARTIFACTS ("requiredArtifacts", String.class, false, false), - CUSTOMIZATION_UUID ("customizationUUID", String.class, false, false), - IS_ARCHIVED ("isArchived", Boolean.class, false, true), - IS_VSP_ARCHIVED ("isVspArchived", Boolean.class, false, true), - ARCHIVE_TIME ("archiveTime", Long.class, false, true); + // Common + LABEL("nodeLabel", String.class, false, true), + HEALTH_CHECK("healthcheckis", String.class, true, true), + // Resource + NAME("name", String.class, false, true), + TOSCA_RESOURCE_NAME("toscaResourceName", String.class, false, true), + CATEGORY_NAME("categoryName", String.class, false, true), + VERSION("version", String.class, false, true), + CREATION_DATE("creationDate", Long.class, false, false), + LAST_UPDATE_DATE("modificationDate", Long.class, false, false), + IS_HIGHEST_VERSION("highestVersion", Boolean.class, false, true), + IS_ABSTRACT("abstract", Boolean.class, false, true), + DESCRIPTION("description", String.class, false, false), + UNIQUE_ID("uid", String.class, true, true), + STATE("state", String.class, false, true), + TYPE("type", String.class, false, true), + REQUIRED("required", Boolean.class, false, false), + DEFAULT_VALUE("defaultValue", String.class, false, false), + CONSTRAINTS("constraints", String.class, false, false), + CONTACT_ID("contactId", String.class, false, false), + VENDOR_NAME("vendorName", String.class, false, false), + VENDOR_RELEASE("vendorRelease", String.class, false, false), + CONFORMANCE_LEVEL("conformanceLevel", String.class, false, false), + ICON("icon", String.class, false, false), + TAGS("tags", String.class, false, false), + UUID("uuid", String.class, false, true), + COST("cost", String.class, false, false), + LICENSE_TYPE("licenseType", String.class, false, false), + NORMALIZED_NAME("normalizedName", String.class, false, true), + SYSTEM_NAME("systemName", String.class, false, true), + IS_DELETED("deleted", Boolean.class, false, true), + RESOURCE_TYPE("resourceType", String.class, false, true), + ENTRY_SCHEMA("entry_schema", String.class, false, false), + CSAR_UUID("csarUuid", String.class, false, true), + CSAR_VERSION("csarVersion", String.class, false, true), + IMPORTED_TOSCA_CHECKSUM("importedToscaChecksum", String.class, false, true), + GENERATED("generated", Boolean.class, false, false), + // User + USERID("userId", String.class, true, true), + EMAIL("email", String.class, false, false), + FIRST_NAME("firstName", String.class, false, false), + LAST_NAME("lastName", String.class, false, false), + ROLE("role", String.class, false, true), + USER_STATUS("status", String.class, false, true), + VALID_SOURCE_TYPES("validSourceTypes", String.class, false, false), + VALID_TARGET_TYPES("validTargetTypes", String.class, false, false), + NODE("node", String.class, false, false), + VALUE("value", String.class, false, false), + HIDDEN("Hidden", Boolean.class, false, false), + PROPERTIES("properties", String.class, false, false), + POSITION_X("positionX", String.class, false, false), + POSITION_Y("positionY", String.class, false, false), + RELATIONSHIP_TYPE("relationshipType", String.class, false, false), + ARTIFACT_TYPE("artifactType", String.class, false, true), + ARTIFACT_REF("artifactRef", String.class, false, false), + ARTIFACT_REPOSITORY("artifactRepository", String.class, false, false), + ARTIFACT_CHECKSUM("artifactChecksum", String.class, false, false), + CREATOR("creator", String.class, false, false), + CREATOR_ID("creatorId", String.class, false, false), + LAST_UPDATER("lastUpdater", String.class, false, false), + CREATOR_FULL_NAME("creatorFullName", String.class, false, false), + UPDATER_FULL_NAME("updaterFullName", String.class, false, false), + ES_ID("esId", String.class, false, false), + ARTIFACT_LABEL("artifactLabel", String.class, false, true), + ARTIFACT_DISPLAY_NAME("artifactDisplayName", String.class, false, true), + INSTANCE_COUNTER("instanceCounter", Integer.class, false, false), + PROJECT_CODE("projectCode", String.class, false, false), + DISTRIBUTION_STATUS("distributionStatus", String.class, false, false), + IS_VNF("isVNF", Boolean.class, false, false), + LAST_LOGIN_TIME("lastLoginTime", Long.class, false, true), + ATTRIBUTE_COUNTER("attributeCounter", Integer.class, false, false), + INPUT_COUNTER("inputCounter", Integer.class, false, false), + PROPERTY_COUNTER("propertyCounter", Integer.class, false, false), + API_URL("apiUrl", String.class, false, false), + SERVICE_API("serviceApi", Boolean.class, false, true), + ADDITIONAL_INFO_PARAMS("additionalInfo", String.class, false, false), + ADDITIONAL_INFO_ID_TO_KEY("idToKey", String.class, false, false), + ARTIFACT_GROUP_TYPE("artifactGroupType", String.class, false, true), + ARTIFACT_TIMEOUT("timeout", Integer.class, false, false), + IS_ACTIVE("isActive", Boolean.class, false, true), + PROPERTY_VALUE_RULES("propertyValueRules", String.class, false, false), + //authantication + CONSUMER_NAME("consumerName", String.class, true, true), + CONSUMER_PASSWORD("consumerPassword", String.class, false, false), + CONSUMER_SALT("consumerSalt", String.class, false, false), + CONSUMER_LAST_AUTHENTICATION_TIME("consumerLastAuthenticationTime", Long.class, false, false), + CONSUMER_DETAILS_LAST_UPDATED_TIME("consumerDetailsLastupdatedtime", Long.class, false, false), + LAST_MODIFIER_USER_ID("lastModfierUserId", String.class, false, false), + ARTIFACT_VERSION("artifactVersion", String.class, false, false), + ARTIFACT_UUID("artifactUUID", String.class, false, false), + PAYLOAD_UPDATE_DATE("payloadUpdateDate", Long.class, false, false), + HEAT_PARAMS_UPDATE_DATE("heatParamsUpdateDate", Long.class, false, false), + //product + FULL_NAME("fullName", String.class, false, true), + //was changed as part of migration from 1602 to 1602 ( in 1602 was defined as unique. it's problem to reconfigure the index ) + CONSTANT_UUID("constantUuidNew", String.class, false, true), + CONTACTS("contacts", String.class, false, false), + //categorys + ICONS("icons", String.class, false, false), + //relation + CAPABILITY_OWNER_ID("capOwnerId", String.class, false, false), + REQUIREMENT_OWNER_ID("reqOwnerId", String.class, false, false), + CAPABILITY_ID("capabiltyId", String.class, false, false), + REQUIREMENT_ID("requirementId", String.class, false, false), + PROPERTY_ID("propertyId", String.class, false, false), + PROPERTY_NAME("propertyName", String.class, false, false), + //component instance + ORIGIN_TYPE("originType", String.class, false, false), + //requirement & capabilty + MIN_OCCURRENCES("minOccurrences", String.class, false, false), + MAX_OCCURRENCES("maxOccurrences", String.class, false, false), + //Data type + DERIVED_FROM("derivedFrom", String.class, false, false), + MEMBERS("members", String.class, false, false), + TARGETS("targets ", String.class, false, false), + METADATA("metadata", String.class, false, false), + INVARIANT_UUID("invariantUuid", String.class, false, true), + IS_BASE("isBase", Boolean.class, false, true), + GROUP_UUID("groupUuid", String.class, false, true), + STATUS("status", String.class, false, false), + FUNCTIONAL_MENU("functionalMenu", String.class, false, false), + REQUIRED_ARTIFACTS("requiredArtifacts", String.class, false, false), + CUSTOMIZATION_UUID("customizationUUID", String.class, false, false), + IS_ARCHIVED("isArchived", Boolean.class, false, true), + IS_VSP_ARCHIVED("isVspArchived", Boolean.class, false, true), + ARCHIVE_TIME("archiveTime", Long.class, false, true); - private final String property; - private final Class clazz; - private final boolean unique; - private final boolean indexed; - - GraphPropertiesDictionary(String property,Class clazz, boolean unique,boolean indexed) { - this.property = property; - this.clazz = clazz; - this.unique = unique; - this.indexed = indexed; - } - + private final String property; + private final Class clazz; + private final boolean unique; + private final boolean indexed; - public String getProperty() { - return property; - } + GraphPropertiesDictionary(String property, Class clazz, boolean unique, boolean indexed) { + this.property = property; + this.clazz = clazz; + this.unique = unique; + this.indexed = indexed; + } - public Class getClazz() { - return clazz; - } - public boolean isUnique() { - return unique; - } + public String getProperty() { + return property; + } - public boolean isIndexed() { - return indexed; - } + public Class getClazz() { + return clazz; + } + + public boolean isUnique() { + return unique; + } + + public boolean isIndexed() { + return indexed; + } } diff --git a/catalog-dao/src/main/java/org/openecomp/sdc/be/resources/data/RelationshipTypeData.java b/catalog-dao/src/main/java/org/openecomp/sdc/be/resources/data/RelationshipTypeData.java index 32a86e42ce..440cddad55 100644 --- a/catalog-dao/src/main/java/org/openecomp/sdc/be/resources/data/RelationshipTypeData.java +++ b/catalog-dao/src/main/java/org/openecomp/sdc/be/resources/data/RelationshipTypeData.java @@ -57,13 +57,20 @@ public class RelationshipTypeData extends GraphNode { relationshipTypeDataDefinition .setDescription((String) properties.get(GraphPropertiesDictionary.DESCRIPTION.getProperty())); - Type listType = new TypeToken>() { + Type listSourceType = new TypeToken>() { }.getType(); List validSourceTypesfromJson = getGson().fromJson( - (String) properties.get(GraphPropertiesDictionary.VALID_SOURCE_TYPES.getProperty()), listType); + (String) properties.get(GraphPropertiesDictionary.VALID_SOURCE_TYPES.getProperty()), listSourceType); relationshipTypeDataDefinition.setValidSourceTypes(validSourceTypesfromJson); + Type listTargetType = new TypeToken>() { + }.getType(); + List validTargetTypesfromJson = getGson().fromJson( + (String) properties.get(GraphPropertiesDictionary.VALID_TARGET_TYPES.getProperty()), listTargetType); + + relationshipTypeDataDefinition.setValidTargetTypes(validTargetTypesfromJson); + // relationshipTypeDataDefinition.setValidSourceTypes((List) // properties.get(GraphPropertiesDictionary.VALID_SOURCE_TYPES // .getProperty())); @@ -98,6 +105,9 @@ public class RelationshipTypeData extends GraphNode { addIfExists(map, GraphPropertiesDictionary.VALID_SOURCE_TYPES, relationshipTypeDataDefinition.getValidSourceTypes()); + addIfExists(map, GraphPropertiesDictionary.VALID_TARGET_TYPES, + relationshipTypeDataDefinition.getValidTargetTypes()); + addIfExists(map, GraphPropertiesDictionary.CREATION_DATE, relationshipTypeDataDefinition.getCreationTime()); addIfExists(map, GraphPropertiesDictionary.LAST_UPDATE_DATE, diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/RelationshipTypeDefinition.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/RelationshipTypeDefinition.java new file mode 100644 index 0000000000..5b03d0ce1b --- /dev/null +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/RelationshipTypeDefinition.java @@ -0,0 +1,69 @@ +/* + * Copyright © 2016-2018 European Support Limited + * + * 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. + */ + + +package org.openecomp.sdc.be.model; + +import org.openecomp.sdc.be.datatypes.elements.RelationshipInstDataDefinition; +import org.openecomp.sdc.be.resources.data.RelationshipTypeData; + +import java.util.Map; + +/** + * Specifies the capabilities that the Node Type exposes. + */ +public class RelationshipTypeDefinition extends RelationshipInstDataDefinition { + + private String derivedFrom; + + private Map properties; + + public RelationshipTypeDefinition() { + super(); + } + + public RelationshipTypeDefinition(RelationshipInstDataDefinition p) { + super(p); + } + + public RelationshipTypeDefinition(RelationshipTypeData relationshipTypeData) { + this.setUniqueId(relationshipTypeData.getUniqueId()); + this.setType(relationshipTypeData.getRelationshipTypeDataDefinition().getType()); + this.setDescription(relationshipTypeData.getRelationshipTypeDataDefinition().getDescription()); + this.setValidSourceTypes(relationshipTypeData.getRelationshipTypeDataDefinition().getValidSourceTypes()); + } + + public String getDerivedFrom() { + return derivedFrom; + } + + public void setDerivedFrom(String derivedFrom) { + this.derivedFrom = derivedFrom; + } + + public Map getProperties() { + return properties; + } + + public void setProperties(Map properties) { + this.properties = properties; + } + + @Override + public String toString() { + return super.toString() + " [ derivedFrom=" + derivedFrom + ", properties=" + properties + " ]"; + } +} diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/datamodel/NodeType.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/datamodel/NodeType.java index 7ac941e5e2..4babd5d4a8 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/datamodel/NodeType.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/datamodel/NodeType.java @@ -34,9 +34,6 @@ public class NodeType extends ToscaElement{ private List derivedFrom; private List derivedList; private Map attributes; - private Map capabilties; - private Map capabiltiesProperties; - private Map requirements; private Map interfaceArtifacts; public List getDerivedList() { @@ -63,30 +60,6 @@ public class NodeType extends ToscaElement{ this.attributes = attributes; } - public Map getCapabilties() { - return capabilties; - } - - public void setCapabilties(Map capabilties) { - this.capabilties = capabilties; - } - - public Map getRequirements() { - return requirements; - } - - public void setRequirements(Map requirements) { - this.requirements = requirements; - } - - public Map getCapabiltiesProperties() { - return capabiltiesProperties; - } - - public void setCapabiltiesProperties(Map capabiltiesProperties) { - this.capabiltiesProperties = capabiltiesProperties; - } - public Map getInterfaceArtifacts() { return interfaceArtifacts; } diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/datamodel/ToscaElement.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/datamodel/ToscaElement.java index 0f0c63f7fb..a18c75bca7 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/datamodel/ToscaElement.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/datamodel/ToscaElement.java @@ -22,6 +22,9 @@ package org.openecomp.sdc.be.model.jsontitan.datamodel; import org.openecomp.sdc.be.datatypes.elements.AdditionalInfoParameterDataDefinition; import org.openecomp.sdc.be.datatypes.elements.ArtifactDataDefinition; +import org.openecomp.sdc.be.datatypes.elements.ListCapabilityDataDefinition; +import org.openecomp.sdc.be.datatypes.elements.ListRequirementDataDefinition; +import org.openecomp.sdc.be.datatypes.elements.MapPropertiesDataDefinition; import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition; import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum; import org.openecomp.sdc.be.datatypes.enums.JsonPresentationFields; @@ -45,6 +48,9 @@ public abstract class ToscaElement { private Map deploymentArtifacts; private Map additionalInformation; private Map properties; + private Map capabilities; + private Map capabiltiesProperties; + private Map requirements; protected ToscaElementTypeEnum toscaType; // User @@ -125,6 +131,30 @@ public abstract class ToscaElement { this.allVersions = allVersions; } + public Map getCapabilities() { + return capabilities; + } + + public void setCapabilities(Map capabilities) { + this.capabilities = capabilities; + } + + public Map getRequirements() { + return requirements; + } + + public void setRequirements(Map requirements) { + this.requirements = requirements; + } + + public Map getCapabilitiesProperties() { + return capabiltiesProperties; + } + + public void setCapabilitiesProperties(Map capabiltiesProperties) { + this.capabiltiesProperties = capabiltiesProperties; + } + // metadata properties // ---------------------------- public Object getMetadataValue(JsonPresentationFields name) { diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/BaseOperation.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/BaseOperation.java index 52801751cc..b18fb96e8e 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/BaseOperation.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/BaseOperation.java @@ -24,6 +24,7 @@ import com.thinkaurelius.titan.core.TitanVertex; import fj.data.Either; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; +import org.apache.commons.lang.ObjectUtils; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang3.tuple.ImmutablePair; import org.apache.commons.lang3.tuple.Pair; @@ -1390,6 +1391,15 @@ public abstract class BaseOperation { StorageOperationStatus status = StorageOperationStatus.OK; String currKey = (String) toscaDataElement.getToscaPresentationValue(mapKeyField); + + if(StringUtils.isEmpty(currKey) && toscaDataElement instanceof ListDataDefinition) { + ToscaDataDefinition toscaDataDefinition = ((ListDataDefinition) toscaDataElement) + .getListToscaDataDefinition().get(0); + if(toscaDataDefinition != null) { + currKey = (String) toscaDataDefinition.getToscaPresentationValue(mapKeyField); + } + } + if (StringUtils.isEmpty(currKey)) { CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to add tosca data to tosca element {}. The key is empty. "); status = StorageOperationStatus.BAD_REQUEST; diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/CapabilitiesOperation.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/CapabilitiesOperation.java new file mode 100644 index 0000000000..a8337b6c4f --- /dev/null +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/CapabilitiesOperation.java @@ -0,0 +1,91 @@ +/* + * Copyright © 2016-2018 European Support Limited + * + * 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. + */ + +package org.openecomp.sdc.be.model.jsontitan.operations; + +import fj.data.Either; +import org.openecomp.sdc.be.dao.jsongraph.types.EdgeLabelEnum; +import org.openecomp.sdc.be.dao.jsongraph.types.VertexTypeEnum; +import org.openecomp.sdc.be.datatypes.elements.CapabilityDataDefinition; +import org.openecomp.sdc.be.datatypes.elements.ListCapabilityDataDefinition; +import org.openecomp.sdc.be.datatypes.enums.JsonPresentationFields; +import org.openecomp.sdc.be.model.CapabilityDefinition; +import org.openecomp.sdc.be.model.Component; +import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +@org.springframework.stereotype.Component("capabilities-operation") +public class CapabilitiesOperation extends BaseOperation { + private static final Logger LOGGER = LoggerFactory.getLogger(CapabilitiesOperation.class); + + public Either, StorageOperationStatus> addCapabilities( + String componentId, + List capabilityDefinitions) { + return addOrUpdateCapabilities(componentId, capabilityDefinitions, false); + } + + public Either, StorageOperationStatus> updateCapabilities( + String componentId, + List capabilityDefinitions) { + return addOrUpdateCapabilities(componentId, capabilityDefinitions, true); + } + + private Either, StorageOperationStatus> addOrUpdateCapabilities(String componentId, + List capabilityDefinitions, + boolean isUpdateAction) { + StorageOperationStatus statusRes = performUpdateToscaAction(isUpdateAction, + componentId, Collections + .singletonList(convertToListCapabilityDataDefinition(capabilityDefinitions))); + if (!statusRes.equals(StorageOperationStatus.OK)) { + titanDao.rollback(); + LOGGER.error("Failed to find the parent capability of capability type {}." + + " status is {}", componentId, statusRes); + return Either.right(statusRes); + } + titanDao.commit(); + return Either.left(capabilityDefinitions); + } + + public StorageOperationStatus deleteCapabilities(Component component, + String capabilityIdToDelete) { + return deleteToscaDataElements(component.getUniqueId(), + EdgeLabelEnum.CAPABILITIES, + Collections.singletonList(capabilityIdToDelete)); + } + + private static ListCapabilityDataDefinition convertToListCapabilityDataDefinition( + List capabilities) { + List capabilityDefinitions = new ArrayList<>(capabilities); + return new ListCapabilityDataDefinition(capabilityDefinitions); + } + + private StorageOperationStatus performUpdateToscaAction(boolean isUpdate, + String componentId, + List toscaDataList) { + if (isUpdate) { + return updateToscaDataOfToscaElement(componentId, EdgeLabelEnum.CAPABILITIES, + VertexTypeEnum.CAPABILITIES, toscaDataList, JsonPresentationFields.TYPE); + } else { + return addToscaDataToToscaElement(componentId, EdgeLabelEnum.CAPABILITIES, + VertexTypeEnum.CAPABILITIES, toscaDataList, JsonPresentationFields.TYPE); + } + } +} diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/NodeTemplateOperation.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/NodeTemplateOperation.java index 95f518aace..7bd36eacd1 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/NodeTemplateOperation.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/NodeTemplateOperation.java @@ -668,58 +668,145 @@ public class NodeTemplateOperation extends BaseOperation { return instInput; } + private MapListCapabilityDataDefinition prepareCalculatedCapabiltyForTopologyTemplate( + Map capabilities, + ComponentInstanceDataDefinition componentInstance, + MapListCapabilityDataDefinition calculatedCap) { + if (capabilities != null) { + MapListCapabilityDataDefinition allCalculatedCap = + new MapListCapabilityDataDefinition(calculatedCap); + populateCapability(capabilities, componentInstance, allCalculatedCap); + return allCalculatedCap; + } + return null; + } + + private void populateCapability(Map capabilities, + ComponentInstanceDataDefinition componentInstance, + MapListCapabilityDataDefinition allCalculatedCap) { + capabilities.forEach((key, value) -> { + List listCapabilities = value.getListToscaDataDefinition() + .stream().map(CapabilityDataDefinition::new).collect(Collectors.toList()); + listCapabilities.forEach(cap -> { + cap.setSource(componentInstance.getComponentUid()); + cap.addToPath(componentInstance.getUniqueId()); + cap.setOwnerId(componentInstance.getUniqueId()); + cap.setOwnerName(componentInstance.getName()); + cap.setLeftOccurrences(cap.getMaxOccurrences()); + allCalculatedCap.add(key, cap); + }); + }); + } + + private MapListRequirementDataDefinition prepareCalculatedRequirementForTopologyTemplate( + Map requirements, + ComponentInstanceDataDefinition componentInstance, + MapListRequirementDataDefinition calculatedReqs) { + if (requirements != null) { + MapListRequirementDataDefinition allCalculatedReq = + new MapListRequirementDataDefinition(calculatedReqs); + + populateRequirement(requirements, componentInstance, allCalculatedReq); + return allCalculatedReq; + } + return null; + } + private void populateRequirement(Map requirements, + ComponentInstanceDataDefinition componentInstance, + MapListRequirementDataDefinition allCalculatedReq) { + requirements.forEach((key, value) -> { + List listRequirements = value.getListToscaDataDefinition() + .stream().map(RequirementDataDefinition::new).collect(Collectors.toList()); + listRequirements.forEach(req -> { + req.setSource(componentInstance.getComponentUid()); + req.addToPath(componentInstance.getUniqueId()); + req.setOwnerId(componentInstance.getUniqueId()); + req.setOwnerName(componentInstance.getName()); + req.setLeftOccurrences(req.getMaxOccurrences()); + allCalculatedReq.add(key, req); + }); + }); + } + + + private StorageOperationStatus addCalculatedCapReqFromTopologyTemplate(TopologyTemplate originTopologyTemplate, ComponentInstanceDataDefinition componentInstance, GraphVertex updatedContainerVertex) { Map calculatedCapabilities = originTopologyTemplate.getCalculatedCapabilities(); + MapListCapabilityDataDefinition allCalculatedCap = new MapListCapabilityDataDefinition(); if (calculatedCapabilities != null) { - MapListCapabilityDataDefinition allCalculatedCap = new MapListCapabilityDataDefinition(); - calculatedCapabilities.entrySet().forEach(enntryPerInstance -> { - Map mapByType = enntryPerInstance.getValue().getMapToscaDataDefinition(); - mapByType.entrySet().forEach(entryPerType -> - entryPerType.getValue().getListToscaDataDefinition().forEach(cap -> { - cap.addToPath(componentInstance.getUniqueId()); - allCalculatedCap.add(entryPerType.getKey(), cap); - })); + calculatedCapabilities.forEach((key1, value1) -> { + Map mapByType = value1.getMapToscaDataDefinition(); + mapByType.forEach((key, value) -> value.getListToscaDataDefinition().forEach(cap -> { + cap.addToPath(componentInstance.getUniqueId()); + allCalculatedCap.add(key, cap); + })); }); - - StorageOperationStatus calculatedResult = addToscaDataDeepElementsBlockToToscaElement(updatedContainerVertex, EdgeLabelEnum.CALCULATED_CAPABILITIES, VertexTypeEnum.CALCULATED_CAPABILITIES, allCalculatedCap, - componentInstance.getUniqueId()); - - if (calculatedResult != StorageOperationStatus.OK) { - return calculatedResult; + } + MapListCapabilityDataDefinition allCaps; + Map capabilities = originTopologyTemplate.getCapabilities(); + if (MapUtils.isNotEmpty(capabilities)) { + allCaps = prepareCalculatedCapabiltyForTopologyTemplate(capabilities, componentInstance, + allCalculatedCap); + } else { + allCaps = new MapListCapabilityDataDefinition(allCalculatedCap); + } + if(!allCaps.isEmpty()) { + StorageOperationStatus calculatedCapabilitiesResult = + addToscaDataDeepElementsBlockToToscaElement(updatedContainerVertex, + EdgeLabelEnum.CALCULATED_CAPABILITIES, VertexTypeEnum.CALCULATED_CAPABILITIES, + allCaps, componentInstance.getUniqueId()); + if (calculatedCapabilitiesResult != StorageOperationStatus.OK) { + return calculatedCapabilitiesResult; } MapListCapabilityDataDefinition fullCalculatedCap = new MapListCapabilityDataDefinition(); - calculatedResult = addToscaDataDeepElementsBlockToToscaElement(updatedContainerVertex, EdgeLabelEnum.FULLFILLED_CAPABILITIES, VertexTypeEnum.FULLFILLED_CAPABILITIES, fullCalculatedCap, componentInstance.getUniqueId()); - - if (calculatedResult != StorageOperationStatus.OK) { - return calculatedResult; + calculatedCapabilitiesResult = addToscaDataDeepElementsBlockToToscaElement(updatedContainerVertex, + EdgeLabelEnum.FULLFILLED_CAPABILITIES, VertexTypeEnum.FULLFILLED_CAPABILITIES, + fullCalculatedCap, componentInstance.getUniqueId()); + if (calculatedCapabilitiesResult != StorageOperationStatus.OK) { + return calculatedCapabilitiesResult; } } - Map calculatedRequirements = originTopologyTemplate.getCalculatedRequirements(); + Map calculatedRequirements = + originTopologyTemplate.getCalculatedRequirements(); + MapListRequirementDataDefinition allCalculatedReq = new MapListRequirementDataDefinition(); if (calculatedRequirements != null) { - - MapListRequirementDataDefinition allCalculatedReq = new MapListRequirementDataDefinition(); - calculatedRequirements.entrySet().forEach(enntryPerInstance -> { - Map mapByType = enntryPerInstance.getValue().getMapToscaDataDefinition(); - mapByType.entrySet().forEach(entryPerType -> - entryPerType.getValue().getListToscaDataDefinition().forEach(req -> { - req.addToPath(componentInstance.getUniqueId()); - allCalculatedReq.add(entryPerType.getKey(), req); - })); + calculatedRequirements.forEach((key, value) -> { + Map mapByType = + value.getMapToscaDataDefinition(); + mapByType.forEach((key1, value1) -> value1.getListToscaDataDefinition().forEach(req -> { + req.addToPath(componentInstance.getUniqueId()); + allCalculatedReq.add(key1, req); + })); }); - StorageOperationStatus calculatedResult = addToscaDataDeepElementsBlockToToscaElement(updatedContainerVertex, EdgeLabelEnum.CALCULATED_REQUIREMENTS, VertexTypeEnum.CALCULATED_REQUIREMENTS, allCalculatedReq, - componentInstance.getUniqueId()); - if (calculatedResult != StorageOperationStatus.OK) { - return calculatedResult; + } + + MapListRequirementDataDefinition allReqs; + Map requirements = originTopologyTemplate.getRequirements(); + if (MapUtils.isNotEmpty(requirements)) { + allReqs = prepareCalculatedRequirementForTopologyTemplate(requirements, + componentInstance, allCalculatedReq); + } else + allReqs = new MapListRequirementDataDefinition(allCalculatedReq); + + if(!allReqs.isEmpty()) { + StorageOperationStatus calculatedRequirementResult = + addToscaDataDeepElementsBlockToToscaElement(updatedContainerVertex, + EdgeLabelEnum.CALCULATED_REQUIREMENTS, VertexTypeEnum.CALCULATED_REQUIREMENTS, + allReqs, componentInstance.getUniqueId()); + if (calculatedRequirementResult != StorageOperationStatus.OK) { + return calculatedRequirementResult; } MapListRequirementDataDefinition fullCalculatedReq = new MapListRequirementDataDefinition(); - calculatedResult = addToscaDataDeepElementsBlockToToscaElement(updatedContainerVertex, EdgeLabelEnum.FULLFILLED_REQUIREMENTS, VertexTypeEnum.FULLFILLED_REQUIREMENTS, fullCalculatedReq, componentInstance.getUniqueId()); - if (calculatedResult != StorageOperationStatus.OK) { - return calculatedResult; + calculatedRequirementResult = addToscaDataDeepElementsBlockToToscaElement(updatedContainerVertex, + EdgeLabelEnum.FULLFILLED_REQUIREMENTS, VertexTypeEnum.FULLFILLED_REQUIREMENTS, + fullCalculatedReq, + componentInstance.getUniqueId()); + if (calculatedRequirementResult != StorageOperationStatus.OK) { + return calculatedRequirementResult; } } - Map calculatedCapabilitiesProperties = originTopologyTemplate.getCalculatedCapabilitiesProperties(); Map updateKeyMap = new HashMap<>(); @@ -730,9 +817,27 @@ public class NodeTemplateOperation extends BaseOperation { updateKeyMap.put(newKey, entry.getValue()); } } - MapCapabilityProperty mapCapabilityProperty = new MapCapabilityProperty(updateKeyMap); - StorageOperationStatus calculatedResult = addToscaDataDeepElementsBlockToToscaElement(updatedContainerVertex, EdgeLabelEnum.CALCULATED_CAP_PROPERTIES, VertexTypeEnum.CALCULATED_CAP_PROPERTIES, mapCapabilityProperty, - componentInstance.getUniqueId()); + } + Map capabilitiesProperties = + originTopologyTemplate.getCapabilitiesProperties(); + Map updateKeyMapCapabilitiesProperties; + if (MapUtils.isNotEmpty(capabilitiesProperties)) { + updateKeyMapCapabilitiesProperties = capabilitiesProperties.entrySet().stream() + .collect(Collectors.toMap(e -> createCapPropertyKey(e.getKey(), + componentInstance.getUniqueId()), Entry::getValue)); + } + else { + updateKeyMapCapabilitiesProperties = new HashMap<>(); + } + updateKeyMap.putAll(updateKeyMapCapabilitiesProperties); + MapCapabilityProperty mapCapabilityProperty = new MapCapabilityProperty(updateKeyMap); + + if(MapUtils.isNotEmpty(capabilitiesProperties) || MapUtils.isNotEmpty(calculatedCapabilitiesProperties )) { + StorageOperationStatus calculatedResult = + addToscaDataDeepElementsBlockToToscaElement(updatedContainerVertex, + EdgeLabelEnum.CALCULATED_CAP_PROPERTIES, + VertexTypeEnum.CALCULATED_CAP_PROPERTIES, mapCapabilityProperty, + componentInstance.getUniqueId()); if (calculatedResult != StorageOperationStatus.OK) { return calculatedResult; } @@ -857,7 +962,7 @@ public class NodeTemplateOperation extends BaseOperation { */ private StorageOperationStatus addCalculatedCapReqFromNodeType(NodeType originNodeType, ComponentInstanceDataDefinition componentInstance, GraphVertex updatedContainerVertex) { - Map capabilities = originNodeType.getCapabilties(); + Map capabilities = originNodeType.getCapabilities(); MapListCapabilityDataDefinition allCalculatedCap = prepareCalculatedCapabiltyForNodeType(capabilities, componentInstance); StorageOperationStatus calculatedResult; if (allCalculatedCap != null) { @@ -867,7 +972,7 @@ public class NodeTemplateOperation extends BaseOperation { return calculatedResult; } } - Map capabiltiesProperties = originNodeType.getCapabiltiesProperties(); + Map capabiltiesProperties = originNodeType.getCapabilitiesProperties(); if (capabiltiesProperties != null) { Map updateKeyMap = capabiltiesProperties.entrySet().stream().collect(Collectors.toMap(e -> createCapPropertyKey(e.getKey(), componentInstance.getUniqueId()), Entry::getValue)); MapCapabilityProperty mapCapabilityProperty = new MapCapabilityProperty(updateKeyMap); @@ -918,17 +1023,7 @@ public class NodeTemplateOperation extends BaseOperation { if (capabilities != null) { MapListCapabilityDataDefinition allCalculatedCap = new MapListCapabilityDataDefinition(); - capabilities.entrySet().forEach(e -> { - List listCapabilities = e.getValue().getListToscaDataDefinition().stream().map(CapabilityDataDefinition::new).collect(Collectors.toList()); - listCapabilities.forEach(cap -> { - cap.setSource(componentInstance.getComponentUid()); - cap.addToPath(componentInstance.getUniqueId()); - cap.setOwnerId(componentInstance.getUniqueId()); - cap.setOwnerName(componentInstance.getName()); - cap.setLeftOccurrences(cap.getMaxOccurrences()); - allCalculatedCap.add(e.getKey(), cap); - }); - }); + populateCapability(capabilities, componentInstance, allCalculatedCap); return allCalculatedCap; } return null; @@ -945,17 +1040,7 @@ public class NodeTemplateOperation extends BaseOperation { if (requirements != null) { MapListRequirementDataDefinition allCalculatedReq = new MapListRequirementDataDefinition(); - requirements.entrySet().forEach(e -> { - List listRequirements = e.getValue().getListToscaDataDefinition().stream().map(RequirementDataDefinition::new).collect(Collectors.toList()); - listRequirements.forEach(req -> { - req.setSource(componentInstance.getComponentUid()); - req.addToPath(componentInstance.getUniqueId()); - req.setOwnerId(componentInstance.getUniqueId()); - req.setOwnerName(componentInstance.getName()); - req.setLeftOccurrences(req.getMaxOccurrences()); - allCalculatedReq.add(e.getKey(), req); - }); - }); + populateRequirement(requirements, componentInstance, allCalculatedReq); return allCalculatedReq; } return null; @@ -1135,7 +1220,7 @@ public class NodeTemplateOperation extends BaseOperation { requirementAndRelationshipPair.setId(relationshipInstData.getUniqueId()); CapabilityRequirementRelationship capReqRel = new CapabilityRequirementRelationship(); capReqRel.setRelation(requirementAndRelationshipPair); - capReqRel.setCapability((CapabilityDataDefinition) associateRes.left().value().get(JsonPresentationFields.CAPAPILITY)); + capReqRel.setCapability((CapabilityDataDefinition) associateRes.left().value().get(JsonPresentationFields.CAPABILITY)); capReqRel.setRequirement((RequirementDataDefinition) associateRes.left().value().get(JsonPresentationFields.REQUIREMENT)); relationshipsResult.add(capReqRel); CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "update customization UUID for from CI {} and to CI {}", relation.getFromNode(), relation.getToNode()); @@ -1680,7 +1765,7 @@ public class NodeTemplateOperation extends BaseOperation { CapabilityDataDefinition cap = iteratorCap.next(); if (cap.getUniqueId().equals(relationPair.getCapabilityUid()) && cap.getOwnerId().equals(relationPair.getCapabilityOwnerId())) { capabilityForRelation = cap; - capReqRelationship.put(JsonPresentationFields.CAPAPILITY, (T) capabilityForRelation); + capReqRelationship.put(JsonPresentationFields.CAPABILITY, (T) capabilityForRelation); String leftOccurrences = cap.getLeftOccurrences(); if (leftOccurrences != null && !leftOccurrences.equals(CapabilityDataDefinition.MAX_OCCURRENCES)) { Integer leftIntValue = Integer.parseInt(leftOccurrences); @@ -1807,23 +1892,23 @@ public class NodeTemplateOperation extends BaseOperation { return relationshipInstData; } - public StorageOperationStatus associateComponentInstancesToComponent(Component containerComponent, Map resourcesInstancesMap, GraphVertex containerVertex, boolean allowDeleted) { + public StorageOperationStatus associateComponentInstancesToComponent(Component containerComponent, Map componentInstanceTMap, GraphVertex containerVertex, boolean allowDeleted) { StorageOperationStatus result = null; String containerId = containerComponent.getUniqueId(); Map instancesJsonData = null; Either updateElement = null; - if (!validateInstanceNames(resourcesInstancesMap)) { + if (!validateInstanceNames(componentInstanceTMap)) { result = StorageOperationStatus.INCONSISTENCY; } - if (result == null && !validateInstanceNames(resourcesInstancesMap)) { + if (result == null && !validateInstanceNames(componentInstanceTMap)) { result = StorageOperationStatus.INCONSISTENCY; } - if (result == null && !allowDeleted && !validateDeletedResources(resourcesInstancesMap)) { + if (result == null && !allowDeleted && !validateDeletedResources(componentInstanceTMap)) { result = StorageOperationStatus.INCONSISTENCY; } if (result == null) { - instancesJsonData = convertToComponentInstanceDataDefinition(resourcesInstancesMap, containerId); + instancesJsonData = convertToComponentInstanceDataDefinition(componentInstanceTMap, containerId); } if (result == null && MapUtils.isNotEmpty(instancesJsonData)) { containerVertex.setJsonMetadataField(JsonPresentationFields.LAST_UPDATE_DATE, System.currentTimeMillis()); @@ -1846,21 +1931,21 @@ public class NodeTemplateOperation extends BaseOperation { return result; } - private Map convertToComponentInstanceDataDefinition(Map resourcesInstancesMap, String containerId) { + private Map convertToComponentInstanceDataDefinition(Map componentInstanceTMap, String containerId) { Map instances = new HashMap<>(); - for (Entry entry : resourcesInstancesMap.entrySet()) { + for (Entry entry : componentInstanceTMap.entrySet()) { ComponentInstanceDataDefinition instance = buildComponentInstanceDataDefinition(entry.getKey(), containerId, null, true, ModelConverter.convertToToscaElement(entry.getValue())); instances.put(instance.getUniqueId(), instance); } return instances; } - private boolean validateDeletedResources(Map resourcesInstancesMap) { + private boolean validateDeletedResources(Map resourcesInstancesMap) { boolean result = true; - for (Resource resource : resourcesInstancesMap.values()) { - if (resource.getIsDeleted() != null && resource.getIsDeleted()) { - CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Component {} is already deleted. Cannot add component instance. ", resource.getName()); + for (Component component : resourcesInstancesMap.values()) { + if (component.getIsDeleted() != null && component.getIsDeleted()) { + CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Component {} is already deleted. Cannot add component instance. ", component.getName()); result = false; break; } @@ -1868,7 +1953,7 @@ public class NodeTemplateOperation extends BaseOperation { return result; } - private boolean validateInstanceNames(Map resourcesInstancesMap) { + private boolean validateInstanceNames(Map resourcesInstancesMap) { boolean result = true; Set names = new HashSet<>(); for (ComponentInstance instance : resourcesInstancesMap.keySet()) { diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/NodeTypeOperation.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/NodeTypeOperation.java index d9ced8c249..967fc16c49 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/NodeTypeOperation.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/NodeTypeOperation.java @@ -289,7 +289,7 @@ public class NodeTypeOperation extends ToscaElementOperation { private TitanOperationStatus setComponentCapPropertiesFromGraph(GraphVertex componentV, NodeType toscaElement) { Either, TitanOperationStatus> result = getDataFromGraph(componentV, EdgeLabelEnum.CAPABILITIES_PROPERTIES); if (result.isLeft()) { - toscaElement.setCapabiltiesProperties(result.left().value()); + toscaElement.setCapabilitiesProperties(result.left().value()); } else { if (result.right().value() != TitanOperationStatus.NOT_FOUND) { return result.right().value(); @@ -317,7 +317,7 @@ public class NodeTypeOperation extends ToscaElementOperation { private TitanOperationStatus setResourceCapabilitiesFromGraph(GraphVertex componentV, NodeType toscaElement) { Either, TitanOperationStatus> result = getDataFromGraph(componentV, EdgeLabelEnum.CAPABILITIES); if (result.isLeft()) { - toscaElement.setCapabilties(result.left().value()); + toscaElement.setCapabilities(result.left().value()); } else { if (result.right().value() != TitanOperationStatus.NOT_FOUND) { return result.right().value(); @@ -448,7 +448,7 @@ public class NodeTypeOperation extends ToscaElementOperation { } Map capabiltiesAll = dataFromDerived.left().value(); - Map capabilties = nodeType.getCapabilties(); + Map capabilties = nodeType.getCapabilities(); if (capabilties != null) { if (capabiltiesAll == null) { capabiltiesAll = new HashMap<>(); @@ -483,7 +483,7 @@ public class NodeTypeOperation extends ToscaElementOperation { }); }); if (!capabiltiesAll.isEmpty()) { - Either assosiateElementToData = associateElementToData(nodeTypeVertex, VertexTypeEnum.CAPABILTIES, EdgeLabelEnum.CAPABILITIES, capabiltiesAll); + Either assosiateElementToData = associateElementToData(nodeTypeVertex, VertexTypeEnum.CAPABILITIES, EdgeLabelEnum.CAPABILITIES, capabiltiesAll); if (assosiateElementToData.isRight()) { return assosiateElementToData.right().value(); } @@ -556,7 +556,7 @@ public class NodeTypeOperation extends ToscaElementOperation { return dataFromDerived.right().value(); } Map propertiesAll = dataFromDerived.left().value(); - Map capabiltiesProps = nodeType.getCapabiltiesProperties(); + Map capabiltiesProps = nodeType.getCapabilitiesProperties(); if (capabiltiesProps != null) { capabiltiesProps.values().forEach(l -> { if (l.getMapToscaDataDefinition() != null && l.getMapToscaDataDefinition().values() != null) { diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/RequirementOperation.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/RequirementOperation.java new file mode 100644 index 0000000000..1fd37500bf --- /dev/null +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/RequirementOperation.java @@ -0,0 +1,92 @@ +/* + * Copyright © 2016-2018 European Support Limited + * + * 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. + */ + +package org.openecomp.sdc.be.model.jsontitan.operations; + +import fj.data.Either; +import org.openecomp.sdc.be.dao.jsongraph.types.EdgeLabelEnum; +import org.openecomp.sdc.be.dao.jsongraph.types.VertexTypeEnum; +import org.openecomp.sdc.be.datatypes.elements.ListRequirementDataDefinition; +import org.openecomp.sdc.be.datatypes.elements.RequirementDataDefinition; +import org.openecomp.sdc.be.datatypes.enums.JsonPresentationFields; +import org.openecomp.sdc.be.model.Component; +import org.openecomp.sdc.be.model.RequirementDefinition; +import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +@org.springframework.stereotype.Component("requirement-operation") +public class RequirementOperation extends BaseOperation { + private static final Logger LOGGER = LoggerFactory.getLogger(RequirementOperation.class); + + public Either, StorageOperationStatus> addRequirement( + String componentId, + List requirementDefinitions) { + return addOrUpdateRequirements( componentId, requirementDefinitions, false); + } + + public Either, StorageOperationStatus> updateRequirement( + String componentId, + List requirementDefinitions) { + return addOrUpdateRequirements( componentId, requirementDefinitions, true); + } + + + private Either, StorageOperationStatus> addOrUpdateRequirements(String componentId, + List requirementDefinitions, + boolean isUpdateAction) { + + StorageOperationStatus statusRes = performUpdateToscaAction(isUpdateAction, + componentId, Collections + .singletonList(convertToListRequirementDataDefinition(requirementDefinitions))); + if (!statusRes.equals(StorageOperationStatus.OK)) { + titanDao.rollback(); + LOGGER.error("Failed to find the parent capability of capability type {}." + + " status is {}", componentId, statusRes); + return Either.right(statusRes); + } + titanDao.commit(); + return Either.left(requirementDefinitions); + } + + public StorageOperationStatus deleteRequirements(Component component, + String requirementToDelete) { + return deleteToscaDataElements(component.getUniqueId(), + EdgeLabelEnum.REQUIREMENTS, Collections.singletonList(requirementToDelete)); + } + + private static ListRequirementDataDefinition convertToListRequirementDataDefinition( + List requirementDefinitions) { + List requirementDataDefinitions = + new ArrayList<>(requirementDefinitions); + return new ListRequirementDataDefinition(requirementDataDefinitions); + } + + private StorageOperationStatus performUpdateToscaAction(boolean isUpdate, + String componentId, List toscaDataList) { + if (isUpdate) { + return updateToscaDataOfToscaElement(componentId, EdgeLabelEnum.REQUIREMENTS, + VertexTypeEnum.REQUIREMENTS, toscaDataList, JsonPresentationFields.CAPABILITY); + } else { + return addToscaDataToToscaElement(componentId, EdgeLabelEnum.REQUIREMENTS, + VertexTypeEnum.REQUIREMENTS, toscaDataList, JsonPresentationFields.CAPABILITY); + } + } +} diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/TopologyTemplateOperation.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/TopologyTemplateOperation.java index 38c6b5d16e..095425748a 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/TopologyTemplateOperation.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/TopologyTemplateOperation.java @@ -50,6 +50,8 @@ import org.openecomp.sdc.be.datatypes.elements.CompositionDataDefinition; import org.openecomp.sdc.be.datatypes.elements.ForwardingPathDataDefinition; import org.openecomp.sdc.be.datatypes.elements.GroupDataDefinition; import org.openecomp.sdc.be.datatypes.elements.InterfaceDataDefinition; +import org.openecomp.sdc.be.datatypes.elements.ListCapabilityDataDefinition; +import org.openecomp.sdc.be.datatypes.elements.ListRequirementDataDefinition; import org.openecomp.sdc.be.datatypes.elements.MapArtifactDataDefinition; import org.openecomp.sdc.be.datatypes.elements.MapCapabilityProperty; import org.openecomp.sdc.be.datatypes.elements.MapDataDefinition; @@ -272,6 +274,15 @@ public class TopologyTemplateOperation extends ToscaElementOperation { return assosiateElementToData.right().value(); } } + Map capabilities = topologyTemplate.getCapabilities(); + if(MapUtils.isNotEmpty(capabilities)) { + Either associateElementToData = + associateElementToData(nodeTypeVertex, VertexTypeEnum.CAPABILITIES, + EdgeLabelEnum.CAPABILITIES, capabilities); + if (associateElementToData.isRight()) { + return associateElementToData.right().value(); + } + } return StorageOperationStatus.OK; } @@ -291,6 +302,15 @@ public class TopologyTemplateOperation extends ToscaElementOperation { return assosiateElementToData.right().value(); } } + Map requirements = topologyTemplate.getRequirements(); + if(MapUtils.isNotEmpty(requirements)) { + Either associateElementToData = + associateElementToData(nodeTypeVertex, VertexTypeEnum.REQUIREMENTS, + EdgeLabelEnum.REQUIREMENTS, requirements); + if (associateElementToData.isRight()) { + return associateElementToData.right().value(); + } + } return StorageOperationStatus.OK; } @@ -905,6 +925,15 @@ public class TopologyTemplateOperation extends ToscaElementOperation { return result.right().value(); } } + Either, TitanOperationStatus> requirementResult = + getDataFromGraph(componentV, EdgeLabelEnum.REQUIREMENTS); + if (requirementResult.isLeft()) { + toscaElement.setRequirements(requirementResult.left().value()); + } else { + if (requirementResult.right().value() != TitanOperationStatus.NOT_FOUND) { + return requirementResult.right().value(); + } + } return TitanOperationStatus.OK; } @@ -926,6 +955,15 @@ public class TopologyTemplateOperation extends ToscaElementOperation { return result.right().value(); } } + Either, TitanOperationStatus> capabilitiesResult = + getDataFromGraph(componentV, EdgeLabelEnum.CAPABILITIES); + if (capabilitiesResult.isLeft()) { + toscaElement.setCapabilities(capabilitiesResult.left().value()); + } else { + if (capabilitiesResult.right().value() != TitanOperationStatus.NOT_FOUND) { + return capabilitiesResult.right().value(); + } + } return TitanOperationStatus.OK; } @@ -1139,6 +1177,21 @@ public class TopologyTemplateOperation extends ToscaElementOperation { return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status)); } + status = titanDao.disassociateAndDeleteLast(toscaElementVertex, Direction.OUT, + EdgeLabelEnum.REQUIREMENTS); + if (status != TitanOperationStatus.OK) { + log.debug("Failed to disassociate requirements for {} error {}", + toscaElementVertex.getUniqueId(), status); + Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status)); + } + status = titanDao.disassociateAndDeleteLast(toscaElementVertex, Direction.OUT, + EdgeLabelEnum.CAPABILITIES); + if (status != TitanOperationStatus.OK) { + log.debug("Failed to disassociate capabilities for {} error {}", + toscaElementVertex.getUniqueId(), status); + Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status)); + } + toscaElementVertex.getVertex().remove(); log.trace("Tosca element vertex for {} was removed", toscaElementVertex.getUniqueId()); @@ -1444,5 +1497,32 @@ public class TopologyTemplateOperation extends ToscaElementOperation { filter.setIgnoreRequirements(false); return filter; } + public void updateCapReqOwnerId(String componentId, TopologyTemplate toscaElement) { + GraphVertex toscaElementV = titanDao.getVertexById(componentId, JsonParseFlagEnum.NoParse) + .left().on(this::throwStorageException); + updateCapOwnerId(toscaElement, componentId); + updateReqOwnerId(toscaElement, componentId); + topologyTemplateOperation + + .updateFullToscaData(toscaElementV, EdgeLabelEnum.CAPABILITIES, + VertexTypeEnum.CAPABILITIES, toscaElement.getCapabilities()); + topologyTemplateOperation + .updateFullToscaData(toscaElementV, EdgeLabelEnum.REQUIREMENTS, + VertexTypeEnum.REQUIREMENTS, toscaElement.getRequirements()); + } + + private void updateCapOwnerId(ToscaElement toscaElement, String ownerId) { + if(MapUtils.isNotEmpty(toscaElement.getCapabilities())) { + toscaElement.getCapabilities().values().stream().flatMap(listCapDef -> listCapDef.getListToscaDataDefinition().stream()) + .forEach(capabilityDefinition -> capabilityDefinition.setOwnerId(ownerId)); + } + } + + private void updateReqOwnerId(ToscaElement toscaElement, String ownerId) { + if(MapUtils.isNotEmpty(toscaElement.getRequirements())) { + toscaElement.getRequirements().values().stream().flatMap(listReqDef -> listReqDef.getListToscaDataDefinition().stream()) + .forEach(requirementDefinition -> requirementDefinition.setOwnerId(ownerId)); + } + } } diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/ToscaOperationFacade.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/ToscaOperationFacade.java index d8a4fc4af1..a69c80cd36 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/ToscaOperationFacade.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/ToscaOperationFacade.java @@ -2546,5 +2546,8 @@ public class ToscaOperationFacade { } return Either.left(parentComponents); } - + public void updateCapReqOwnerId(String componentId) { + topologyTemplateOperation + .updateCapReqOwnerId(componentId, getTopologyTemplate(componentId)); + } } diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/utils/ModelConverter.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/utils/ModelConverter.java index 5e40bd57e7..6fbd7adc98 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/utils/ModelConverter.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/utils/ModelConverter.java @@ -152,6 +152,8 @@ public class ModelConverter { convertServiceInterfaces(topologyTemplate, service); convertNodeFiltersComponents(topologyTemplate, service); + setCapabilitiesToComponent(topologyTemplate, service); + setRequirementsToComponent(topologyTemplate, service); return service; } @@ -200,6 +202,8 @@ public class ModelConverter { convertPolicies(topologyTemplate, resource); convertNodeFiltersComponents(topologyTemplate, resource); convertProperties(topologyTemplate, resource); + setCapabilitiesToComponent(topologyTemplate, resource); + setRequirementsToComponent(topologyTemplate, resource); } convertArtifacts(toscaElement, resource); convertAdditionalInformation(toscaElement, resource); @@ -401,6 +405,7 @@ public class ModelConverter { } private static void convertCapabilities(Component component, TopologyTemplate topologyTemplate) { + convertTopologyTemplateCapabilities(component, topologyTemplate); if(componentInstancesCapabilitiesExist(component) || groupsCapabilitiesExist(component)){ topologyTemplate.setCalculatedCapabilities(new HashMap<>()); topologyTemplate.setCalculatedCapabilitiesProperties(new HashMap<>()); @@ -418,6 +423,65 @@ public class ModelConverter { } } + private static void convertTopologyTemplateCapabilities(Component component, ToscaElement toscaElement) { + Map> capabilities = component.getCapabilities(); + + Map toscaCapMap = new HashMap<>(); + Map toscaCapPropMap = new HashMap<>(); + + if (MapUtils.isNotEmpty(capabilities )) { + capabilities.forEach((s, caps) -> { + if (CollectionUtils.isNotEmpty(caps)) { + List capList = caps.stream().filter(capabilityDefinition -> capabilityDefinition.getOwnerId() + .equals(component.getUniqueId())).map(CapabilityDataDefinition::new).collect(Collectors.toList()); + + populateCapabilityMap(toscaCapMap, toscaCapPropMap, s, caps, capList); + } + } + ); + + toscaElement.setCapabilities(toscaCapMap); + toscaElement.setCapabilitiesProperties(toscaCapPropMap); + } + } + private static void populateCapabilityMap(Map toscaCapMap, + Map toscaCapPropMap, + String s, List caps, + List capList) { + ListCapabilityDataDefinition listCapabilityDataDefinition = new ListCapabilityDataDefinition(capList); + toscaCapMap.put(s, listCapabilityDataDefinition); + + for (CapabilityDefinition cap : caps) { + List capPrps = cap.getProperties(); + if (CollectionUtils.isNotEmpty(capPrps)) { + MapPropertiesDataDefinition dataToCreate = new MapPropertiesDataDefinition(); + for (ComponentInstanceProperty cip : capPrps) { + dataToCreate.put(cip.getName(), new PropertyDataDefinition(cip)); + } + toscaCapPropMap.put(s + CAP_PROP_DELIM + cap.getName(), dataToCreate); + } + } + } + + private static void convertTopologyTemplateRequirements(Component component, ToscaElement toscaElement) { + Map> requirements = component.getRequirements(); + + Map toscaReqMap = new HashMap<>(); + + if (MapUtils.isNotEmpty(requirements )) { + requirements.forEach((s, reqs)-> { + if (CollectionUtils.isNotEmpty(reqs)) { + List reqList = reqs.stream().filter(requirementDefinition -> requirementDefinition.getOwnerId() + .equals(component.getUniqueId())).map(RequirementDataDefinition::new).collect(Collectors.toList()); + + ListRequirementDataDefinition listRequirementDataDefinition = new ListRequirementDataDefinition(reqList); + toscaReqMap.put(s, listRequirementDataDefinition); + } + } + ); + toscaElement.setRequirements(toscaReqMap); + } + } private static void convertComponentInstancesCapabilities(Component component, TopologyTemplate topologyTemplate) { if (componentInstancesCapabilitiesExist(component)) { component.getComponentInstances() @@ -510,6 +574,7 @@ public class ModelConverter { private static void convertRequirements(Component component, TopologyTemplate topologyTemplate) { + convertTopologyTemplateRequirements(component, topologyTemplate); if (component.getRequirements() != null && component.getComponentInstances() != null) { topologyTemplate.setCalculatedRequirements(new HashMap<>()); for (ComponentInstance instance : component.getComponentInstances()) { @@ -759,27 +824,13 @@ public class ModelConverter { if (caps != null && !caps.isEmpty()) { List capList = caps.stream().map(CapabilityDataDefinition::new).collect(Collectors.toList()); - ListCapabilityDataDefinition listCapabilityDataDefinition = new ListCapabilityDataDefinition(capList); - toscaCapMap.put(s, listCapabilityDataDefinition); - - for (CapabilityDefinition cap : caps) { - List capPrps = cap.getProperties(); - if (capPrps != null && !capPrps.isEmpty()) { - - MapPropertiesDataDefinition dataToCreate = new MapPropertiesDataDefinition(); - for (ComponentInstanceProperty cip : capPrps) { - dataToCreate.put(cip.getName(), new PropertyDataDefinition(cip)); - } - - toscaCapPropMap.put(s + CAP_PROP_DELIM + cap.getName(), dataToCreate); - } - } + populateCapabilityMap(toscaCapMap, toscaCapPropMap, s, caps, capList); } } ); - toscaElement.setCapabilties(toscaCapMap); - toscaElement.setCapabiltiesProperties(toscaCapPropMap); + toscaElement.setCapabilities(toscaCapMap); + toscaElement.setCapabilitiesProperties(toscaCapPropMap); } } @@ -812,8 +863,8 @@ public class ModelConverter { } private static void convertCapabilities(NodeType toscaElement, Component component) { - Map toscaCapabilities = toscaElement.getCapabilties(); - Map toscaCapPropMap = toscaElement.getCapabiltiesProperties(); + Map toscaCapabilities = toscaElement.getCapabilities(); + Map toscaCapPropMap = toscaElement.getCapabilitiesProperties(); Map> compCap = new HashMap<>(); if (toscaCapabilities == null || toscaCapabilities.isEmpty()) @@ -1295,7 +1346,76 @@ public class ModelConverter { } } - private static void setCapabilitiesToComponentAndGroups(TopologyTemplate topologyTemplate, Component component) { + private static void setCapabilitiesToComponent(TopologyTemplate topologyTemplate, Component component) { + Map capabilities = topologyTemplate.getCapabilities(); + Map> componentCapabilities = component.getCapabilities(); + if(MapUtils.isNotEmpty(capabilities)) { + if(componentCapabilities == null) { + componentCapabilities = new HashMap<>(); + } + componentCapabilities.putAll(groupCapabilityByType(capabilities)); + component.setCapabilities(componentCapabilities); + } + + } + private static Map> groupCapabilityByType(Map capabilities) { + Map> groupedCapabilities = new HashMap<>(); + + Set typesSet = new HashSet<>(); + List allCapabilityDefinitions = new ArrayList<>(); + for (Entry capabilitiesEntry : capabilities.entrySet()) { + typesSet.addAll( capabilitiesEntry.getValue().getListToscaDataDefinition() + .stream().map(CapabilityDataDefinition::getType).collect(Collectors.toSet())); + + allCapabilityDefinitions.addAll(capabilitiesEntry.getValue().getListToscaDataDefinition() + .stream().map(CapabilityDefinition::new).collect(Collectors.toList())); + } + + for(String capType : typesSet) { + groupedCapabilities.put(capType, allCapabilityDefinitions.stream() + .filter(capabilityDefinition -> capabilityDefinition.getType() + .equals(capType)).collect(Collectors.toList())); + } + return groupedCapabilities; + } + + private static void setRequirementsToComponent(TopologyTemplate topologyTemplate, Component component) { + Map requirements = topologyTemplate.getRequirements(); + Map> componentRequirements = component.getRequirements(); + if(MapUtils.isNotEmpty(requirements)) { + if(componentRequirements == null) { + componentRequirements = new HashMap<>(); + } + componentRequirements.putAll(groupRequirementByType(requirements)); + component.setRequirements(componentRequirements); + } + } + + private static Map> groupRequirementByType(Map requirements) { + Map> groupedRequirement = new HashMap<>(); + + Set typesSet = new HashSet<>(); + List allRequirements = new ArrayList<>(); + for (Entry requirementsEntry : requirements.entrySet()) { + typesSet.addAll( requirementsEntry.getValue().getListToscaDataDefinition() + .stream().map(RequirementDataDefinition::getCapability).collect(Collectors.toSet())); + + allRequirements.addAll(requirementsEntry.getValue().getListToscaDataDefinition() + .stream().map(RequirementDefinition::new).collect(Collectors.toList())); + } + + for(String capType : typesSet) { + groupedRequirement.put(capType, allRequirements.stream().filter(requirementDefinition -> + requirementDefinition.getCapability().equals(capType)).collect(Collectors.toList())); + } + return groupedRequirement; + + } + + + private static void setCapabilitiesToComponentAndGroups(TopologyTemplate topologyTemplate, Component component) { Map calculatedCapProperties = topologyTemplate.getCalculatedCapabilitiesProperties(); diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/api/ICapabilityTypeOperation.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/api/ICapabilityTypeOperation.java index 7f8e07e2c3..4316f733a7 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/api/ICapabilityTypeOperation.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/api/ICapabilityTypeOperation.java @@ -21,8 +21,11 @@ package org.openecomp.sdc.be.model.operations.api; import fj.data.Either; +import org.openecomp.sdc.be.dao.titan.TitanOperationStatus; import org.openecomp.sdc.be.model.CapabilityTypeDefinition; +import java.util.Map; + public interface ICapabilityTypeOperation { /** @@ -43,4 +46,5 @@ public interface ICapabilityTypeOperation { public Either getCapabilityType(String uniqueId); public Either getCapabilityType(String uniqueId, boolean inTransaction); + Either, TitanOperationStatus> getAllCapabilityTypes(); } diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/CapabilityTypeOperation.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/CapabilityTypeOperation.java index 97f3e80e2a..3a4a2725e2 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/CapabilityTypeOperation.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/CapabilityTypeOperation.java @@ -42,6 +42,7 @@ import org.openecomp.sdc.common.log.wrappers.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.stream.Collectors; @@ -58,6 +59,10 @@ public class CapabilityTypeOperation extends AbstractOperation implements ICapab } private static final Logger log = Logger.getLogger(CapabilityTypeOperation.class.getName()); + private static final String DATA_TYPE_CANNOT_BE_FOUND_IN_GRAPH_STATUS_IS = "Data type {} cannot be found in graph." + + " status is {}"; + private static final String FAILED_TO_FETCH_PROPERTIES_OF_DATA_TYPE = "Failed to fetch properties of data type {}"; + /** * FOR TEST ONLY @@ -268,10 +273,15 @@ public class CapabilityTypeOperation extends AbstractOperation implements ICapab CapabilityTypeData ctData = capabilityTypesRes.left().value(); CapabilityTypeDefinition capabilityTypeDefinition = new CapabilityTypeDefinition(ctData.getCapabilityTypeDataDefinition()); - TitanOperationStatus propertiesStatus = fillProperties(uniqueId, capabilityTypeDefinition); - if (propertiesStatus != TitanOperationStatus.OK) { + Either, TitanOperationStatus> propertiesStatus = + OperationUtils.fillProperties(uniqueId, propertyOperation, NodeTypeEnum.CapabilityType); + if (propertiesStatus.isRight() && propertiesStatus.right().value() != TitanOperationStatus.OK) { log.error("Failed to fetch properties of capability type {}", uniqueId); - return Either.right(propertiesStatus); + return Either.right(propertiesStatus.right().value()); + } + + if (propertiesStatus.isLeft()) { + capabilityTypeDefinition.setProperties(propertiesStatus.left().value()); } Either, TitanOperationStatus> parentNode = titanGenericDao.getChild(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.CapabilityType), uniqueId, GraphEdgeLabels.DERIVED_FROM, @@ -295,24 +305,6 @@ public class CapabilityTypeOperation extends AbstractOperation implements ICapab return result; } - private TitanOperationStatus fillProperties(String uniqueId, CapabilityTypeDefinition capabilityTypeDefinition) { - - Either, TitanOperationStatus> findPropertiesOfNode = propertyOperation.findPropertiesOfNode(NodeTypeEnum.CapabilityType, uniqueId); - if (findPropertiesOfNode.isRight()) { - TitanOperationStatus titanOperationStatus = findPropertiesOfNode.right().value(); - log.debug("After looking for properties of vertex {}. status is {}", uniqueId, titanOperationStatus); - if (TitanOperationStatus.NOT_FOUND.equals(titanOperationStatus)) { - return TitanOperationStatus.OK; - } else { - return titanOperationStatus; - } - } else { - Map properties = findPropertiesOfNode.left().value(); - capabilityTypeDefinition.setProperties(properties); - return TitanOperationStatus.OK; - } - } - public Either isCapabilityTypeDerivedFrom(String childCandidateType, String parentCandidateType) { return derivedFromOperation.isTypeDerivedFrom(childCandidateType, parentCandidateType, null, NodeTypeEnum.CapabilityType, CapabilityTypeData.class, t -> t.getCapabilityTypeDataDefinition().getType()); } @@ -417,4 +409,107 @@ public class CapabilityTypeOperation extends AbstractOperation implements ICapab public Either getCapabilityType(String uniqueId) { return getCapabilityType(uniqueId, true); } + public Either, TitanOperationStatus> getAllCapabilityTypes() { + + Map capabilityTypes = new HashMap<>(); + Either, TitanOperationStatus> result = Either.left(capabilityTypes); + + Either, TitanOperationStatus> getAllCapabilityTypes = + titanGenericDao.getByCriteria(NodeTypeEnum.CapabilityType, null, CapabilityTypeData.class); + if (getAllCapabilityTypes.isRight()) { + TitanOperationStatus status = getAllCapabilityTypes.right().value(); + if (status != TitanOperationStatus.NOT_FOUND) { + return Either.right(status); + } else { + return result; + } + } + + List list = getAllCapabilityTypes.left().value(); + if (list != null) { + + log.trace("Number of data types to load is {}", list.size()); + //Set properties + for (CapabilityTypeData capabilityTypeData : list) { + + log.trace("Going to fetch data type {}. uid is {}", + capabilityTypeData.getCapabilityTypeDataDefinition().getType(), + capabilityTypeData.getUniqueId()); + Either capabilityTypesByUid = + getAndAddPropertiesANdDerivedFrom(capabilityTypeData.getUniqueId(), capabilityTypes); + if (capabilityTypesByUid.isRight()) { + TitanOperationStatus status = capabilityTypesByUid.right().value(); + if (status == TitanOperationStatus.NOT_FOUND) { + status = TitanOperationStatus.INVALID_ID; + } + return Either.right(status); + } + } + } + + return result; + } + + private void fillDerivedFrom(String uniqueId, CapabilityTypeDefinition capabilityType) { + log.debug("#fillDerivedFrom - fetching capability type {} derived node", capabilityType.getType()); + derivedFromOperation.getDerivedFromChild(uniqueId, NodeTypeEnum.CapabilityType, CapabilityTypeData.class) + .right() + .bind(this::handleDerivedFromNotExist) + .left() + .map(derivedFrom -> setDerivedFrom(capabilityType, derivedFrom)); + + } + + private Either handleDerivedFromNotExist(StorageOperationStatus err) { + if (err == StorageOperationStatus.NOT_FOUND) { + return Either.left(null); + } + return Either.right(err); + } + + private CapabilityTypeData setDerivedFrom(CapabilityTypeDefinition capabilityTypeDefinition, CapabilityTypeData derivedFrom) { + if (derivedFrom != null) { + capabilityTypeDefinition.setDerivedFrom(derivedFrom.getCapabilityTypeDataDefinition().getType()); + } + return derivedFrom; + } + + private Either getAndAddPropertiesANdDerivedFrom( + String uniqueId, Map capabilityTypeDefinitionMap) { + if (capabilityTypeDefinitionMap.containsKey(uniqueId)) { + return Either.left(capabilityTypeDefinitionMap.get(uniqueId)); + } + + Either capabilityTypesRes = + titanGenericDao.getNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.CapabilityType), uniqueId, + CapabilityTypeData.class); + + if (capabilityTypesRes.isRight()) { + TitanOperationStatus status = capabilityTypesRes.right().value(); + log.debug(DATA_TYPE_CANNOT_BE_FOUND_IN_GRAPH_STATUS_IS, uniqueId, status); + return Either.right(status); + } + + CapabilityTypeData ctData = capabilityTypesRes.left().value(); + CapabilityTypeDefinition capabilityTypeDefinition = + new CapabilityTypeDefinition(ctData.getCapabilityTypeDataDefinition()); + + Either, TitanOperationStatus> propertiesStatus = + OperationUtils.fillProperties(uniqueId, propertyOperation, NodeTypeEnum.CapabilityType); + + if (propertiesStatus.isRight() && propertiesStatus.right().value() != TitanOperationStatus.OK) { + log.error(FAILED_TO_FETCH_PROPERTIES_OF_DATA_TYPE, uniqueId); + return Either.right(propertiesStatus.right().value()); + } + + if (propertiesStatus.isLeft()) { + capabilityTypeDefinition.setProperties(propertiesStatus.left().value()); + } + + fillDerivedFrom(uniqueId, capabilityTypeDefinition); + + capabilityTypeDefinitionMap.put(capabilityTypeDefinition.getType(), capabilityTypeDefinition); + + return Either.left(capabilityTypeDefinition); + } } diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/OperationUtils.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/OperationUtils.java index dcaafe55ac..a06d342d26 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/OperationUtils.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/OperationUtils.java @@ -1,15 +1,23 @@ package org.openecomp.sdc.be.model.operations.impl; +import fj.data.Either; import org.openecomp.sdc.be.dao.jsongraph.TitanDao; import org.openecomp.sdc.be.dao.titan.TitanOperationStatus; +import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum; +import org.openecomp.sdc.be.model.PropertyDefinition; import org.openecomp.sdc.be.model.operations.StorageException; +import org.openecomp.sdc.common.log.wrappers.Logger; import org.springframework.stereotype.Component; +import java.util.Map; + @Component public class OperationUtils { private final TitanDao titanDao; + private static final Logger logger = Logger.getLogger(OperationUtils.class.getName()); + public OperationUtils(TitanDao titanDao) { this.titanDao = titanDao; } @@ -18,4 +26,23 @@ public class OperationUtils { titanDao.rollback(); throw new StorageException(status); } + + static Either, TitanOperationStatus> fillProperties(String uniqueId, + PropertyOperation propertyOperation, + NodeTypeEnum nodeTypeEnum) { + + Either, TitanOperationStatus> findPropertiesOfNode = + propertyOperation.findPropertiesOfNode(nodeTypeEnum, uniqueId); + if (findPropertiesOfNode.isRight()) { + TitanOperationStatus titanOperationStatus = findPropertiesOfNode.right().value(); + logger.debug("After looking for properties of vertex {}. status is {}", uniqueId, titanOperationStatus); + if (TitanOperationStatus.NOT_FOUND.equals(titanOperationStatus)) { + return Either.right(TitanOperationStatus.OK); + } else { + return Either.right(titanOperationStatus); + } + } else { + return Either.left(findPropertiesOfNode.left().value()); + } + } } diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/RelationshipTypeOperation.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/RelationshipTypeOperation.java new file mode 100644 index 0000000000..13ad7a798c --- /dev/null +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/RelationshipTypeOperation.java @@ -0,0 +1,513 @@ +package org.openecomp.sdc.be.model.operations.impl; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import fj.data.Either; +import org.apache.commons.collections.MapUtils; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.openecomp.sdc.be.dao.graph.datatype.GraphEdge; +import org.openecomp.sdc.be.dao.graph.datatype.GraphRelation; +import org.openecomp.sdc.be.dao.neo4j.GraphEdgeLabels; +import org.openecomp.sdc.be.dao.titan.TitanOperationStatus; +import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum; +import org.openecomp.sdc.be.model.PropertyDefinition; +import org.openecomp.sdc.be.model.RelationshipTypeDefinition; +import org.openecomp.sdc.be.model.operations.api.DerivedFromOperation; +import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus; +import org.openecomp.sdc.be.resources.data.PropertyData; +import org.openecomp.sdc.be.resources.data.RelationshipTypeData; +import org.openecomp.sdc.common.log.wrappers.Logger; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component("relationship-type-operation") +public class RelationshipTypeOperation extends AbstractOperation { + + @Autowired + private PropertyOperation propertyOperation; + + @Autowired + private DerivedFromOperation derivedFromOperation; + + private static final Logger logger = Logger.getLogger(RelationshipTypeOperation.class.getName()); + private static final String RELATIONSHIP_TYPE_CANNOT_BE_FOUND_IN_GRAPH_STATUS_IS = "Relationship type {} cannot be " + + "found in " + + "graph status is {}"; + private static final String FAILED_TO_FETCH_PROPERTIES_OF_RELATIONSHIP_TYPE = "Failed to fetch properties of " + + "relationship type {}"; + + public Either getRelationshipTypeByName(String name) { + String uid = UniqueIdBuilder.buildRelationshipTypeUid(name); + Either result = getRelationshipTypeByUid(uid); + if (result.isRight()) { + TitanOperationStatus status = result.right().value(); + if (status != TitanOperationStatus.NOT_FOUND) { + logger.error("Failed to get information on relationship type {} status is {}", name, status); + } + return Either.right(status); + } + return Either.left(result.left().value()); + } + + public Either getRelationshipTypeByUid(String uniqueId) { + + Either result; + + Either relationshipTypesRes = + titanGenericDao.getNode(UniqueIdBuilder.getKeyByNodeType( + NodeTypeEnum.RelationshipType), uniqueId, RelationshipTypeData.class); + + if (relationshipTypesRes.isRight()) { + TitanOperationStatus status = relationshipTypesRes.right().value(); + logger.debug("Relationship type {} cannot be found in graph. status is {}", uniqueId, status); + return Either.right(status); + } + + RelationshipTypeData relationshipTypeData = relationshipTypesRes.left().value(); + RelationshipTypeDefinition relationshipTypeDefinition = + new RelationshipTypeDefinition(relationshipTypeData.getRelationshipTypeDataDefinition()); + + Either, TitanOperationStatus> propertiesStatus = + OperationUtils.fillProperties(uniqueId, propertyOperation, NodeTypeEnum.RelationshipType); + if (propertiesStatus.isRight() && propertiesStatus.right().value() != TitanOperationStatus.OK) { + logger.error("Failed to fetch properties of relationship type {}", uniqueId); + return Either.right(propertiesStatus.right().value()); + } + + if (propertiesStatus.isLeft()) { + relationshipTypeDefinition.setProperties(propertiesStatus.left().value()); + } + + Either, TitanOperationStatus> parentNode = titanGenericDao + .getChild(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.RelationshipType), uniqueId, + GraphEdgeLabels.DERIVED_FROM, + NodeTypeEnum.RelationshipType, RelationshipTypeData.class); + logger.debug("After retrieving DERIVED_FROM node of {}. status is {}", uniqueId, parentNode); + if (parentNode.isRight()) { + TitanOperationStatus titanOperationStatus = parentNode.right().value(); + if (titanOperationStatus != TitanOperationStatus.NOT_FOUND) { + logger.error("Failed to find the parent relationship of relationship type {}. status is {}", uniqueId, + titanOperationStatus); + result = Either.right(titanOperationStatus); + return result; + } + } else { + // derived from node was found + ImmutablePair immutablePair = parentNode.left().value(); + RelationshipTypeData parentCT = immutablePair.getKey(); + relationshipTypeDefinition.setDerivedFrom(parentCT.getRelationshipTypeDataDefinition().getType()); + } + result = Either.left(relationshipTypeDefinition); + + return result; + } + + private Either validateUpdateProperties( + RelationshipTypeDefinition relationshipTypeDefinition) { + TitanOperationStatus error = null; + if (MapUtils.isNotEmpty(relationshipTypeDefinition.getProperties()) + && relationshipTypeDefinition.getDerivedFrom() != null) { + Either, TitanOperationStatus> allPropertiesRes = + getAllRelationshipTypePropertiesFromAllDerivedFrom(relationshipTypeDefinition.getDerivedFrom()); + if (allPropertiesRes.isRight() && !TitanOperationStatus.NOT_FOUND.equals(allPropertiesRes.right().value())) { + error = allPropertiesRes.right().value(); + logger.debug("Couldn't fetch derived from property nodes for relationship type {}, error: {}", + relationshipTypeDefinition.getType(), error); + } + error = getTitanOperationStatus(relationshipTypeDefinition, error, allPropertiesRes); + } + if (error == null) { + return Either.left(relationshipTypeDefinition); + } + return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(error)); + } + + private TitanOperationStatus getTitanOperationStatus(RelationshipTypeDefinition relationshipTypeDefinition, + TitanOperationStatus error, + Either, TitanOperationStatus> allPropertiesRes) { + if (error == null && !allPropertiesRes.left().value().isEmpty()) { + Map derivedFromProperties = allPropertiesRes.left().value(); + relationshipTypeDefinition.getProperties().entrySet().stream() + .filter(e -> derivedFromProperties.containsKey(e.getKey()) && e.getValue().getType() == null) + .forEach(e -> e.getValue().setType(derivedFromProperties.get(e.getKey()).getType())); + + List + properties = new ArrayList<>(relationshipTypeDefinition.getProperties().values()); + Either, TitanOperationStatus> validatePropertiesRes = + propertyOperation.validatePropertiesUniqueness(allPropertiesRes.left().value(), properties); + if (validatePropertiesRes.isRight()) { + error = validatePropertiesRes.right().value(); + } + } + return error; + } + + private Either, TitanOperationStatus> getAllRelationshipTypePropertiesFromAllDerivedFrom( + String firstParentType) { + return propertyOperation.getAllTypePropertiesFromAllDerivedFrom(firstParentType, NodeTypeEnum.RelationshipType, + RelationshipTypeData.class); + } + + public Either addRelationshipType( + RelationshipTypeDefinition relationshipTypeDefinition, + boolean inTransaction) { + + Either result = null; + + try { + Either validationRes = + validateUpdateProperties(relationshipTypeDefinition); + if (validationRes.isRight()) { + logger.error( + "#addRelationshipType - One or all properties of relationship type {} not valid. status is {}" + , relationshipTypeDefinition, validationRes.right().value()); + return validationRes; + } + + Either eitherStatus = + addRelationshipTypeToGraph(relationshipTypeDefinition); + + result = eitherStatus.left() + .map(RelationshipTypeData::getUniqueId) + .left() + .bind(uniqueId -> getRelationshipType(uniqueId, inTransaction)); + + if (result.isLeft()) { + logger.debug("#addRelationshipType - The returned RelationshipTypeDefinition is {}", + result.left().value()); + } + + return result; + } finally { + if (!inTransaction) { + if (result == null || result.isRight()) { + logger.error("#addRelationshipType - Going to execute rollback on graph."); + titanGenericDao.rollback(); + } else { + logger.debug("#addRelationshipType - Going to execute commit on graph."); + titanGenericDao.commit(); + } + } + } + } + + public Either getRelationshipType(String uniqueId, + boolean inTransaction) { + + Either result; + try { + + Either ctResult = this.getRelationshipTypeByUid(uniqueId); + + if (ctResult.isRight()) { + TitanOperationStatus status = ctResult.right().value(); + if (status != TitanOperationStatus.NOT_FOUND) { + logger.error("Failed to retrieve information on relationship type {}. status is {}", uniqueId, + status); + } + result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(ctResult.right().value())); + return result; + } + + result = Either.left(ctResult.left().value()); + + return result; + } finally { + if (!inTransaction) { + logger.debug("Going to execute commit on graph."); + titanGenericDao.commit(); + } + } + } + + private Either addRelationshipTypeToGraph( + RelationshipTypeDefinition relationshipTypeDefinition) { + + logger.debug("Got relationship type {}", relationshipTypeDefinition); + + String ctUniqueId = UniqueIdBuilder.buildRelationshipTypeUid(relationshipTypeDefinition.getType()); + RelationshipTypeData relationshipTypeData = buildRelationshipTypeData(relationshipTypeDefinition, ctUniqueId); + + logger.debug("Before adding relationship type to graph. relationshipTypeData = {}", relationshipTypeData); + Either createCTResult = + titanGenericDao.createNode(relationshipTypeData, RelationshipTypeData.class); + logger.debug("After adding relationship type to graph. status is = {}", createCTResult); + + if (createCTResult.isRight()) { + TitanOperationStatus operationStatus = createCTResult.right().value(); + logger.error("Failed to relationship type {} to graph. status is {}", relationshipTypeDefinition.getType(), + operationStatus); + return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(operationStatus)); + } + + RelationshipTypeData resultCTD = createCTResult.left().value(); + Map propertiesMap = relationshipTypeDefinition.getProperties(); + Either, TitanOperationStatus> addPropertiesToRelationshipType = propertyOperation + .addPropertiesToElementType(resultCTD.getUniqueId(), NodeTypeEnum.RelationshipType, propertiesMap); + if (addPropertiesToRelationshipType.isRight()) { + logger.error("Failed add properties {} to relationship {}", propertiesMap, + relationshipTypeDefinition.getType()); + return Either.right(DaoStatusConverter + .convertTitanStatusToStorageStatus(addPropertiesToRelationshipType.right().value())); + } + + return addDerivedFromRelation(relationshipTypeDefinition, ctUniqueId) + .left() + .map(updatedDerivedFrom -> createCTResult.left().value()); + + + } + + private RelationshipTypeData buildRelationshipTypeData(RelationshipTypeDefinition relationshipTypeDefinition, + String ctUniqueId) { + + RelationshipTypeData relationshipTypeData = new RelationshipTypeData(relationshipTypeDefinition); + + relationshipTypeData.getRelationshipTypeDataDefinition().setUniqueId(ctUniqueId); + Long creationDate = relationshipTypeData.getRelationshipTypeDataDefinition().getCreationTime(); + if (creationDate == null) { + creationDate = System.currentTimeMillis(); + } + relationshipTypeData.getRelationshipTypeDataDefinition().setCreationTime(creationDate); + relationshipTypeData.getRelationshipTypeDataDefinition().setModificationTime(creationDate); + return relationshipTypeData; + } + + private Either addDerivedFromRelation( + RelationshipTypeDefinition relationshipTypeDefinition, + String relationshipTypeUniqueId) { + String derivedFrom = relationshipTypeDefinition.getDerivedFrom(); + if (derivedFrom == null) { + return Either.left(null); + } + logger.debug( + "#addDerivedFromRelation - adding derived from relation between relationship type {} to its parent " + + "{}", relationshipTypeDefinition.getType(), derivedFrom); + return getRelationshipTypeByType(derivedFrom) + .right() + .map(DaoStatusConverter::convertTitanStatusToStorageStatus) + .left() + .bind(derivedFromRelationship -> derivedFromOperation.addDerivedFromRelation(relationshipTypeUniqueId, + derivedFromRelationship.getUniqueId(), NodeTypeEnum.RelationshipType)); + } + + private Either getRelationshipTypeByType( + String relationshipType) { + // Optimization: In case of Relationship Type its unique ID is the same as type + return getRelationshipTypeByUid(relationshipType); + } + + public Either updateRelationshipType( + RelationshipTypeDefinition newRelationshipTypeDefinition, + RelationshipTypeDefinition oldRelationshipTypeDefinition, boolean inTransaction) { + logger.debug("updating relationship type {}", newRelationshipTypeDefinition.getType()); + Either updateRelationshipEither = null; + + try { + updateRelationshipEither = + updateRelationshipTypeOnGraph(newRelationshipTypeDefinition, oldRelationshipTypeDefinition); + } finally { + if (!inTransaction) { + if (updateRelationshipEither == null || updateRelationshipEither.isRight()) { + titanGenericDao.rollback(); + } else { + titanGenericDao.commit(); + } + } + } + return updateRelationshipEither; + } + + private Either updateRelationshipTypeOnGraph( + RelationshipTypeDefinition newRelationshipTypeDefinition, + RelationshipTypeDefinition oldRelationshipTypeDefinition) { + updateRelationshipTypeData(newRelationshipTypeDefinition, oldRelationshipTypeDefinition); + return titanGenericDao + .updateNode(new RelationshipTypeData(newRelationshipTypeDefinition), RelationshipTypeData.class) + .right() + .map(DaoStatusConverter::convertTitanStatusToStorageStatus) + .left() + .bind(updatedNode -> updateRelationshipTypeProperties(newRelationshipTypeDefinition.getUniqueId(), + newRelationshipTypeDefinition.getProperties())) + .left() + .bind(updatedProperties -> updateRelationshipTypeDerivedFrom(newRelationshipTypeDefinition, + oldRelationshipTypeDefinition.getDerivedFrom())) + .left() + .map(updatedDerivedFrom -> newRelationshipTypeDefinition); + } + + private Either, StorageOperationStatus> updateRelationshipTypeProperties( + String relationshipTypeId, Map properties) { + logger.debug( + "#updateRelationshipTypeProperties - updating relationship type properties for relationship type with " + + "id {}", relationshipTypeId); + return propertyOperation.deletePropertiesAssociatedToNode(NodeTypeEnum.RelationshipType, relationshipTypeId) + .left() + .bind(deleteProps -> addPropertiesToRelationshipType(relationshipTypeId, properties)); + } + + private Either updateRelationshipTypeDerivedFrom( + RelationshipTypeDefinition newRelationshipTypeDefinition, String currDerivedFromRelationshipType) { + String relationshipTypeId = newRelationshipTypeDefinition.getUniqueId(); + logger.debug( + "#updateRelationshipTypeDerivedFrom - updating relationship derived from relation for relationship " + + "type with id {}. old derived type {}. new derived type {}", relationshipTypeId, + currDerivedFromRelationshipType, newRelationshipTypeDefinition.getDerivedFrom()); + StorageOperationStatus deleteDerivedRelationStatus = + deleteDerivedFromRelationshipType(relationshipTypeId, currDerivedFromRelationshipType); + if (deleteDerivedRelationStatus != StorageOperationStatus.OK) { + return Either.right(deleteDerivedRelationStatus); + } + return addDerivedFromRelation(newRelationshipTypeDefinition, relationshipTypeId); + } + + private void updateRelationshipTypeData(RelationshipTypeDefinition newRelationshipTypeDefinition, + RelationshipTypeDefinition oldRelationshipTypeDefinition) { + newRelationshipTypeDefinition.setUniqueId(oldRelationshipTypeDefinition.getUniqueId()); + newRelationshipTypeDefinition.setCreationTime(oldRelationshipTypeDefinition.getCreationTime()); + newRelationshipTypeDefinition.setModificationTime(System.currentTimeMillis()); + } + + private Either, StorageOperationStatus> addPropertiesToRelationshipType( + String relationshipTypeId, Map properties) { + logger.debug( + "#addPropertiesToRelationshipType - adding relationship type properties for relationship type with " + + "id {}", relationshipTypeId); + return propertyOperation + .addPropertiesToElementType(relationshipTypeId, NodeTypeEnum.RelationshipType, properties) + .right() + .map(DaoStatusConverter::convertTitanStatusToStorageStatus); + } + + private StorageOperationStatus deleteDerivedFromRelationshipType(String relationshipTypeId, + String derivedFromType) { + if (derivedFromType == null) { + return StorageOperationStatus.OK; + } + logger.debug("#deleteDerivedFromRelationshipType - deleting derivedFrom relation for relationship type with id " + + "{} and its derived type {}", relationshipTypeId, derivedFromType); + return getRelationshipTypeByType(derivedFromType) + .either(derivedFromNode -> derivedFromOperation + .removeDerivedFromRelation(relationshipTypeId, derivedFromNode.getUniqueId(), + NodeTypeEnum.RelationshipType), + DaoStatusConverter::convertTitanStatusToStorageStatus); + } + + public Either, TitanOperationStatus> getAllRelationshipTypes() { + + Map relationshipTypeDefinitionMap = new HashMap<>(); + Either, TitanOperationStatus> result = Either.left(relationshipTypeDefinitionMap); + + Either, TitanOperationStatus> getAllRelationshipTypes = + titanGenericDao.getByCriteria(NodeTypeEnum.RelationshipType, null, RelationshipTypeData.class); + if (getAllRelationshipTypes.isRight()) { + TitanOperationStatus status = getAllRelationshipTypes.right().value(); + if (status != TitanOperationStatus.NOT_FOUND) { + return Either.right(status); + } else { + return result; + } + } + + List list = getAllRelationshipTypes.left().value(); + if (list != null) { + + logger.trace("Number of relationship types to load is {}", list.size()); + //Set properties + Either, TitanOperationStatus> status = + getMapTitanOperationStatusEither(relationshipTypeDefinitionMap, list); + if (status != null) { + return status; + } + } + + return result; + } + + private Either, TitanOperationStatus> getMapTitanOperationStatusEither( + Map relationshipTypeDefinitionMap, + List list) { + for (RelationshipTypeData relationshipTypeData : list) { + + logger.trace("Going to fetch relationship type {}. uid is {}", + relationshipTypeData.getRelationshipTypeDataDefinition().getType(), + relationshipTypeData.getUniqueId()); + Either relationshipTypesByUid = + getAndAddPropertiesANdDerivedFrom(relationshipTypeData.getUniqueId(), relationshipTypeDefinitionMap); + if (relationshipTypesByUid.isRight()) { + TitanOperationStatus status = relationshipTypesByUid.right().value(); + if (status == TitanOperationStatus.NOT_FOUND) { + status = TitanOperationStatus.INVALID_ID; + } + return Either.right(status); + } + } + return null; + } + + private Either getAndAddPropertiesANdDerivedFrom( + String uniqueId, Map relationshipTypeDefinitionMap) { + if (relationshipTypeDefinitionMap.containsKey(uniqueId)) { + return Either.left(relationshipTypeDefinitionMap.get(uniqueId)); + } + + Either relationshipTypesRes = + titanGenericDao.getNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.RelationshipType), uniqueId, + RelationshipTypeData.class); + + if (relationshipTypesRes.isRight()) { + TitanOperationStatus status = relationshipTypesRes.right().value(); + logger.debug(RELATIONSHIP_TYPE_CANNOT_BE_FOUND_IN_GRAPH_STATUS_IS, uniqueId, status); + return Either.right(status); + } + + RelationshipTypeData ctData = relationshipTypesRes.left().value(); + RelationshipTypeDefinition relationshipTypeDefinition = + new RelationshipTypeDefinition(ctData.getRelationshipTypeDataDefinition()); + + Either, TitanOperationStatus> propertiesStatus = + OperationUtils.fillProperties(uniqueId, propertyOperation, NodeTypeEnum.RelationshipType); + if (propertiesStatus.isRight() && propertiesStatus.right().value() != TitanOperationStatus.OK) { + logger.error(FAILED_TO_FETCH_PROPERTIES_OF_RELATIONSHIP_TYPE, uniqueId); + return Either.right(propertiesStatus.right().value()); + } + + if (propertiesStatus.isLeft()) { + relationshipTypeDefinition.setProperties(propertiesStatus.left().value()); + } + + fillDerivedFrom(uniqueId, relationshipTypeDefinition); + + relationshipTypeDefinitionMap.put(relationshipTypeDefinition.getType(), relationshipTypeDefinition); + + return Either.left(relationshipTypeDefinition); + } + + private void fillDerivedFrom(String uniqueId, + RelationshipTypeDefinition relationshipType) { + logger.debug("#fillDerivedFrom - fetching relationship type {} derived node", relationshipType.getType()); + derivedFromOperation.getDerivedFromChild(uniqueId, NodeTypeEnum.RelationshipType, RelationshipTypeData.class) + .right() + .bind(this::handleDerivedFromNotExist) + .left() + .map(derivedFrom -> setDerivedFrom(relationshipType, derivedFrom)); + + } + + private Either handleDerivedFromNotExist(StorageOperationStatus err) { + if (err == StorageOperationStatus.NOT_FOUND) { + return Either.left(null); + } + return Either.right(err); + } + + private RelationshipTypeData setDerivedFrom(RelationshipTypeDefinition relationshipTypeDefinition, RelationshipTypeData derivedFrom) { + if (derivedFrom != null) { + relationshipTypeDefinition.setDerivedFrom(derivedFrom.getRelationshipTypeDataDefinition().getType()); + } + return derivedFrom; + } +} 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 058e9de163..aa5ca81a31 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 @@ -99,6 +99,10 @@ public class UniqueIdBuilder { return type; } + static String buildRelationshipTypeUid(String type) { + return type; + } + public static String buildAttributeUid(String resourceId, String attName) { return buildTypeUid(NodeTypeEnum.Attribute.getName(), resourceId, attName); } diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/utils/TypeCompareUtils.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/utils/TypeCompareUtils.java index 298cae0da5..e0e02ae121 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/utils/TypeCompareUtils.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/utils/TypeCompareUtils.java @@ -71,6 +71,22 @@ public class TypeCompareUtils { SetUtils.isEqualSet(ct1.getValidSourceTypes(), ct2.getValidSourceTypes()) && propertiesEquals(ct1.getProperties(), ct2.getProperties()); } + + public static boolean isRelationshipTypesEquals(RelationshipTypeDefinition rs1, RelationshipTypeDefinition rs2) { + if (rs1 == rs2) { + return true; + } + + if (rs1 == null || rs2 == null) { + return false; + } + + return Objects.equals(rs1.getType(), rs2.getType()) && + Objects.equals(rs1.getDerivedFrom(), rs2.getDerivedFrom()) && + Objects.equals(rs1.getDescription(), rs2.getDescription()) && + SetUtils.isEqualSet(rs1.getValidSourceTypes(), rs2.getValidSourceTypes()) && + propertiesEquals(rs1.getProperties(), rs2.getProperties()); + } private static boolean propertiesEquals(Map props1, Map props2) { if (props1 == props2) { diff --git a/catalog-model/src/test/java/org/openecomp/sdc/be/model/jsontitan/datamodel/NodeTypeTest.java b/catalog-model/src/test/java/org/openecomp/sdc/be/model/jsontitan/datamodel/NodeTypeTest.java index aae9d6f2a0..493cb74a25 100644 --- a/catalog-model/src/test/java/org/openecomp/sdc/be/model/jsontitan/datamodel/NodeTypeTest.java +++ b/catalog-model/src/test/java/org/openecomp/sdc/be/model/jsontitan/datamodel/NodeTypeTest.java @@ -91,7 +91,7 @@ public class NodeTypeTest { // default test testSubject = createTestSubject(); - result = testSubject.getCapabilties(); + result = testSubject.getCapabilities(); } @@ -102,7 +102,7 @@ public class NodeTypeTest { // default test testSubject = createTestSubject(); - testSubject.setCapabilties(capabilties); + testSubject.setCapabilities(capabilties); } @@ -135,7 +135,7 @@ public class NodeTypeTest { // default test testSubject = createTestSubject(); - result = testSubject.getCapabiltiesProperties(); + result = testSubject.getCapabilitiesProperties(); } @@ -146,7 +146,7 @@ public class NodeTypeTest { // default test testSubject = createTestSubject(); - testSubject.setCapabiltiesProperties(capabiltiesProperties); + testSubject.setCapabilitiesProperties(capabiltiesProperties); } diff --git a/catalog-model/src/test/java/org/openecomp/sdc/be/model/operations/impl/RelationshipTypeOperationTest.java b/catalog-model/src/test/java/org/openecomp/sdc/be/model/operations/impl/RelationshipTypeOperationTest.java new file mode 100644 index 0000000000..6f8c7ea629 --- /dev/null +++ b/catalog-model/src/test/java/org/openecomp/sdc/be/model/operations/impl/RelationshipTypeOperationTest.java @@ -0,0 +1,474 @@ +/*- + * ============LICENSE_START======================================================= + * SDC + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdc.be.model.operations.impl; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import fj.data.Either; +import org.apache.commons.collections4.MapUtils; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; +import org.mockito.Spy; +import org.openecomp.sdc.be.dao.graph.datatype.GraphRelation; +import org.openecomp.sdc.be.dao.titan.TitanGenericDao; +import org.openecomp.sdc.be.dao.titan.TitanOperationStatus; +import org.openecomp.sdc.be.datatypes.elements.RelationshipInstDataDefinition; +import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum; +import org.openecomp.sdc.be.model.ModelTestBase; +import org.openecomp.sdc.be.model.PropertyConstraint; +import org.openecomp.sdc.be.model.PropertyDefinition; +import org.openecomp.sdc.be.model.RelationshipTypeDefinition; +import org.openecomp.sdc.be.model.operations.api.DerivedFromOperation; +import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus; +import org.openecomp.sdc.be.model.tosca.ToscaType; +import org.openecomp.sdc.be.model.tosca.constraints.GreaterThanConstraint; +import org.openecomp.sdc.be.model.tosca.constraints.InRangeConstraint; +import org.openecomp.sdc.be.model.tosca.constraints.LessOrEqualConstraint; +import org.openecomp.sdc.be.resources.data.RelationshipTypeData; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration("classpath:application-context-test.xml") +public class RelationshipTypeOperationTest extends ModelTestBase { + + private static final String PROP = "prop"; + + @Mock + TitanGenericDao titanGenericDao; + + @Mock + PropertyOperation propertyOperation; + + @Mock + DerivedFromOperation derivedFromOperation; + + @InjectMocks + @Spy + private RelationshipTypeOperation relationshipTypeOperation; + + private RelationshipTypeDefinition relationshipTypeDefinition = new RelationshipTypeDefinition(); + + { + relationshipTypeDefinition.setDescription("desc1"); + relationshipTypeDefinition.setType("tosca.relationships.Container1"); + relationshipTypeDefinition.setDerivedFrom("tosca.relationships.Root"); + relationshipTypeDefinition.setProperties(createPropertyData("prop1")); + relationshipTypeDefinition.setUniqueId("tosca.relationships.Container1"); + } + + @BeforeClass + public static void setupBeforeClass() { + ModelTestBase.init(); + } + + @Before + public void setUp() throws Exception { + MockitoAnnotations.initMocks(this); + + Mockito.doReturn(TitanOperationStatus.OK).when(titanGenericDao).commit(); + Mockito.doReturn(TitanOperationStatus.OK).when(titanGenericDao).rollback(); + } + + @Test + public void getRelationshipTypeByNameNotCreated() { + Mockito.doReturn(Either.right(TitanOperationStatus.NOT_CREATED)) + .when(relationshipTypeOperation).getRelationshipTypeByUid(Mockito.anyString()); + + Either either = + relationshipTypeOperation.getRelationshipTypeByName("name"); + assertTrue(either.isRight()); + } + + @Test + public void testDummy() { + assertNotNull(relationshipTypeOperation); + } + + @Test + public void testAddRelationshipTypeValidationFailStatusNullInTransactionFalse() { + Mockito.doReturn(Either.right(TitanOperationStatus.NOT_CONNECTED)) + .when(propertyOperation) + .getAllTypePropertiesFromAllDerivedFrom(Mockito.anyString(), Mockito.any(), Mockito.any()); + + + Either addRelationshipType = + relationshipTypeOperation.addRelationshipType(relationshipTypeDefinition, false); + + assertTrue(addRelationshipType.isRight()); + } + + @Test + public void testAddRelationshipTypeValidationFailStatusPropertiesReturnedInTransactionFalse() { + Mockito.doReturn(Either.left(Collections.singletonMap("prop1", new PropertyDefinition()))).when(propertyOperation) + .getAllTypePropertiesFromAllDerivedFrom(Mockito.anyString(), Mockito.any(), Mockito.any()); + Mockito.doReturn(Either.right(TitanOperationStatus.NOT_FOUND)).when(propertyOperation) + .validatePropertiesUniqueness(Mockito.any(), Mockito.any()); + + Either addRelationshipType = + relationshipTypeOperation.addRelationshipType(relationshipTypeDefinition, false); + + assertTrue(addRelationshipType.isRight()); + } + + @Test + public void testGetAllRelationshipTypesNotFound() { + Mockito.doReturn(Either.right(TitanOperationStatus.NOT_FOUND)).when(titanGenericDao).getByCriteria(NodeTypeEnum.RelationshipType, null, + RelationshipTypeData.class); + Either, TitanOperationStatus> either = relationshipTypeOperation.getAllRelationshipTypes(); + + assertTrue(either.isLeft() && MapUtils.isEmpty(either.left().value())); + } + + @Test + public void testGetAllRelationshipTypesNotConnnected() { + Mockito.doReturn(Either.right(TitanOperationStatus.NOT_CONNECTED)).when(titanGenericDao).getByCriteria(NodeTypeEnum.RelationshipType, null, + RelationshipTypeData.class); + Either, TitanOperationStatus> either = relationshipTypeOperation.getAllRelationshipTypes(); + + assertTrue(either.isRight() && TitanOperationStatus.NOT_CONNECTED == either.right().value()); + } + + @Test + public void testGetAllRelationshipTypesSuccess() { + List relationshipTypeDataList = new ArrayList<>(); + + RelationshipTypeData relationshipTypeData1 = new RelationshipTypeData(); + RelationshipInstDataDefinition relationshipInstDataDefinition1 = new RelationshipInstDataDefinition(); + relationshipInstDataDefinition1.setUniqueId("tosca.relationships.Root1"); + relationshipInstDataDefinition1.setType("tosca.relationships.Root1"); + relationshipTypeData1.setRelationshipTypeDataDefinition(relationshipInstDataDefinition1); + + relationshipTypeDataList.add(relationshipTypeData1); + + Mockito.doReturn(Either.left(relationshipTypeDataList)) + .when(titanGenericDao).getByCriteria(NodeTypeEnum.RelationshipType, null, + RelationshipTypeData.class); + + Mockito.doReturn(Either.left(relationshipTypeData1)).when(titanGenericDao) + .getNode(Mockito.anyString(), Mockito.anyString(), Mockito.eq(RelationshipTypeData.class)); + + Mockito.doReturn(Either.left(createPropertyData("prop1"))).when(propertyOperation) + .findPropertiesOfNode(NodeTypeEnum.RelationshipType, "tosca.relationships.Root1"); + + RelationshipInstDataDefinition derivedFromRelationshipTypeDefinition = new RelationshipInstDataDefinition(); + derivedFromRelationshipTypeDefinition.setUniqueId("tosca.relationships.Root1"); + derivedFromRelationshipTypeDefinition.setType("tosca.relationships.Parent"); + + Mockito.doReturn(Either.left(new RelationshipTypeData(derivedFromRelationshipTypeDefinition))) + .when(derivedFromOperation) + .getDerivedFromChild("tosca.relationships.Root1", NodeTypeEnum.RelationshipType, RelationshipTypeData.class); + + Either, TitanOperationStatus> either = + relationshipTypeOperation.getAllRelationshipTypes(); + + assertTrue(either.isLeft()); + RelationshipTypeDefinition relationshipTypeDefinition = either.left().value().get("tosca.relationships.Root1"); + assertEquals("tosca.relationships.Parent", relationshipTypeDefinition.getDerivedFrom()); + } + + public RelationshipTypeDefinition createRelationship(String relationshipTypeName) { + + RelationshipTypeDefinition relationshipTypeDefinition = new RelationshipTypeDefinition(); + relationshipTypeDefinition.setDescription("desc1"); + relationshipTypeDefinition.setType(relationshipTypeName); + + Map properties = new HashMap<>(); + + String propName1 = "disk_size"; + String propName2 = "num_cpus"; + + PropertyDefinition property1 = buildProperty1(); + + properties.put(propName1, property1); + + PropertyDefinition property2 = buildProperty2(); + + properties.put(propName2, property2); + + relationshipTypeDefinition.setProperties(properties); + + Either addRelationshipType1 = + relationshipTypeOperation.addRelationshipType(relationshipTypeDefinition, true); + + RelationshipTypeDefinition relationshipTypeDefinitionCreated = addRelationshipType1.left().value(); + Either relationshipType = + relationshipTypeOperation.getRelationshipType(relationshipTypeDefinitionCreated.getUniqueId(), true); + assertTrue("check relationship type fetched", relationshipType.isLeft()); + RelationshipTypeDefinition fetchedCTD = relationshipType.left().value(); + + Map fetchedProps = fetchedCTD.getProperties(); + + compareProperties(fetchedProps, properties); + + return fetchedCTD; + + } + + private void compareProperties(Map first, Map second) { + + assertTrue("check properties are full or empty", + ((first == null && second == null) || (first != null && second != null))); + if (first != null) { + assertEquals("check properties size", first.size(), second.size()); + + for (Entry entry : first.entrySet()) { + + String propName = entry.getKey(); + PropertyDefinition secondPD = second.get(propName); + assertNotNull("Cannot find property " + propName + " in " + second, secondPD); + + PropertyDefinition firstPD = entry.getValue(); + + comparePropertyDefinition(firstPD, secondPD); + } + + } + + } + + private void comparePropertyDefinition(PropertyDefinition first, PropertyDefinition second) { + + assertTrue("check objects are full or empty", + ((first == null && second == null) || (first != null && second != null))); + if (first != null) { + assertTrue("check property description", compareValue(first.getDescription(), second.getDescription())); + assertTrue("check property default value", compareValue((String) first.getDefaultValue(), + (String) second.getDefaultValue())); + assertTrue("check property type", compareValue(first.getType(), second.getType())); + compareList(first.getConstraints(), second.getConstraints()); + } + + } + + private void compareList(List first, List second) { + + assertTrue("check lists are full or empty", + ((first == null && second == null) || (first != null && second != null))); + if (first != null) { + assertEquals("check list size", first.size(), second.size()); + } + } + + private PropertyDefinition buildProperty2() { + PropertyDefinition property2 = new PropertyDefinition(); + property2.setDefaultValue("2"); + property2.setDescription("Number of (actual or virtual) CPUs associated with the Compute node."); + property2.setType(ToscaType.INTEGER.name().toLowerCase()); + List constraints3 = new ArrayList<>(); + List range = new ArrayList<>(); + range.add("4"); + range.add("1"); + InRangeConstraint propertyConstraint3 = new InRangeConstraint(range); + constraints3.add(propertyConstraint3); + property2.setConstraints(constraints3); + return property2; + } + + private PropertyDefinition buildProperty1() { + PropertyDefinition property1 = new PropertyDefinition(); + property1.setDefaultValue("10"); + property1.setDescription("Size of the local disk, in Gigabytes (GB), " + + "available to applications running on the Compute node."); + property1.setType(ToscaType.INTEGER.name().toLowerCase()); + List constraints = new ArrayList<>(); + GreaterThanConstraint propertyConstraint1 = new GreaterThanConstraint("0"); + constraints.add(propertyConstraint1); + + LessOrEqualConstraint propertyConstraint2 = new LessOrEqualConstraint("10"); + constraints.add(propertyConstraint2); + + property1.setConstraints(constraints); + return property1; + } + + private boolean compareValue(String first, String second) { + + if (first == null && second == null) { + return true; + } + if (first != null) { + return first.equals(second); + } else { + return false; + } + } + + public void setOperations(RelationshipTypeOperation relationshipTypeOperation) { + this.relationshipTypeOperation = relationshipTypeOperation; + } + + @Test + public void testAddRelationshipType() { + + RelationshipTypeData relationshipTypeData = new RelationshipTypeData(); + RelationshipInstDataDefinition relationshipInstDataDefinition1 = new RelationshipInstDataDefinition(); + relationshipInstDataDefinition1.setUniqueId("tosca.relationships.Root"); + relationshipInstDataDefinition1.setType("tosca.relationships.Root"); + relationshipTypeData.setRelationshipTypeDataDefinition(relationshipInstDataDefinition1); + + RelationshipTypeDefinition relationshipTypeDefinition = new RelationshipTypeDefinition(relationshipTypeData); + relationshipTypeDefinition.setProperties(createPropertyData("prop1")); + relationshipTypeDefinition.setDerivedFrom("tosca.relationships.Root"); + + Mockito.doReturn(Either.left(Collections.singletonMap("prop1", new PropertyDefinition()))).when(propertyOperation) + .getAllTypePropertiesFromAllDerivedFrom(Mockito.anyString(), Mockito.any(), Mockito.any()); + + Mockito.doReturn(Either.left(new ArrayList<>(relationshipTypeDefinition.getProperties().values()))).when(propertyOperation) + .validatePropertiesUniqueness(Mockito.any(), Mockito.any()); + + Mockito.doReturn(Either.left(relationshipTypeData)).when(titanGenericDao) + .createNode(Mockito.any(), Mockito.eq(RelationshipTypeData.class)); + + Mockito.doReturn(Either.left(new HashMap())).when(propertyOperation) + .addPropertiesToElementType(Mockito.anyString(), Mockito.any(), Mockito.anyMap()); + + Mockito.doReturn(Either.left(relationshipTypeDefinition)) + .when(relationshipTypeOperation).getRelationshipTypeByUid(Mockito.anyString()); + + Mockito.doReturn(Either.left(new GraphRelation())) + .when(derivedFromOperation) + .addDerivedFromRelation(Mockito.anyString(), Mockito.anyString(), Mockito.any()); + + Mockito.doReturn(Either.left(relationshipTypeDefinition)) + .when(relationshipTypeOperation).getRelationshipType(Mockito.anyString(), Mockito.anyBoolean()); + + Either either = + relationshipTypeOperation.addRelationshipType(relationshipTypeDefinition, true); + + assertTrue(either.isLeft()); + } + + @Test + public void testGetRelationshipTypeNotConnected() { + Mockito.doReturn(Either.right(TitanOperationStatus.NOT_CONNECTED)) + .when(relationshipTypeOperation).getRelationshipTypeByUid(Mockito.anyString()); + + Either either = + relationshipTypeOperation.getRelationshipType(Mockito.anyString(), Mockito.anyBoolean()); + + assertTrue(either.isRight()); + } + + @Test + public void testGetRelationshipTypeSuccess() { + Mockito.doReturn(Either.left(relationshipTypeDefinition)) + .when(relationshipTypeOperation).getRelationshipTypeByUid(Mockito.anyString()); + + Either either = + relationshipTypeOperation.getRelationshipType(Mockito.anyString(), Mockito.anyBoolean()); + + assertTrue(either.isLeft()); + } + + @Test + public void testUpdateRelationshipType() { + RelationshipTypeDefinition newRelationshipTypeDefinition = new RelationshipTypeDefinition(); + newRelationshipTypeDefinition.setUniqueId("tosca.relationships.Container2"); + newRelationshipTypeDefinition.setDescription("desc2"); + newRelationshipTypeDefinition.setType("tosca.relationships.Container2"); + newRelationshipTypeDefinition.setDerivedFrom("tosca.relationships.Root"); + newRelationshipTypeDefinition.setProperties(createPropertyData("prop1")); + + Mockito.doReturn(Either.left(new RelationshipTypeData(newRelationshipTypeDefinition))).when(titanGenericDao) + .updateNode(Mockito.any(), Mockito.eq(RelationshipTypeData.class)); + + Mockito.doReturn(Either.left(newRelationshipTypeDefinition.getProperties())) + .when(propertyOperation).deletePropertiesAssociatedToNode(Mockito.any(), Mockito.anyString()); + + Mockito.doReturn(Either.left(newRelationshipTypeDefinition.getProperties())) + .when(propertyOperation).addPropertiesToElementType(Mockito.anyString(), Mockito.any(), Mockito.anyMap()); + + Mockito.doReturn(Either.left(newRelationshipTypeDefinition)).when(relationshipTypeOperation) + .getRelationshipTypeByUid(Mockito.anyString()); + + Mockito.doReturn(StorageOperationStatus.OK).when(derivedFromOperation) + .removeDerivedFromRelation(Mockito.anyString(), Mockito.anyString(), Mockito.any()); + + Mockito.doReturn(Either.left(new GraphRelation())) + .when(derivedFromOperation) + .addDerivedFromRelation(Mockito.anyString(), Mockito.anyString(), Mockito.any()); + + Either either = + relationshipTypeOperation.updateRelationshipType(relationshipTypeDefinition, + newRelationshipTypeDefinition, false); + + assertTrue(either.isLeft()); + } + + @Test + public void testGetRelationshipTypeByUid() { + RelationshipTypeData relationshipTypeData = new RelationshipTypeData(relationshipTypeDefinition); + + Mockito.doReturn(Either.left(relationshipTypeData)).when(titanGenericDao) + .getNode(Mockito.anyString(), Mockito.any(), Mockito.eq(RelationshipTypeData.class)); + + Mockito.doReturn(Either.left(relationshipTypeDefinition.getProperties())) + .when(propertyOperation).findPropertiesOfNode(Mockito.any(), Mockito.anyString()); + + RelationshipTypeDefinition childRelationshipTypeDefinition = new RelationshipTypeDefinition(); + childRelationshipTypeDefinition.setType("tosca.relationships.ContainerChild"); + + Mockito.doReturn(Either.left(new ImmutablePair(new RelationshipTypeData(childRelationshipTypeDefinition), null))).when(titanGenericDao) + .getChild(Mockito.anyString(), Mockito.anyString(), Mockito.any(), Mockito.any(), + Mockito.eq(RelationshipTypeData.class)); + + Either either = + relationshipTypeOperation.getRelationshipTypeByUid("tosca.relationships.Container1"); + + assertTrue(either.isLeft() + && "tosca.relationships.ContainerChild".equals(either.left().value().getDerivedFrom())); + } + + private Map createPropertyData(String value) { + PropertyDefinition propertyDefinition = new PropertyDefinition(); + propertyDefinition.setDefaultValue(value); + propertyDefinition.setDescription(PROP + "_" + value); + propertyDefinition.setType(ToscaType.INTEGER.name().toLowerCase()); + List constraints = new ArrayList<>(); + List range = new ArrayList<>(); + range.add("1"); + range.add("4"); + InRangeConstraint propertyConstraint = new InRangeConstraint(range); + constraints.add(propertyConstraint); + propertyDefinition.setConstraints(constraints); + Map propertiesMap = new HashMap<>(); + propertiesMap.put(PROP, propertyDefinition); + return propertiesMap; + } + +} diff --git a/catalog-model/src/test/java/org/openecomp/sdc/be/model/operations/impl/ToscaElementLifecycleOperationTest.java b/catalog-model/src/test/java/org/openecomp/sdc/be/model/operations/impl/ToscaElementLifecycleOperationTest.java index 88bb5142aa..c70e41b2f1 100644 --- a/catalog-model/src/test/java/org/openecomp/sdc/be/model/operations/impl/ToscaElementLifecycleOperationTest.java +++ b/catalog-model/src/test/java/org/openecomp/sdc/be/model/operations/impl/ToscaElementLifecycleOperationTest.java @@ -59,10 +59,6 @@ import org.openecomp.sdc.common.util.ValidationUtils; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import java.io.BufferedOutputStream; -import java.io.File; -import java.io.FileOutputStream; -import java.io.OutputStream; import java.util.*; import static org.junit.Assert.assertEquals; @@ -147,7 +143,7 @@ public class ToscaElementLifecycleOperationTest extends ModelTestBase { cap1.setDescription("create"); cap1.setUniqueId(UniqueIdBuilder.buildCapabilityUid(id, "cap1")); - status = nodeTypeOperation.addToscaDataToToscaElement(id, EdgeLabelEnum.CAPABILITIES, VertexTypeEnum.CAPABILTIES, cap1, JsonPresentationFields.NAME); + status = nodeTypeOperation.addToscaDataToToscaElement(id, EdgeLabelEnum.CAPABILITIES, VertexTypeEnum.CAPABILITIES, cap1, JsonPresentationFields.NAME); assertSame(status, StorageOperationStatus.OK); res = lifecycleOperation.checkinToscaELement(LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT, id, ownerVertex.getUniqueId(), ownerVertex.getUniqueId()); @@ -164,7 +160,7 @@ public class ToscaElementLifecycleOperationTest extends ModelTestBase { cap1.setDescription("update"); - status = nodeTypeOperation.updateToscaDataOfToscaElement(id, EdgeLabelEnum.CAPABILITIES, VertexTypeEnum.CAPABILTIES, cap1, JsonPresentationFields.NAME); + status = nodeTypeOperation.updateToscaDataOfToscaElement(id, EdgeLabelEnum.CAPABILITIES, VertexTypeEnum.CAPABILITIES, cap1, JsonPresentationFields.NAME); assertSame(status, StorageOperationStatus.OK); PropertyDataDefinition prop66 = new PropertyDataDefinition(); diff --git a/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/CapabilityDataDefinition.java b/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/CapabilityDataDefinition.java index fdd1386e48..2612e6f888 100644 --- a/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/CapabilityDataDefinition.java +++ b/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/CapabilityDataDefinition.java @@ -32,7 +32,7 @@ import java.util.List; */ public class CapabilityDataDefinition extends ToscaDataDefinition { - public static final String MIN_OCCURRENCES = "1"; + public static final String MIN_OCCURRENCES = "0"; public static final String MAX_OCCURRENCES = "UNBOUNDED"; /** diff --git a/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/RelationshipInstDataDefinition.java b/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/RelationshipInstDataDefinition.java index 72d9c36bf6..2f995fd844 100644 --- a/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/RelationshipInstDataDefinition.java +++ b/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/RelationshipInstDataDefinition.java @@ -32,6 +32,7 @@ public class RelationshipInstDataDefinition extends ToscaDataDefinition { this.setDescription(cdt.getDescription()); this.setType(cdt.getType()); this.setValidSourceTypes(cdt.getValidSourceTypes()); + this.setValidTargetTypes(cdt.getValidTargetTypes()); this.setVersion(cdt.getVersion()); this.setOriginUI(cdt.isOriginUI()); this.setCreationTime(cdt.getCreationTime()); @@ -54,11 +55,11 @@ public class RelationshipInstDataDefinition extends ToscaDataDefinition { return (String) getToscaPresentationValue(JsonPresentationFields.REQUIREMENT); } public void setCapability(String capability) { - setToscaPresentationValue(JsonPresentationFields.CAPAPILITY, capability); + setToscaPresentationValue(JsonPresentationFields.CAPABILITY, capability); } public String getCapability() { - return (String) getToscaPresentationValue(JsonPresentationFields.CAPAPILITY); + return (String) getToscaPresentationValue(JsonPresentationFields.CAPABILITY); } public void setToId(Object toId) { setToscaPresentationValue(JsonPresentationFields.TO_ID, toId); @@ -144,6 +145,14 @@ public class RelationshipInstDataDefinition extends ToscaDataDefinition { setToscaPresentationValue(JsonPresentationFields.VALID_SOURCE_TYPES, validSourceTypes); } + public List getValidTargetTypes() { + return (List) getToscaPresentationValue(JsonPresentationFields.VALID_TARGET_TYPES); + } + + public void setValidTargetTypes(List validTargetTypes) { + setToscaPresentationValue(JsonPresentationFields.VALID_TARGET_TYPES, validTargetTypes); + } + public String getVersion() { return (String) getToscaPresentationValue(JsonPresentationFields.VERSION); } diff --git a/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/RequirementDataDefinition.java b/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/RequirementDataDefinition.java index 4ede93eaa6..0df5ba500d 100644 --- a/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/RequirementDataDefinition.java +++ b/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/RequirementDataDefinition.java @@ -31,7 +31,7 @@ import java.util.List; */ public class RequirementDataDefinition extends ToscaDataDefinition { - public static final String MIN_OCCURRENCES = "1"; + public static final String MIN_OCCURRENCES = "0"; public static final String MAX_OCCURRENCES = "UNBOUNDED"; public static final String MAX_DEFAULT_OCCURRENCES = "1"; @@ -107,11 +107,11 @@ public class RequirementDataDefinition extends ToscaDataDefinition { */ public String getCapability() { - return (String) getToscaPresentationValue(JsonPresentationFields.CAPAPILITY); + return (String) getToscaPresentationValue(JsonPresentationFields.CAPABILITY); } public void setCapability(String capability) { - setToscaPresentationValue(JsonPresentationFields.CAPAPILITY, capability); + setToscaPresentationValue(JsonPresentationFields.CAPABILITY, capability); } /** diff --git a/common-be/src/main/java/org/openecomp/sdc/be/datatypes/enums/JsonPresentationFields.java b/common-be/src/main/java/org/openecomp/sdc/be/datatypes/enums/JsonPresentationFields.java index 7a4c3d4af7..a72984ab7d 100644 --- a/common-be/src/main/java/org/openecomp/sdc/be/datatypes/enums/JsonPresentationFields.java +++ b/common-be/src/main/java/org/openecomp/sdc/be/datatypes/enums/JsonPresentationFields.java @@ -129,10 +129,11 @@ public enum JsonPresentationFields { SOURCE("source", null), //Requirement - CAPAPILITY("capability", null), + CAPABILITY("capability", null), NODE("node", null), RELATIONSHIP("relationship", null), VALID_SOURCE_TYPES("validSourceTypes", null), + VALID_TARGET_TYPES("validTargetTypes", null), REQUIREMENT_ID("requirementId", null), PARENT_NAME("parentName", null), PREVIOUS_NAME("previousName", null), diff --git a/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/api/Urls.java b/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/api/Urls.java index ba35ac3d33..1f1c90764b 100644 --- a/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/api/Urls.java +++ b/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/api/Urls.java @@ -408,4 +408,16 @@ public interface Urls { final String UPDATE_INTERFACE_OPERATIONS = SDC_HTTP_METHOD + "://%s:%s/sdc2/rest/v1/catalog/%s/%s/interfaceOperations"; final String GET_INTERFACE_OPERATIONS = SDC_HTTP_METHOD + "://%s:%s/sdc2/rest/v1/catalog/%s/%s/interfaces/%s/operations/%s"; final String DELETE_INTERFACE_OPERATIONS = SDC_HTTP_METHOD + "://%s:%s/sdc2/rest/v1/catalog/%s/%s/interfaces/%s/operations/%s"; + + //Requirements + String CREATE_REQUIREMENT = SDC_HTTP_METHOD + "://%s:%s/sdc2/rest/v1/catalog/%s/%s/requirements"; + String UPDATE_REQUIREMENT = SDC_HTTP_METHOD + "://%s:%s/sdc2/rest/v1/catalog/%s/%s/requirements"; + String DELETE_REQUIREMENT = SDC_HTTP_METHOD + "://%s:%s/sdc2/rest/v1/catalog/%s/%s/requirements/%s"; + String GET_REQUIREMENT = SDC_HTTP_METHOD + "://%s:%s/sdc2/rest/v1/catalog/%s/%s/requirements/%s"; + //Capabilities + String CREATE_CAPABILITY = SDC_HTTP_METHOD + "://%s:%s/sdc2/rest/v1/catalog/%s/%s/capabilities"; + String UPDATE_CAPABILITY = SDC_HTTP_METHOD + "://%s:%s/sdc2/rest/v1/catalog/%s/%s/capabilities"; + String DELETE_CAPABILITY = SDC_HTTP_METHOD + "://%s:%s/sdc2/rest/v1/catalog/%s/%s/capabilities/%s"; + String GET_CAPABILITY = SDC_HTTP_METHOD + "://%s:%s/sdc2/rest/v1/catalog/%s/%s/capabilities/%s"; + } diff --git a/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/capability/CapabilitiesTest.java b/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/capability/CapabilitiesTest.java new file mode 100644 index 0000000000..ecdb48619b --- /dev/null +++ b/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/capability/CapabilitiesTest.java @@ -0,0 +1,119 @@ +/* + * Copyright © 2016-2018 European Support Limited + * + * 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. + */ + +package org.openecomp.sdc.ci.tests.capability; + +import org.junit.Rule; +import org.junit.rules.TestName; +import org.openecomp.sdc.be.model.Service; +import org.openecomp.sdc.be.model.User; +import org.openecomp.sdc.ci.tests.api.ComponentBaseTest; +import org.openecomp.sdc.ci.tests.datatypes.CapabilityDetails; +import org.openecomp.sdc.ci.tests.datatypes.ServiceReqDetails; +import org.openecomp.sdc.ci.tests.datatypes.enums.UserRoleEnum; +import org.openecomp.sdc.ci.tests.datatypes.http.RestResponse; +import org.openecomp.sdc.ci.tests.utils.general.ElementFactory; +import org.openecomp.sdc.ci.tests.utils.rest.BaseRestUtils; +import org.openecomp.sdc.ci.tests.utils.rest.CapabilityRestUtils; +import org.openecomp.sdc.ci.tests.utils.rest.ServiceRestUtils; +import org.testng.Assert; +import org.testng.annotations.BeforeTest; +import org.testng.annotations.Test; + +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +import static org.openecomp.sdc.ci.tests.utils.general.AtomicOperationUtils.getServiceObject; + +public class CapabilitiesTest extends ComponentBaseTest { + @Rule + public static final TestName name = new TestName(); + + private ServiceReqDetails component; + private User user = null; + + public CapabilitiesTest() { + super(name, CapabilitiesTest.class.getName()); + } + + @BeforeTest + public void init() throws Exception { + user = ElementFactory.getDefaultUser(UserRoleEnum.DESIGNER); + component = ElementFactory.getDefaultService(); + component.setName("comp_cap" + Math.random()); + ServiceRestUtils.createService(component, user); + } + + @Test + public void createCapabilityTest() throws Exception { + + CapabilityDetails capability = createCapability(); + RestResponse restResponse = CapabilityRestUtils.createCapability(component.getUniqueId(), + Collections.singletonList(capability), user); + logger.info("createCapability Response Code:" + restResponse.getErrorCode()); + Assert.assertEquals((int) restResponse.getErrorCode(), BaseRestUtils.STATUS_CODE_SUCCESS); + } + + + + @Test(dependsOnMethods = "createCapabilityTest") + public void updateCapabilityTest() throws Exception { + + CapabilityDetails capability = createCapability(); + capability.setMaxOccurrences("10"); + capability.setMinOccurrences("4"); + RestResponse restResponse = CapabilityRestUtils.updateCapability(component.getUniqueId(), + Collections.singletonList(capability), user); + logger.info("updateCapability Response Code:" + restResponse.getErrorCode()); + Assert.assertEquals((int) restResponse.getErrorCode(), BaseRestUtils.STATUS_CODE_SUCCESS); + } + + @Test(dependsOnMethods = "updateCapabilityTest") + public void getCapabilityTest() throws Exception { + Service service = getServiceObject(component.getUniqueId()); + + List capabilityDefinitionList = service.getCapabilities().values() + .stream().flatMap(Collection::stream).collect(Collectors.toList()); + + RestResponse restResponse = CapabilityRestUtils.getCapability(component.getUniqueId(), + capabilityDefinitionList.get(0).getUniqueId(), user); + logger.info("getCapabilityTest Response Code:" + restResponse.getErrorCode()); + Assert.assertEquals((int) restResponse.getErrorCode(), BaseRestUtils.STATUS_CODE_SUCCESS); + } + + @Test(dependsOnMethods = "getCapabilityTest") + public void deleteCapabilityTest() throws Exception { + Service service = getServiceObject(component.getUniqueId()); + + List capabilityDefinitionList = service.getCapabilities().values() + .stream().flatMap(Collection::stream).collect(Collectors.toList()); + + RestResponse restResponse = CapabilityRestUtils.deleteCapability(component.getUniqueId(), + capabilityDefinitionList.get(0).getUniqueId(), user); + logger.info("deleteCapabilityTest Response Code:" + restResponse.getErrorCode()); + Assert.assertEquals((int) restResponse.getErrorCode(), BaseRestUtils.STATUS_CODE_SUCCESS); + } + + private CapabilityDetails createCapability() { + CapabilityDetails capabilityDetails = new CapabilityDetails(); + capabilityDetails.setName("cap" + Math.random()); + capabilityDetails.setType("tosca.capabilities.network.Bindable"); + + return capabilityDetails; + } +} diff --git a/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/datatypes/CapabilityDetails.java b/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/datatypes/CapabilityDetails.java new file mode 100644 index 0000000000..954a16a63d --- /dev/null +++ b/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/datatypes/CapabilityDetails.java @@ -0,0 +1,56 @@ +/* + * Copyright © 2016-2018 European Support Limited + * + * 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. + */ + +package org.openecomp.sdc.ci.tests.datatypes; + +public class CapabilityDetails { + private String name; + private String type; + private String maxOccurrences; + private String minOccurrences; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getMaxOccurrences() { + return maxOccurrences; + } + + public void setMaxOccurrences(String maxOccurrences) { + this.maxOccurrences = maxOccurrences; + } + + public String getMinOccurrences() { + return minOccurrences; + } + + public void setMinOccurrences(String minOccurrences) { + this.minOccurrences = minOccurrences; + } +} diff --git a/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/datatypes/RequirementDetails.java b/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/datatypes/RequirementDetails.java new file mode 100644 index 0000000000..a720786d83 --- /dev/null +++ b/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/datatypes/RequirementDetails.java @@ -0,0 +1,74 @@ +/* + * Copyright © 2016-2018 European Support Limited + * + * 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. + */ + +package org.openecomp.sdc.ci.tests.datatypes; + +public class RequirementDetails { + private String capability; + private String name; + private String node; + private String relationship; + private String maxOccurrences; + private String minOccurrences; + + public String getCapability() { + return capability; + } + + public void setCapability(String capability) { + this.capability = capability; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getNode() { + return node; + } + + public void setNode(String node) { + this.node = node; + } + + public String getRelationship() { + return relationship; + } + + public void setRelationship(String relationship) { + this.relationship = relationship; + } + + public String getMaxOccurrences() { + return maxOccurrences; + } + + public void setMaxOccurrences(String maxOccurrences) { + this.maxOccurrences = maxOccurrences; + } + + public String getMinOccurrences() { + return minOccurrences; + } + + public void setMinOccurrences(String minOccurrences) { + this.minOccurrences = minOccurrences; + } +} diff --git a/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/requirements/RequirementsTest.java b/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/requirements/RequirementsTest.java new file mode 100644 index 0000000000..51894e7ec1 --- /dev/null +++ b/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/requirements/RequirementsTest.java @@ -0,0 +1,118 @@ +/* + * Copyright © 2016-2018 European Support Limited + * + * 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. + */ + +package org.openecomp.sdc.ci.tests.requirements; + +import org.junit.Assert; +import org.junit.Rule; +import org.junit.rules.TestName; +import org.openecomp.sdc.be.model.RequirementDefinition; +import org.openecomp.sdc.be.model.Service; +import org.openecomp.sdc.be.model.User; +import org.openecomp.sdc.ci.tests.api.ComponentBaseTest; +import org.openecomp.sdc.ci.tests.datatypes.RequirementDetails; +import org.openecomp.sdc.ci.tests.datatypes.ServiceReqDetails; +import org.openecomp.sdc.ci.tests.datatypes.enums.UserRoleEnum; +import org.openecomp.sdc.ci.tests.datatypes.http.RestResponse; +import org.openecomp.sdc.ci.tests.utils.general.ElementFactory; +import org.openecomp.sdc.ci.tests.utils.rest.BaseRestUtils; +import org.openecomp.sdc.ci.tests.utils.rest.RequirementsUtils; +import org.openecomp.sdc.ci.tests.utils.rest.ServiceRestUtils; +import org.testng.annotations.BeforeTest; +import org.testng.annotations.Test; + +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +import static org.openecomp.sdc.ci.tests.utils.general.AtomicOperationUtils.getServiceObject; + +public class RequirementsTest extends ComponentBaseTest { + @Rule + public static final TestName name = new TestName(); + + private ServiceReqDetails component; + private User user = null; + + public RequirementsTest() { + super(name, RequirementsTest.class.getName()); + } + + @BeforeTest + public void init() throws Exception { + user = ElementFactory.getDefaultUser(UserRoleEnum.DESIGNER); + component = ElementFactory.getDefaultService(); + component.setName("comp_req" + Math.random()); + ServiceRestUtils.createService(component, user); + } + + @Test + public void createRequirementTest() throws Exception { + + RequirementDetails requirement = createRequirement(); + RestResponse restResponse = RequirementsUtils.createRequirement(component.getUniqueId(), + Collections.singletonList(requirement), user); + logger.info("createRequirement Response Code:" + restResponse.getErrorCode()); + Assert.assertEquals((int) restResponse.getErrorCode(), BaseRestUtils.STATUS_CODE_SUCCESS); + } + + @Test(dependsOnMethods = "createRequirementTest") + public void updateRequirementTest() throws Exception { + + RequirementDetails requirement = createRequirement(); + requirement.setMaxOccurrences("10"); + requirement.setMinOccurrences("4"); + RestResponse restResponse = RequirementsUtils.updateRequirement(component.getUniqueId(), + Collections.singletonList(requirement), user); + logger.info("updateRequirement Response Code:" + restResponse.getErrorCode()); + Assert.assertEquals((int) restResponse.getErrorCode(), BaseRestUtils.STATUS_CODE_SUCCESS); + } + + @Test(dependsOnMethods = "updateRequirementTest") + public void getRequirementTest() throws Exception { + Service service = getServiceObject(component.getUniqueId()); + + List requirementDefinitionList = service.getRequirements().values() + .stream().flatMap(Collection::stream).collect(Collectors.toList()); + + RestResponse restResponse = RequirementsUtils.getRequirement(component.getUniqueId(), + requirementDefinitionList.get(0).getUniqueId(), user); + logger.info("getRequirementTest Response Code:" + restResponse.getErrorCode()); + Assert.assertEquals((int) restResponse.getErrorCode(), BaseRestUtils.STATUS_CODE_SUCCESS); + } + + @Test(dependsOnMethods = "getRequirementTest") + public void deleteRequirementTest() throws Exception { + Service service = getServiceObject(component.getUniqueId()); + + List requirementDefinitionList = service.getRequirements().values() + .stream().flatMap(Collection::stream).collect(Collectors.toList()); + + RestResponse restResponse = RequirementsUtils.deleteRequirement(component.getUniqueId(), + requirementDefinitionList.get(0).getUniqueId(), user); + logger.info("deleteRequirementTest Response Code:" + restResponse.getErrorCode()); + Assert.assertEquals((int) restResponse.getErrorCode(), BaseRestUtils.STATUS_CODE_SUCCESS); + } + + private RequirementDetails createRequirement() { + RequirementDetails requirementDetails = new RequirementDetails(); + requirementDetails.setName("req" + Math.random()); + requirementDetails.setCapability("tosca.capabilities.network.Bindable"); + + return requirementDetails; + } +} diff --git a/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/utils/rest/CapabilityRestUtils.java b/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/utils/rest/CapabilityRestUtils.java new file mode 100644 index 0000000000..1959aa8b9a --- /dev/null +++ b/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/utils/rest/CapabilityRestUtils.java @@ -0,0 +1,76 @@ +/* + * Copyright © 2016-2018 European Support Limited + * + * 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. + */ + +package org.openecomp.sdc.ci.tests.utils.rest; + +import com.google.gson.Gson; +import org.openecomp.sdc.be.model.User; +import org.openecomp.sdc.ci.tests.api.Urls; +import org.openecomp.sdc.ci.tests.config.Config; +import org.openecomp.sdc.ci.tests.datatypes.CapabilityDetails; +import org.openecomp.sdc.ci.tests.datatypes.http.RestResponse; + +import java.util.List; + +public class CapabilityRestUtils extends BaseRestUtils { + private static Gson gson = new Gson(); + private static final String COMPONENT_TYPE = "services"; + + public static RestResponse createCapability(String componentId, + List capabilityDetailsList, + User user) throws Exception{ + Config config = Config.instance(); + String url = String.format(Urls.CREATE_CAPABILITY, config.getCatalogBeHost(), config.getCatalogBePort(), + COMPONENT_TYPE, componentId); + + String data = "{ \"capabilities\" : {" + "\"" +capabilityDetailsList.get(0).getType()+ "\"" +" : " + + gson.toJson(capabilityDetailsList) + " } }"; + + return sendPost(url, data , user.getUserId(), acceptHeaderData); + } + + public static RestResponse updateCapability(String componentId, + List capabilityDetailsList, + User user) throws Exception{ + Config config = Config.instance(); + String url = String.format(Urls.UPDATE_CAPABILITY, config.getCatalogBeHost(), config.getCatalogBePort(), + COMPONENT_TYPE, componentId); + + String data = "{ \"capabilities\" : {" + "\"" +capabilityDetailsList.get(0).getType()+ "\"" +" : " + + gson.toJson(capabilityDetailsList) + " } }"; + + return sendPost(url, data , user.getUserId(), acceptHeaderData); + } + + public static RestResponse deleteCapability(String componentId, + String requirementId, + User user) throws Exception{ + Config config = Config.instance(); + String url = String.format(Urls.DELETE_CAPABILITY, config.getCatalogBeHost(), config.getCatalogBePort(), + COMPONENT_TYPE, componentId, requirementId); + return sendDelete(url, user.getUserId()); + } + + public static RestResponse getCapability(String componentId, + String requirementId, + User user) throws Exception{ + Config config = Config.instance(); + String url = String.format(Urls.GET_CAPABILITY, config.getCatalogBeHost(), config.getCatalogBePort(), + COMPONENT_TYPE, componentId, requirementId); + return sendDelete(url, user.getUserId()); + } + +} diff --git a/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/utils/rest/RequirementsUtils.java b/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/utils/rest/RequirementsUtils.java new file mode 100644 index 0000000000..4be1d941ce --- /dev/null +++ b/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/utils/rest/RequirementsUtils.java @@ -0,0 +1,75 @@ +/* + * Copyright © 2016-2018 European Support Limited + * + * 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. + */ + +package org.openecomp.sdc.ci.tests.utils.rest; + +import com.google.gson.Gson; +import org.openecomp.sdc.be.model.User; +import org.openecomp.sdc.ci.tests.api.Urls; +import org.openecomp.sdc.ci.tests.config.Config; +import org.openecomp.sdc.ci.tests.datatypes.RequirementDetails; +import org.openecomp.sdc.ci.tests.datatypes.http.RestResponse; + +import java.util.List; + +public class RequirementsUtils extends BaseRestUtils { + private static Gson gson = new Gson(); + private static final String COMPONENT_TYPE = "services"; + + public static RestResponse createRequirement(String componentId, + List requirementDefinitionList, + User user) throws Exception{ + Config config = Config.instance(); + String url = String.format(Urls.CREATE_REQUIREMENT, config.getCatalogBeHost(), config.getCatalogBePort(), + COMPONENT_TYPE, componentId); + + String data = "{ \"requirements\" : {" + "\"" +requirementDefinitionList.get(0).getCapability()+ "\"" +" : " + + gson.toJson(requirementDefinitionList) + " } }"; + + return sendPost(url, data , user.getUserId(), acceptHeaderData); + } + + public static RestResponse updateRequirement(String componentId, + List requirementDefinitionList, + User user) throws Exception{ + Config config = Config.instance(); + String url = String.format(Urls.UPDATE_REQUIREMENT, config.getCatalogBeHost(), config.getCatalogBePort(), + COMPONENT_TYPE, componentId); + + String data = "{ \"requirements\" : {" + "\"" +requirementDefinitionList.get(0).getCapability()+ "\"" +" : " + + gson.toJson(requirementDefinitionList) + " } }"; + + return sendPost(url, data , user.getUserId(), acceptHeaderData); + } + + public static RestResponse deleteRequirement(String componentId, + String requirementId, + User user) throws Exception{ + Config config = Config.instance(); + String url = String.format(Urls.DELETE_REQUIREMENT, config.getCatalogBeHost(), config.getCatalogBePort(), + COMPONENT_TYPE, componentId, requirementId); + return sendDelete(url, user.getUserId()); + } + + public static RestResponse getRequirement(String componentId, + String requirementId, + User user) throws Exception{ + Config config = Config.instance(); + String url = String.format(Urls.GET_REQUIREMENT, config.getCatalogBeHost(), config.getCatalogBePort(), + COMPONENT_TYPE, componentId, requirementId); + return sendDelete(url, user.getUserId()); + } +} diff --git a/test-apis-ci/src/main/resources/ci/testSuites/cap_req.xml b/test-apis-ci/src/main/resources/ci/testSuites/cap_req.xml new file mode 100644 index 0000000000..8298af2da5 --- /dev/null +++ b/test-apis-ci/src/main/resources/ci/testSuites/cap_req.xml @@ -0,0 +1,10 @@ + + + + + + + + + + -- cgit 1.2.3-korg