From 82e531a1ee8ffa30e80b27d9097a2272ae18cdee Mon Sep 17 00:00:00 2001 From: Mojahidul Islam Date: Tue, 14 May 2019 12:49:31 +0530 Subject: Support Capability Properties This change includes following changes 1. Get capability properties from global types- BE 2. Show capability properties in cap/req screen 3. Support Capability Properties in assingment, operation and consumption screens Change-Id: Ieb4fa5705007c8bed3d82eb4fe4604572aa202d7 Issue-ID: SDC-2294 Signed-off-by: Mojahidul Islam --- .../components/impl/CapabilitiesBusinessLogic.java | 566 ++++++++++++--------- .../impl/ComponentInstanceBusinessLogic.java | 168 +++--- .../impl/InterfaceOperationBusinessLogic.java | 24 +- .../be/components/impl/ServiceBusinessLogic.java | 54 +- .../lifecycle/CertificationChangeTransition.java | 6 +- .../components/lifecycle/CheckoutTransition.java | 6 +- .../ComponentInstancePropertyDeclarator.java | 35 +- .../property/DefaultPropertyDeclarator.java | 90 ++-- .../sdc/be/components/utils/ConsumptionUtils.java | 127 +++++ .../components/utils/InterfaceOperationUtils.java | 28 +- .../sdc/be/components/utils/PropertiesUtils.java | 171 +++++++ .../utils/ProxyServicePropertiesUtils.java | 54 -- .../validation/CapabilitiesValidation.java | 55 +- .../validation/InterfaceOperationValidation.java | 6 +- .../sdc/be/servlets/ServiceConsumptionServlet.java | 9 +- .../openecomp/sdc/be/tosca/ToscaExportHandler.java | 4 +- .../main/resources/config/error-configuration.yaml | 17 +- .../impl/CapabilitiesBusinessLogicTest.java | 84 ++- .../impl/InterfaceOperationBusinessLogicTest.java | 42 ++ .../components/impl/utils/PropertiesUtilsTest.java | 195 +++++++ .../components/property/CapabilityTestUtils.java | 51 ++ .../ComponentInstancePropertyDeclaratorTest.java | 62 +++ .../be/components/utils/ConsumptionUtilsTest.java | 76 +++ .../utils/InterfaceOperationUtilsTest.java | 6 + .../validation/CapabilitiesValidationTest.java | 78 ++- .../org/openecomp/sdc/be/dao/api/ActionStatus.java | 1 + .../sdc/be/model/ComponentParametersView.java | 4 +- .../model/jsontitan/operations/BaseOperation.java | 2 +- .../operations/CapabilitiesOperation.java | 104 +++- .../operations/TopologyTemplateOperation.java | 55 +- .../jsontitan/operations/ToscaOperationFacade.java | 128 ++++- .../be/model/jsontitan/utils/ModelConverter.java | 51 +- .../operations/CapabilitiesOperationTest.java | 87 ++++ .../model/jsontitan/utils/CapabilityTestUtils.java | 85 ++++ .../model/jsontitan/utils/ModelConverterTest.java | 19 + catalog-ui/src/app/models/capability-types.ts | 3 + catalog-ui/src/app/models/capability.ts | 7 + .../models/properties-inputs/property-be-model.ts | 6 +- .../models/properties-inputs/property-fe-model.ts | 2 + catalog-ui/src/app/models/tosca-presentation.ts | 2 + catalog-ui/src/app/modules/directive-module.ts | 2 +- .../service-consumption.component.ts | 22 +- .../interface-operation.page.component.ts | 18 +- .../operation-creator.component.html | 21 +- .../operation-creator.component.ts | 20 +- .../param-row/param-row.component.html | 9 + .../param-row/param-row.component.ts | 31 +- .../properties-assignment.page.component.ts | 138 ++++- .../capabilities-editor.component.ts | 4 + .../service-consumption-editor.component.html | 9 + .../service-consumption-editor.component.ts | 53 +- .../services/component-services/service.service.ts | 4 +- .../service-consumption-view-model.ts | 24 +- .../service-consumption-view.html | 1 + .../req-and-capabilities-editable-view.html | 62 ++- .../req-and-capabilities/req-and-capabilities.less | 141 +++-- catalog-ui/src/assets/styles/mixins_old.less | 5 + .../sdc/ci/tests/capability/CapabilitiesTest.java | 313 ++++++++++-- .../sdc/ci/tests/datatypes/CapabilityDetails.java | 13 + .../ci/tests/utils/rest/CapabilityRestUtils.java | 19 +- 60 files changed, 2790 insertions(+), 689 deletions(-) create mode 100644 catalog-be/src/main/java/org/openecomp/sdc/be/components/utils/ConsumptionUtils.java create mode 100644 catalog-be/src/main/java/org/openecomp/sdc/be/components/utils/PropertiesUtils.java delete mode 100644 catalog-be/src/main/java/org/openecomp/sdc/be/components/utils/ProxyServicePropertiesUtils.java create mode 100644 catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/utils/PropertiesUtilsTest.java create mode 100644 catalog-be/src/test/java/org/openecomp/sdc/be/components/property/CapabilityTestUtils.java create mode 100644 catalog-be/src/test/java/org/openecomp/sdc/be/components/utils/ConsumptionUtilsTest.java create mode 100644 catalog-model/src/test/java/org/openecomp/sdc/be/model/jsontitan/operations/CapabilitiesOperationTest.java create mode 100644 catalog-model/src/test/java/org/openecomp/sdc/be/model/jsontitan/utils/CapabilityTestUtils.java 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 index 75d5836df6..f2fd37704d 100644 --- 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 @@ -18,28 +18,35 @@ package org.openecomp.sdc.be.components.impl; 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.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.elements.MapPropertiesDataDefinition; +import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition; 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.Component; +import org.openecomp.sdc.be.model.ComponentInstanceProperty; 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.jsontitan.utils.ModelConverter; import org.openecomp.sdc.be.model.operations.api.ICapabilityTypeOperation; import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus; +import org.openecomp.sdc.be.model.operations.impl.UniqueIdBuilder; 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.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; @@ -47,15 +54,13 @@ import java.util.Optional; import java.util.UUID; import java.util.stream.Collectors; -@Component("capabilitiesBusinessLogic") +@org.springframework.stereotype.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 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 {}"; + private static final String EXCEPTION_OCCURRED_DURING_CAPABILITIES = "Exception occurred during {}. Response is {}"; @Autowired private CapabilitiesOperation capabilitiesOperation; @@ -64,7 +69,6 @@ public class CapabilitiesBusinessLogic extends BaseBusinessLogic { @Autowired private ICapabilityTypeOperation capabilityTypeOperation; - public void setCapabilitiesValidation(CapabilitiesValidation capabilitiesValidation) { this.capabilitiesValidation = capabilitiesValidation; } @@ -73,67 +77,22 @@ public class CapabilitiesBusinessLogic extends BaseBusinessLogic { 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()); + public Either, ResponseFormat> createCapabilities(String componentId, + List capabilityDefinitions, + User user, String errorContext, boolean lock) { + Either validateUserAndCapabilitiesEither = + validateUserAndCapabilities(user, componentId, errorContext, capabilityDefinitions); + if(validateUserAndCapabilitiesEither.isRight()) { + return Either.right(validateUserAndCapabilitiesEither.right().value()); } + Component storedComponent = validateUserAndCapabilitiesEither.left().value(); - Either lockResult = lockComponentResult(lock, - storedComponent, errorContext); + 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); + return createCapability(componentId, capabilityDefinitions, storedComponent); } catch (Exception e) { titanDao.rollback(); LOGGER.error(EXCEPTION_OCCURRED_DURING_CAPABILITIES, "addOrUpdate", e); @@ -146,39 +105,99 @@ public class CapabilitiesBusinessLogic extends BaseBusinessLogic { } } - public Either, ResponseFormat> updateCapabilities( - String componentId, List capabilityDefinitions, - User user, String errorContext, boolean lock) { + + private Either validateUserAndCapabilities(User user, String componentId, + String errorContext, + List capabilityDefinitions ) { + validateUserExists(user.getUserId(), errorContext, true); + Either componentEither = getComponentDetails(componentId); + if (componentEither.isRight()) { + return Either.right(componentEither.right().value()); + } + Component storedComponent = componentEither.left().value(); + Either capabilitiesValidationEither = capabilitiesValidation + .validateCapabilities(capabilityDefinitions, storedComponent, false); + if (capabilitiesValidationEither.isRight()) { + return Either.right(capabilitiesValidationEither.right().value()); + } + return Either.left(storedComponent); + } + + private Either, ResponseFormat> createCapability(String componentId, + List capabilityDefinitions, + Component storedComponent) { + Either, StorageOperationStatus> result; + List capabilitiesListStoredInComponent = null; + Map> storedComponentCapabilities = storedComponent.getCapabilities(); + if (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()), "")); + } + Map propertiesMap = + getCapabilitiesPropertiesDataDefinitionMap(capabilityDefinitions); + if (MapUtils.isNotEmpty(propertiesMap)) { + StorageOperationStatus storageOperationStatus = capabilitiesOperation + .createOrUpdateCapabilityProperties(componentId, propertiesMap); + if (storageOperationStatus != StorageOperationStatus.OK) { + titanDao.rollback(); + return Either.right(componentsUtils.getResponseFormat(storageOperationStatus)); + } + } + titanDao.commit(); + return Either.left(capabilitiesToReturn); + } + + public Either, ResponseFormat> updateCapabilities(String componentId, + List capabilityDefinitions, + User user, String errorContext, boolean lock) { validateUserExists(user.getUserId(), errorContext, true); - Either componentEither - = getComponentDetails(componentId); + Either componentEither = getComponentDetails(componentId); if (componentEither.isRight()) { return Either.right(componentEither.right().value()); } - org.openecomp.sdc.be.model.Component storedComponent = componentEither.left().value(); + 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); + 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(); + Map> storedComponentCapabilities = storedComponent.getCapabilities(); if (org.apache.commons.collections.MapUtils.isNotEmpty(storedComponentCapabilities)) { CapabilityDefinition capabilityDefinitionToGetType = capabilityDefinitions.get(0); - if(Objects.isNull(capabilityDefinitionToGetType)) { + if (Objects.isNull(capabilityDefinitionToGetType)) { return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT)); } - capabilitiesListStoredInComponent - = getCapabilityStoredInComponentByType(capabilityDefinitionToGetType + capabilitiesListStoredInComponent = getCapabilityStoredInComponentByType(capabilityDefinitionToGetType .getType(), storedComponentCapabilities); } List capabilitiesDefListToUpdate = new ArrayList<>(); @@ -186,54 +205,57 @@ public class CapabilitiesBusinessLogic extends BaseBusinessLogic { 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)); + 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())) + 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())); + capabilityDefinitionToUpdate, storedComponent)).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); + = handleCapabilityTypeUpdateWhenNewTypeExist(storedComponent, storedComponent + .getCapabilities(), capabilitiesToReturn, capabilityDefinitionToUpdate); if (capTypeUpdateEither.isRight()) { return Either.right(capTypeUpdateEither.right().value()); } capabilitiesDefListToUpdate = capTypeUpdateEither.left().value(); } } - result = capabilitiesOperation.updateCapabilities(componentId, - capabilitiesDefListToUpdate); + result = capabilitiesOperation.updateCapabilities(componentId, capabilitiesDefListToUpdate); } else { Either, ResponseFormat> capabilityDefinitionToDelete - = handleCapabilityTypeUpdateWhenNewTypeNotExist(capabilityDefinitions, - storedComponent, storedComponentCapabilities); + = handleCapabilityTypeUpdateWhenNewTypeNotExist(capabilityDefinitions, storedComponent, + storedComponentCapabilities); if (capabilityDefinitionToDelete != null) { return capabilityDefinitionToDelete; } - capabilitiesToReturn = capabilityDefinitions.stream() - .map(capabilityDefinition -> initiateNewCapability( - storedComponent, capabilityDefinition)) - .collect(Collectors.toList()); + 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()), "")); + return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(result + .right().value(), storedComponent.getComponentType()), "")); + } + Map propertiesMap = + getCapabilitiesPropertiesDataDefinitionMap(capabilityDefinitions); + if (MapUtils.isNotEmpty(propertiesMap)) { + StorageOperationStatus storageOperationStatus = capabilitiesOperation + .createOrUpdateCapabilityProperties(componentId, propertiesMap); + if (storageOperationStatus != StorageOperationStatus.OK) { + titanDao.rollback(); + return Either.right(componentsUtils.getResponseFormat(storageOperationStatus)); + } } - titanDao.commit(); return Either.left(capabilitiesToReturn); } catch (Exception e) { @@ -249,30 +271,36 @@ public class CapabilitiesBusinessLogic extends BaseBusinessLogic { } private Either, ResponseFormat> handleCapabilityTypeUpdateWhenNewTypeExist( - org.openecomp.sdc.be.model.Component storedComponent, Map> storedComponentCapabilities, + 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() + 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())); + return Either.right(componentsUtils.getResponseFormat(ActionStatus.CAPABILITY_NOT_FOUND, + storedComponent.getUniqueId())); } CapabilityDefinition capabilityDefinitionToDelete = definitionOptional.get(); - capabilitiesListStoredInComponent = getCapabilityStoredInComponentByType( - capabilityDefinitionToUpdate.getType(), storedComponentCapabilities); + 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())); } + StorageOperationStatus deleteStorageOperationStatus = capabilitiesOperation + .deleteCapabilityProperties(storedComponent, buildCapPropKey(capabilityDefinitionToDelete)); + if (deleteStorageOperationStatus != StorageOperationStatus.OK) { + titanDao.rollback(); + return Either.right(componentsUtils.getResponseFormat(deleteStorageOperationStatus)); + } capabilitiesToReturn.add(initiateNewCapability(storedComponent, capabilityDefinitionToUpdate)); capabilitiesDefsToCreateOrUpdate.addAll(capabilitiesToReturn); @@ -282,21 +310,20 @@ public class CapabilitiesBusinessLogic extends BaseBusinessLogic { private Either, ResponseFormat> handleCapabilityTypeUpdateWhenNewTypeNotExist( List capabilityDefinitions, - org.openecomp.sdc.be.model.Component storedComponent, + Component storedComponent, Map> storedComponentCapabilities) { for (CapabilityDefinition capabilityDefinitionToUpdate : capabilityDefinitions) { - Optional definitionOptional = storedComponentCapabilities.values() - .stream().flatMap(Collection::stream) - .filter(capabilityDefinition -> capabilityDefinition.getUniqueId() + 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())); + return Either.right(componentsUtils.getResponseFormat(ActionStatus + .CAPABILITY_NOT_FOUND, storedComponent.getUniqueId())); } CapabilityDefinition capabilityDefinitionToDelete = definitionOptional.get(); - Boolean isCapabilityUsedInServiceComposition = isCapabilityUsedInServiceComposition( - capabilityDefinitionToDelete, storedComponent); + Boolean isCapabilityUsedInServiceComposition = isCapabilityUsedInServiceComposition(capabilityDefinitionToDelete, + storedComponent); if (isCapabilityUsedInServiceComposition) { LOGGER.error("Capability {} can't be edited, since it is used in service composition", capabilityDefinitionToDelete.getUniqueId()); @@ -305,125 +332,88 @@ public class CapabilitiesBusinessLogic extends BaseBusinessLogic { capabilityDefinitionToDelete.getName())); } Either, StorageOperationStatus> deleteCapabilityEither - = deleteCapability(storedComponent, storedComponentCapabilities, - capabilityDefinitionToDelete); + = deleteCapability(storedComponent, storedComponentCapabilities, capabilityDefinitionToDelete); if (deleteCapabilityEither.isRight()) { titanDao.rollback(); return Either.right(componentsUtils.getResponseFormat(deleteCapabilityEither.right().value())); } + StorageOperationStatus deleteStorageOperationStatus = capabilitiesOperation + .deleteCapabilityProperties(storedComponent, buildCapPropKey(capabilityDefinitionToDelete)); + if (deleteStorageOperationStatus != StorageOperationStatus.OK) { + titanDao.rollback(); + return Either.right(componentsUtils.getResponseFormat(deleteStorageOperationStatus)); + } } return null; } - public Either getCapability( - String componentId, - String capabilityToGet, User user, boolean lock) { + public Either getCapability(String componentId, String capabilityToGet, + User user, boolean lock) { validateUserExists(user.getUserId(), GET_CAPABILITIES, true); - Either componentEither - = getComponentDetails(componentId); + Either componentEither = getComponentDetails(componentId); if (componentEither.isRight()) { return Either.right(componentEither.right().value()); } - org.openecomp.sdc.be.model.Component storedComponent = componentEither.left().value(); + Component storedComponent = componentEither.left().value(); - Either lockResult = lockComponentResult(lock, - storedComponent, GET_CAPABILITIES); + 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)); + Either getCapabilityDefinitionEither = + getCapabilityDefinition(capabilityToGet, storedComponent); + if (getCapabilityDefinitionEither.isRight()) { + return Either.right(getCapabilityDefinitionEither.right().value()); } - - 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); + return Either.left(getCapabilityDefinitionEither.left().value()); } catch (Exception e) { LOGGER.error(EXCEPTION_OCCURRED_DURING_CAPABILITIES, "get", e); - return Either.right(componentsUtils.getResponseFormat( - ActionStatus.CAPABILITY_NOT_FOUND, componentId)); + 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())); + NodeTypeEnum.getByNameIgnoreCase(storedComponent.getComponentType().getValue())); } } } - public Either deleteCapability( - String componentId, String capabilityIdToDelete, User user, - boolean lock) { + private Either getCapabilityDefinition(String capabilityIdToGet, + Component storedComponent) { + List capabilityDefinitions = storedComponent.getCapabilities().values() + .stream().flatMap(Collection::stream).collect(Collectors.toList()); + if (capabilityDefinitions.isEmpty()) { + return Either.right(componentsUtils.getResponseFormat(ActionStatus.CAPABILITY_NOT_FOUND, + storedComponent.getUniqueId())); + } + CapabilityDefinition capabilityDefinitionToReturn; + Optional capabilityDefinitionOptional = capabilityDefinitions.stream() + .filter(capabilityDefinition -> capabilityDefinition.getUniqueId().equals(capabilityIdToGet)).findAny(); + if (capabilityDefinitionOptional.isPresent()) { + capabilityDefinitionToReturn = capabilityDefinitionOptional.get(); + } else { + return Either.right(componentsUtils.getResponseFormat(ActionStatus.CAPABILITY_NOT_FOUND, + storedComponent.getUniqueId())); + } + + return Either.left(capabilityDefinitionToReturn); + } + + public Either deleteCapability(String componentId, String capabilityIdToDelete, + User user, boolean lock) { validateUserExists(user.getUserId(), DELETE_CAPABILITIES, true); - Either componentEither - = getComponentDetails(componentId); + Either componentEither = getComponentDetails(componentId); if (componentEither.isRight()) { return Either.right(componentEither.right().value()); } - org.openecomp.sdc.be.model.Component storedComponent = componentEither.left().value(); + Component storedComponent = componentEither.left().value(); - Either lockResult = lockComponentResult(lock, - storedComponent, DELETE_CAPABILITIES); + 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); + return deleteCapability(capabilityIdToDelete, storedComponent); } catch (Exception e) { LOGGER.error(EXCEPTION_OCCURRED_DURING_CAPABILITIES, "delete", e); titanDao.rollback(); @@ -436,16 +426,61 @@ public class CapabilitiesBusinessLogic extends BaseBusinessLogic { } } - 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); + private Either deleteCapability(String capabilityIdToDelete, + Component storedComponent) { + Map> storedComponentCapabilities = storedComponent.getCapabilities(); + if (storedComponentCapabilities.isEmpty()) { + return Either.right(componentsUtils.getResponseFormat(ActionStatus.CAPABILITY_NOT_FOUND, storedComponent.getUniqueId())); } + Either capabilityDefinitionToDeleteEither = + getAndValidateCapabilitiesToDelete(storedComponent, storedComponentCapabilities, capabilityIdToDelete); + + if(capabilityDefinitionToDeleteEither.isRight()) { + return Either.right(capabilityDefinitionToDeleteEither.right().value()); + } + Either, StorageOperationStatus> result = deleteCapability(storedComponent, + storedComponentCapabilities, capabilityDefinitionToDeleteEither.left().value()); + 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(capabilityDefinitionToDeleteEither.left().value()); + } + + private Either getAndValidateCapabilitiesToDelete(Component storedComponent, + Map> storedComponentCapabilities, + String capabilityIdToDelete) { + + 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, storedComponent.getUniqueId())); + } + 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())); + } + + return Either.left(capabilityDefinitionToDelete); + } + private Either, StorageOperationStatus> deleteCapability(Component storedComponent, + Map> storedComponentCapabilities, + CapabilityDefinition capabilityDefinitionToDelete) { + + List capabilitiesListStoredInComponent = + getCapabilityStoredInComponentByType(capabilityDefinitionToDelete.getType(), storedComponentCapabilities); capabilitiesListStoredInComponent.removeIf(capabilityDefinition -> capabilityDefinition.getUniqueId().equals(capabilityDefinitionToDelete.getUniqueId())); Either, StorageOperationStatus> result; @@ -461,34 +496,35 @@ public class CapabilitiesBusinessLogic extends BaseBusinessLogic { result = capabilitiesOperation.updateCapabilities(storedComponent.getUniqueId(), capabilitiesListStoredInComponent); } + if (result.isLeft()) { + StorageOperationStatus deleteStorageOperationStatus = capabilitiesOperation + .deleteCapabilityProperties(storedComponent, buildCapPropKey(capabilityDefinitionToDelete)); + if (deleteStorageOperationStatus != StorageOperationStatus.OK) { + result = Either.right(deleteStorageOperationStatus); + } + } return result; } - private Either getComponentDetails( - String componentId) { + private Either getComponentDetails(String componentId) { ComponentParametersView filter = new ComponentParametersView(true); filter.setIgnoreCapabilities(false); filter.setIgnoreCapabiltyProperties(false); - Either - componentStorageOperationStatusEither = toscaOperationFacade - .getToscaElement(componentId, filter); + 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.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) { + private Either lockComponentResult(boolean lock, Component component, String action) { if (lock) { - Either lockResult = lockComponent(component.getUniqueId(), - component, action); + Either lockResult = lockComponent(component.getUniqueId(), component, action); if (lockResult.isRight()) { LOGGER.debug(FAILED_TO_LOCK_COMPONENT_RESPONSE_IS, component.getName(), lockResult.right().value().getFormattedMessage()); @@ -499,19 +535,14 @@ public class CapabilitiesBusinessLogic extends BaseBusinessLogic { return Either.left(true); } - private List getCapabilityStoredInComponentByType( - String capabilityType, Map 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); - + Optional>> entryOptional = capabilities.entrySet().stream() + .filter(map -> map.getKey().equals(capabilityType)).findFirst(); + return entryOptional.map(Map.Entry::getValue).orElse(Collections.emptyList()); } - private CapabilityDefinition initiateNewCapability( - org.openecomp.sdc.be.model.Component component, - CapabilityDefinition capabilityDefinition) { + private CapabilityDefinition initiateNewCapability(Component component, CapabilityDefinition capabilityDefinition) { if (StringUtils.isEmpty(capabilityDefinition.getUniqueId())) capabilityDefinition.setUniqueId(UUID.randomUUID().toString()); if (StringUtils.isEmpty(capabilityDefinition.getOwnerId())) @@ -519,36 +550,58 @@ public class CapabilitiesBusinessLogic extends BaseBusinessLogic { if (StringUtils.isEmpty(capabilityDefinition.getOwnerName())) capabilityDefinition.setOwnerName(component.getName()); capabilityDefinition.setLeftOccurrences(capabilityDefinition.getMaxOccurrences()); + List capabilityProperties = capabilityDefinition.getProperties(); + initiateProperties(capabilityDefinition, capabilityProperties); return capabilityDefinition; } + private void initiateProperties(CapabilityDefinition capabilityDefinition, + List capabilityProperties) { + if (CollectionUtils.isNotEmpty(capabilityProperties)) { + capabilityProperties.stream().filter(prop -> prop != null && StringUtils.isEmpty(prop.getUniqueId())) + .forEach(propDef -> { + String uid = UniqueIdBuilder.buildRequirementUid(capabilityDefinition.getUniqueId(), propDef.getName()); + propDef.setUniqueId(uid); + propDef.setParentUniqueId(capabilityDefinition.getUniqueId()); + }); + } + } + private CapabilityDefinition updateCapability(CapabilityDefinition storedCapability, - CapabilityDefinition capabilityToUpdate) { + CapabilityDefinition capabilityToUpdate, Component component) { storedCapability.setName(capabilityToUpdate.getName()); storedCapability.setDescription(capabilityToUpdate.getDescription()); storedCapability.setType(capabilityToUpdate.getType()); storedCapability.setValidSourceTypes(capabilityToUpdate.getValidSourceTypes()); storedCapability.setMinOccurrences(capabilityToUpdate.getMinOccurrences()); storedCapability.setMaxOccurrences(capabilityToUpdate.getMaxOccurrences()); + if (!storedCapability.getType().equals(capabilityToUpdate.getType())) { + List capabilityProperties = capabilityToUpdate.getProperties(); + initiateProperties(capabilityToUpdate, capabilityProperties); + storedCapability.setProperties(capabilityToUpdate.getProperties()); + } + if (!storedCapability.getName().equals(capabilityToUpdate.getName())) { + StorageOperationStatus deleteStorageOperationStatus = capabilitiesOperation + .deleteCapabilityProperties(component, buildCapPropKey(storedCapability)); + if (deleteStorageOperationStatus != StorageOperationStatus.OK) { + titanDao.rollback(); + } + } return storedCapability; } - private Boolean isCapabilityUsedInServiceComposition( - CapabilityDefinition capabilityDefinition, - org.openecomp.sdc.be.model.Component component) { - Either, StorageOperationStatus> - componentList = toscaOperationFacade + private Boolean isCapabilityUsedInServiceComposition(CapabilityDefinition capabilityDefinition, 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())); + .getComponentInstancesRelations().stream()).flatMap(requirementCapabilityRelDef -> + requirementCapabilityRelDef.getRelationships().stream()).anyMatch(capabilityRequirementRelationship -> + capabilityRequirementRelationship.getRelation().getCapabilityUid().equals(capabilityDefinition.getUniqueId())); } public Either, ResponseFormat> getAllCapabilityTypes() { @@ -557,17 +610,38 @@ public class CapabilitiesBusinessLogic extends BaseBusinessLogic { 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); + 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); + 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()); } + + private Map getCapabilitiesPropertiesDataDefinitionMap( + List capabilityDefinitions) { + CapabilityDefinition capabilityDefinitionToAddOrUpdateCapProp = capabilityDefinitions.get(0); + List componentInstanceProperties = null; + if (Objects.nonNull(capabilityDefinitionToAddOrUpdateCapProp)) { + componentInstanceProperties = capabilityDefinitionToAddOrUpdateCapProp.getProperties(); + } + Map propertiesMap = new HashMap<>(); + if (CollectionUtils.isNotEmpty(componentInstanceProperties)) { + MapPropertiesDataDefinition dataToCreate = new MapPropertiesDataDefinition(); + for (ComponentInstanceProperty cip : componentInstanceProperties) { + dataToCreate.put(cip.getName(), new PropertyDataDefinition(cip)); + } + propertiesMap.put(buildCapPropKey(capabilityDefinitionToAddOrUpdateCapProp), dataToCreate); + } + return propertiesMap; + } + + private String buildCapPropKey(CapabilityDefinition capabilityDefinitionToAddOrUpdateCapProp) { + return capabilityDefinitionToAddOrUpdateCapProp.getType() + ModelConverter.CAP_PROP_DELIM + + capabilityDefinitionToAddOrUpdateCapProp.getName(); + } } diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ComponentInstanceBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ComponentInstanceBusinessLogic.java index 3bae240a67..71b125737e 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ComponentInstanceBusinessLogic.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ComponentInstanceBusinessLogic.java @@ -20,26 +20,7 @@ package org.openecomp.sdc.be.components.impl; -import static org.openecomp.sdc.be.components.property.GetInputUtils.isGetInputValueForInput; - import com.google.common.collect.Sets; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Objects; -import java.util.Optional; -import java.util.Set; -import java.util.UUID; -import java.util.function.BiConsumer; -import java.util.stream.Collectors; - import fj.data.Either; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; @@ -49,7 +30,7 @@ import org.openecomp.sdc.be.components.impl.instance.ComponentInstanceChangeOper import org.openecomp.sdc.be.components.impl.utils.DirectivesUtils; import org.openecomp.sdc.be.components.merge.instance.ComponentInstanceMergeDataBusinessLogic; import org.openecomp.sdc.be.components.merge.instance.DataForMergeHolder; -import org.openecomp.sdc.be.components.utils.ProxyServicePropertiesUtils; +import org.openecomp.sdc.be.components.utils.PropertiesUtils; import org.openecomp.sdc.be.components.validation.ComponentValidations; import org.openecomp.sdc.be.config.BeEcompErrorManager; import org.openecomp.sdc.be.config.BeEcompErrorManager.ErrorSeverity; @@ -86,6 +67,7 @@ import org.openecomp.sdc.be.model.GroupDefinition; import org.openecomp.sdc.be.model.InputDefinition; import org.openecomp.sdc.be.model.InterfaceDefinition; import org.openecomp.sdc.be.model.LifecycleStateEnum; +import org.openecomp.sdc.be.model.PolicyDefinition; import org.openecomp.sdc.be.model.PropertyDefinition; import org.openecomp.sdc.be.model.PropertyDefinition.PropertyNames; import org.openecomp.sdc.be.model.RelationshipInfo; @@ -94,23 +76,6 @@ 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.ComponentInstancePropInput; -import org.openecomp.sdc.be.model.LifecycleStateEnum; -import org.openecomp.sdc.be.model.ArtifactDefinition; -import org.openecomp.sdc.be.model.DataTypeDefinition; -import org.openecomp.sdc.be.model.PropertyDefinition; -import org.openecomp.sdc.be.model.GroupDefinition; -import org.openecomp.sdc.be.model.InputDefinition; -import org.openecomp.sdc.be.model.InterfaceDefinition; -import org.openecomp.sdc.be.model.LifecycleStateEnum; -import org.openecomp.sdc.be.model.PolicyDefinition; -import org.openecomp.sdc.be.model.PropertyDefinition; -import org.openecomp.sdc.be.model.PropertyDefinition.PropertyNames; -import org.openecomp.sdc.be.model.RequirementCapabilityRelDef; -import org.openecomp.sdc.be.model.ComponentInstance; -import org.openecomp.sdc.be.model.ComponentInstanceInput; -import org.openecomp.sdc.be.model.ComponentInstanceProperty; -import org.openecomp.sdc.be.model.PropertyDefinition.PropertyNames; import org.openecomp.sdc.be.model.jsontitan.operations.ForwardingPathOperation; import org.openecomp.sdc.be.model.jsontitan.operations.NodeFilterOperation; import org.openecomp.sdc.be.model.jsontitan.operations.ToscaOperationFacade; @@ -133,6 +98,25 @@ import org.openecomp.sdc.common.util.ValidationUtils; import org.openecomp.sdc.exception.ResponseFormat; import org.springframework.beans.factory.annotation.Autowired; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Objects; +import java.util.Optional; +import java.util.Set; +import java.util.UUID; +import java.util.function.BiConsumer; +import java.util.stream.Collectors; + +import static org.openecomp.sdc.be.components.property.GetInputUtils.isGetInputValueForInput; +import static org.openecomp.sdc.be.components.utils.PropertiesUtils.getPropertyCapabilityOfChildInstance; + @org.springframework.stereotype.Component public class ComponentInstanceBusinessLogic extends BaseBusinessLogic { @@ -417,7 +401,7 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic { } - resourceInstance.setProperties(ProxyServicePropertiesUtils.getProperties(service)); + resourceInstance.setProperties(PropertiesUtils.getProperties(service)); List serviceInputs = service.getInputs(); resourceInstance.setInputs(serviceInputs); @@ -1789,9 +1773,20 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic { try { for (ComponentInstanceProperty property: properties) { + String propertyParentUniqueId = property.getParentUniqueId(); Either updatedPropertyValue = updatePropertyObjectValue(property, false); - updatedPropertyValue.bimap(updatedValue -> updatePropertyOnContainerComponent(property,updatedValue, containerComponent, foundResourceInstance), - responseFormat -> Either.right(responseFormat)); + Optional + capPropDefinition = getPropertyCapabilityOfChildInstance(propertyParentUniqueId, foundResourceInstance.getCapabilities()); + if(capPropDefinition.isPresent()) { + updatedPropertyValue + .bimap(updatedValue -> updateCapabilityPropFromUpdateInstProp(property, updatedValue, + containerComponent, foundResourceInstance, capPropDefinition.get().getType(), + capPropDefinition.get().getName()), Either::right); + } + else { + updatedPropertyValue.bimap(updatedValue -> updatePropertyOnContainerComponent(property, updatedValue, + containerComponent, foundResourceInstance), Either::right); + } } Either updateContainerRes = toscaOperationFacade.updateComponentInstanceMetadataOfTopologyTemplate(containerComponent); @@ -1814,21 +1809,71 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic { } } - private ResponseFormat updateCapabilityPropertyOnContainerComponent(ComponentInstanceProperty property, String newValue, Component containerComponent, ComponentInstance foundResourceInstance, + private ResponseFormat updateCapabilityPropertyOnContainerComponent(ComponentInstanceProperty property, + String newValue, Component containerComponent, ComponentInstance foundResourceInstance, String capabilityType, String capabilityName) { String componentInstanceUniqueId = foundResourceInstance.getUniqueId(); - StringBuilder sb = new StringBuilder(componentInstanceUniqueId); - sb.append(ModelConverter.CAP_PROP_DELIM).append(property.getOwnerId()).append(ModelConverter.CAP_PROP_DELIM).append(capabilityType).append(ModelConverter.CAP_PROP_DELIM).append(capabilityName); + StringBuffer sb = new StringBuffer(componentInstanceUniqueId); + sb.append(ModelConverter.CAP_PROP_DELIM).append(property.getOwnerId()).append(ModelConverter.CAP_PROP_DELIM) + .append(capabilityType).append(ModelConverter.CAP_PROP_DELIM).append(capabilityName); String capKey = sb.toString(); - Map> capabilities = Optional.ofNullable(foundResourceInstance.getCapabilities()) - .orElse(Collections.emptyMap()); - List capPerType = Optional.ofNullable(capabilities.get(capabilityType)).orElse(Collections.emptyList()); - Optional cap = capPerType.stream().filter(c -> c.getName().equals(capabilityName)).findAny(); + ResponseFormat actionStatus = updateCapPropOnContainerComponent(property, newValue, containerComponent, + foundResourceInstance, capabilityType, capabilityName, componentInstanceUniqueId, capKey); + if (actionStatus != null) { + return actionStatus; + } + + return componentsUtils.getResponseFormat(ActionStatus.OK); + } + + private ResponseFormat updateCapabilityPropFromUpdateInstProp(ComponentInstanceProperty property, + String newValue, Component containerComponent, + ComponentInstance foundResourceInstance, + String capabilityType, String capabilityName) { + String componentInstanceUniqueId = foundResourceInstance.getUniqueId(); + Either getComponentRes = + toscaOperationFacade.getToscaFullElement(foundResourceInstance.getComponentUid()); + if(getComponentRes.isRight()) { + return componentsUtils.getResponseFormat(getComponentRes.right().value()); + } + String propOwner; + if(!PropertiesUtils.isNodeServiceProxy(getComponentRes.left().value())) { + propOwner = componentInstanceUniqueId; + } else { + propOwner = foundResourceInstance.getSourceModelUid(); + } + StringBuffer sb = new StringBuffer(componentInstanceUniqueId); + + sb.append(ModelConverter.CAP_PROP_DELIM).append(propOwner).append(ModelConverter.CAP_PROP_DELIM) + .append(capabilityType).append(ModelConverter.CAP_PROP_DELIM).append(capabilityName); + String capKey = sb.toString(); + + ResponseFormat actionStatus = updateCapPropOnContainerComponent(property, newValue, containerComponent, + foundResourceInstance, capabilityType, capabilityName, componentInstanceUniqueId, capKey); + if (actionStatus != null) { + return actionStatus; + } + + return componentsUtils.getResponseFormat(ActionStatus.OK); + } + + private ResponseFormat updateCapPropOnContainerComponent(ComponentInstanceProperty property, String newValue, + Component containerComponent, + ComponentInstance foundResourceInstance, + String capabilityType, String capabilityName, + String componentInstanceUniqueId, String capKey) { + Map> capabilities = + Optional.ofNullable(foundResourceInstance.getCapabilities()).orElse(Collections.emptyMap()); + List capPerType = + Optional.ofNullable(capabilities.get(capabilityType)).orElse(Collections.EMPTY_LIST); + Optional cap = + capPerType.stream().filter(c -> c.getName().equals(capabilityName)).findAny(); if (cap.isPresent()) { List capProperties = cap.get().getProperties(); if (capProperties != null) { - Optional instanceProperty = capProperties.stream().filter(p -> p.getUniqueId().equals(property.getUniqueId())).findAny(); + Optional instanceProperty = + capProperties.stream().filter(p -> p.getUniqueId().equals(property.getUniqueId())).findAny(); StorageOperationStatus status; if (instanceProperty.isPresent()) { instanceProperty.get().setValue(newValue); @@ -1836,9 +1881,11 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic { path.add(componentInstanceUniqueId); path.add(capKey); instanceProperty.get().setPath(path); - status = toscaOperationFacade.updateComponentInstanceCapabiltyProperty(containerComponent, componentInstanceUniqueId, capKey, instanceProperty.get()); + status = toscaOperationFacade.updateComponentInstanceCapabiltyProperty(containerComponent, + componentInstanceUniqueId, capKey, instanceProperty.get()); if (status != StorageOperationStatus.OK) { - ActionStatus actionStatus = componentsUtils.convertFromStorageResponseForResourceInstanceProperty(status); + ActionStatus actionStatus = + componentsUtils.convertFromStorageResponseForResourceInstanceProperty(status); return componentsUtils.getResponseFormatForResourceInstanceProperty(actionStatus, ""); } @@ -1846,20 +1893,25 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic { } } } - - - return componentsUtils.getResponseFormat(ActionStatus.OK); + return null; } - private ResponseFormat updatePropertyOnContainerComponent(ComponentInstanceProperty property, String newValue, Component containerComponent, ComponentInstance foundResourceInstance) { - List instanceProperties = containerComponent.getComponentInstancesProperties().get(foundResourceInstance.getUniqueId()); - Optional instanceProperty = instanceProperties.stream().filter(p -> p.getUniqueId().equals(property.getUniqueId())).findAny(); + private ResponseFormat updatePropertyOnContainerComponent(ComponentInstanceProperty property, String newValue, + Component containerComponent, ComponentInstance foundResourceInstance) { + List instanceProperties = + containerComponent.getComponentInstancesProperties().get(foundResourceInstance.getUniqueId()); + Optional instanceProperty = + instanceProperties.stream().filter(p -> p.getUniqueId().equals(property.getUniqueId())).findAny(); StorageOperationStatus status; instanceProperty.get().setValue(newValue); if (instanceProperty.isPresent()) { - status = toscaOperationFacade.updateComponentInstanceProperty(containerComponent, foundResourceInstance.getUniqueId(), property); + status = toscaOperationFacade + .updateComponentInstanceProperty(containerComponent, foundResourceInstance.getUniqueId(), + property); } else { - status = toscaOperationFacade.addComponentInstanceProperty(containerComponent, foundResourceInstance.getUniqueId(), property); + status = toscaOperationFacade + .addComponentInstanceProperty(containerComponent, foundResourceInstance.getUniqueId(), + property); } if (status != StorageOperationStatus.OK) { ActionStatus actionStatus = componentsUtils.convertFromStorageResponseForResourceInstanceProperty(status); diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/InterfaceOperationBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/InterfaceOperationBusinessLogic.java index de2839f653..5cdaa6a590 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/InterfaceOperationBusinessLogic.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/InterfaceOperationBusinessLogic.java @@ -17,12 +17,15 @@ package org.openecomp.sdc.be.components.impl; +import static org.openecomp.sdc.be.components.utils.InterfaceOperationUtils.createMappedCapabilityPropertyDefaultValue; import static org.openecomp.sdc.be.components.utils.InterfaceOperationUtils.createMappedInputPropertyDefaultValue; import static org.openecomp.sdc.be.components.utils.InterfaceOperationUtils.createMappedOutputDefaultValue; import static org.openecomp.sdc.be.components.utils.InterfaceOperationUtils.getInterfaceDefinitionFromComponentByInterfaceId; import static org.openecomp.sdc.be.components.utils.InterfaceOperationUtils.getInterfaceDefinitionFromComponentByInterfaceType; import static org.openecomp.sdc.be.components.utils.InterfaceOperationUtils.getOperationFromInterfaceDefinition; import static org.openecomp.sdc.be.components.utils.InterfaceOperationUtils.isOperationInputMappedToComponentInput; +import static org.openecomp.sdc.be.components.utils.PropertiesUtils.getPropertyCapabilityFromAllCapProps; +import static org.openecomp.sdc.be.components.utils.PropertiesUtils.isCapabilityProperty; import static org.openecomp.sdc.be.tosca.utils.InterfacesOperationsToscaUtil.SELF; import com.google.gson.Gson; @@ -51,7 +54,9 @@ import org.openecomp.sdc.be.datatypes.elements.OperationDataDefinition; import org.openecomp.sdc.be.datatypes.elements.OperationInputDefinition; import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum; import org.openecomp.sdc.be.model.ArtifactDefinition; +import org.openecomp.sdc.be.model.CapabilityDefinition; import org.openecomp.sdc.be.model.ComponentInstanceInterface; +import org.openecomp.sdc.be.model.ComponentInstanceProperty; import org.openecomp.sdc.be.model.InputDefinition; import org.openecomp.sdc.be.model.InterfaceDefinition; import org.openecomp.sdc.be.model.Operation; @@ -459,11 +464,28 @@ public class InterfaceOperationBusinessLogic extends BaseBusinessLogic { private String getInputToscaDefaultValue(OperationInputDefinition input, org.openecomp.sdc.be.model.Component component) { - Map> defaultInputValue; + Map> defaultInputValue = null; if (isOperationInputMappedToComponentInput(input, component.getInputs())) { String propertyName = input.getInputId().substring(input.getInputId().indexOf('.') + 1); setParentPropertyTypeAndInputPath(input, component); defaultInputValue = createMappedInputPropertyDefaultValue(propertyName); + } else if (isCapabilityProperty(input.getInputId(), component).isPresent()) { + ComponentInstanceProperty instanceProperty = isCapabilityProperty(input.getInputId(), component).get(); + String parentPropertyId = instanceProperty.getParentUniqueId(); + Map> componentCapabilities = component.getCapabilities(); + if(MapUtils.isNotEmpty(componentCapabilities)) { + List capabilityDefinitionList = componentCapabilities.values().stream() + .flatMap(Collection::stream).filter(capabilityDefinition -> capabilityDefinition.getOwnerId() + .equals(component.getUniqueId())).collect(Collectors.toList()); + Optional propertyCapability = getPropertyCapabilityFromAllCapProps(parentPropertyId, + capabilityDefinitionList); + if (propertyCapability.isPresent()) { + String propertyName = instanceProperty.getName(); + defaultInputValue = createMappedCapabilityPropertyDefaultValue(propertyCapability.get().getName(), + propertyName); + } + } + } else { //Currently inputs can only be mapped to a declared input or an other operation outputs defaultInputValue = createMappedOutputDefaultValue(SELF, input.getInputId()); diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceBusinessLogic.java index d1bfcc8bba..a586e23da7 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceBusinessLogic.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceBusinessLogic.java @@ -22,6 +22,8 @@ package org.openecomp.sdc.be.components.impl; import static org.apache.commons.collections.CollectionUtils.isEmpty; import static org.apache.commons.collections.CollectionUtils.isNotEmpty; +import static org.openecomp.sdc.be.components.utils.ConsumptionUtils.handleConsumptionInputMappedToCapabilityProperty; +import static org.openecomp.sdc.be.components.utils.ConsumptionUtils.isAssignedValueFromValidType; import static org.openecomp.sdc.be.components.utils.InterfaceOperationUtils.getOperationOutputName; import static org.openecomp.sdc.be.components.utils.InterfaceOperationUtils.isOperationInputMappedToOtherOperationOutput; import static org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum.UPDATE_SERVICE_METADATA; @@ -64,6 +66,7 @@ import org.openecomp.sdc.be.components.impl.utils.NodeFilterConstraintAction; import org.openecomp.sdc.be.components.lifecycle.LifecycleChangeInfoWithAction; import org.openecomp.sdc.be.components.path.ForwardingPathValidator; import org.openecomp.sdc.be.components.utils.InterfaceOperationUtils; +import org.openecomp.sdc.be.components.utils.PropertiesUtils; import org.openecomp.sdc.be.components.validation.NodeFilterValidator; import org.openecomp.sdc.be.components.validation.ServiceDistributionValidation; import org.openecomp.sdc.be.config.BeEcompErrorManager; @@ -91,6 +94,7 @@ import org.openecomp.sdc.be.externalapi.servlet.representation.ServiceDistributi import org.openecomp.sdc.be.impl.ForwardingPathUtils; import org.openecomp.sdc.be.impl.WebAppContextWrapper; import org.openecomp.sdc.be.model.ArtifactDefinition; +import org.openecomp.sdc.be.model.CapabilityDefinition; import org.openecomp.sdc.be.model.Component; import org.openecomp.sdc.be.model.ComponentInstance; import org.openecomp.sdc.be.model.ComponentInstanceInterface; @@ -118,8 +122,6 @@ import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus; import org.openecomp.sdc.be.model.operations.impl.UniqueIdBuilder; import org.openecomp.sdc.be.model.operations.utils.ComponentValidationUtils; import org.openecomp.sdc.be.model.tosca.ToscaFunctions; -import org.openecomp.sdc.be.model.tosca.ToscaPropertyType; -import org.openecomp.sdc.be.model.tosca.validators.PropertyTypeValidator; import org.openecomp.sdc.be.resources.data.ComponentInstanceData; import org.openecomp.sdc.be.resources.data.ComponentMetadataData; import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum; @@ -475,12 +477,20 @@ public class ServiceBusinessLogic extends ComponentBusinessLogic { ServiceConsumptionSource sourceValue = ServiceConsumptionSource.getSourceValue(source); if(STATIC.equals(sourceValue)) { + // Validate constraint on input value + Either constraintValidationResult = + validateOperationInputConstraint(operationInputDefinition, consumptionValue, type); + + if (constraintValidationResult.isRight()) { + return Either.right(constraintValidationResult.right().value()); + } return handleConsumptionStaticValue(consumptionValue, type, operation, operationInputDefinition); } if (Objects.isNull(sourceValue)) { List propertyDefinitions; + Map> capabilities = null; String componentName; List outputs = null; if (source.equals(containerService.getUniqueId())) { @@ -505,6 +515,7 @@ public class ServiceBusinessLogic extends ComponentBusinessLogic { ComponentInstance componentInstance = getComponentInstance.get(); operationInputDefinition.setSource(componentInstance.getUniqueId()); propertyDefinitions = componentInstance.getProperties(); + capabilities = componentInstance.getCapabilities(); componentName = source.equals(serviceInstanceId) ? SELF : componentInstance.getName(); if (MapUtils.isNotEmpty(componentInstance.getInterfaces())) { Map componentInstanceInterfaces = @@ -522,7 +533,7 @@ public class ServiceBusinessLogic extends ComponentBusinessLogic { operationInputDefinition); } return handleConsumptionPropertyValue(operation, operationInputDefinition, - serviceConsumptionData, propertyDefinitions, outputs, consumptionValue, componentName); + serviceConsumptionData, propertyDefinitions, capabilities, outputs, componentName); } operationInputDefinition.setToscaPresentationValue(JsonPresentationFields.SOURCE, source); @@ -545,12 +556,14 @@ public class ServiceBusinessLogic extends ComponentBusinessLogic { private Either handleConsumptionPropertyValue( Operation operation, OperationInputDefinition operationInputDefinition, - ServiceConsumptionData serviceConsumptionData, List properties, - List outputs, String consumptionValue, String componentName) { + ServiceConsumptionData serviceConsumptionData, List properties,Map> capabilities, + List outputs, String componentName) { if (CollectionUtils.isEmpty(properties) && CollectionUtils.isEmpty(outputs)) { return Either.left(operation); } + String consumptionValue = serviceConsumptionData.getValue(); if (CollectionUtils.isNotEmpty(outputs) && isOperationInputMappedToOtherOperationOutput(getOperationOutputName(consumptionValue), outputs)) { @@ -558,10 +571,16 @@ public class ServiceBusinessLogic extends ComponentBusinessLogic { consumptionValue, componentName); } - if (CollectionUtils.isNotEmpty(properties)) { + if (CollectionUtils.isNotEmpty(properties) && PropertiesUtils.isNodeProperty(consumptionValue, properties)) { return handleConsumptionInputMappedToProperty(operation, operationInputDefinition, serviceConsumptionData, properties, componentName); } + + if (MapUtils.isNotEmpty(capabilities)) { + return handleConsumptionInputMappedToCapabilityProperty(operation, operationInputDefinition, + serviceConsumptionData, capabilities, componentName); + } + return Either.left(operation); } @@ -672,7 +691,9 @@ public class ServiceBusinessLogic extends ComponentBusinessLogic { ComponentInstanceProperty propertyDefinition = new ComponentInstanceProperty(); propertyDefinition.setType(operationInputDefinition.getParentPropertyType()); - inputDefinition.setProperties(Collections.singletonList(propertyDefinition)); + if (operationInputDefinition.getParentPropertyType() != null) { + inputDefinition.setProperties(Collections.singletonList(propertyDefinition)); + } return PropertyValueConstraintValidationUtil.getInstance() .validatePropertyConstraints(Collections.singletonList(inputDefinition), applicationDataTypeCache); @@ -719,25 +740,6 @@ public class ServiceBusinessLogic extends ComponentBusinessLogic { return Either.left(operation); } - - private boolean isAssignedValueFromValidType(String operationInputType, Object actualValue) { - if (actualValue instanceof String) { - // validate static value - ToscaPropertyType actualType = ToscaPropertyType.isValidType(operationInputType); - PropertyTypeValidator validator = actualType.getValidator(); - return validator.isValid((String)actualValue, operationInputType); - } else if (actualValue instanceof PropertyDefinition) { - // validate input / property value - String actualType = ((PropertyDefinition) actualValue).getType(); - return actualType.equalsIgnoreCase(operationInputType); - } else if (actualValue instanceof OperationOutputDefinition) { - // validate input / output value - String actualType = ((OperationOutputDefinition) actualValue).getType(); - return actualType.equalsIgnoreCase(operationInputType); - } - return false; - } - private void addGetInputValueToOperationInput(Operation operation, OperationInputDefinition operationInputDefinition, InputDefinition inputForValue) { 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 2ca6ca41cb..e9289de839 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 @@ -194,7 +194,7 @@ public class CertificationChangeTransition extends LifeCycleTransition { } } updateCalculatedCapabilitiesRequirements(componentAfterCertification); - updateCapReqOwnerId(componentAfterCertification); + updateCapReqPropertiesOwnerId(componentAfterCertification); result = Either.left(componentAfterCertification); return result; } finally { @@ -214,9 +214,9 @@ public class CertificationChangeTransition extends LifeCycleTransition { } - private void updateCapReqOwnerId(Component component) { + private void updateCapReqPropertiesOwnerId(Component component) { if(component.isTopologyTemplate() && ToscaUtils.isNotComplexVfc(component)) { - toscaOperationFacade.updateCapReqOwnerId(component.getUniqueId()); + toscaOperationFacade.updateCapReqPropertiesOwnerId(component.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 0c4464239e..33b625002f 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,7 +123,7 @@ public class CheckoutTransition extends LifeCycleTransition { } } handleCalculatedCapabilitiesRequirements(clonedComponent); - updateCapReqOwnerId(clonedComponent); + updateCapReqPropertiesOwnerId(clonedComponent); } } finally { @@ -149,9 +149,9 @@ public class CheckoutTransition extends LifeCycleTransition { } } - private void updateCapReqOwnerId(Component component) { + private void updateCapReqPropertiesOwnerId(Component component) { if(component.isTopologyTemplate() && ToscaUtils.isNotComplexVfc(component)) { - toscaOperationFacade.updateCapReqOwnerId(component.getUniqueId()); + toscaOperationFacade.updateCapReqPropertiesOwnerId(component.getUniqueId()); } } private StorageOperationStatus upgradeToLatestGenericData(Component clonedComponent) { diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/property/ComponentInstancePropertyDeclarator.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/property/ComponentInstancePropertyDeclarator.java index 973e5985f9..14ea9300fe 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/property/ComponentInstancePropertyDeclarator.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/property/ComponentInstancePropertyDeclarator.java @@ -8,8 +8,10 @@ import java.util.Map; import java.util.Optional; import org.apache.commons.collections.CollectionUtils; import org.openecomp.sdc.be.components.impl.ComponentInstanceBusinessLogic; +import org.openecomp.sdc.be.components.utils.PropertiesUtils; import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition; import org.openecomp.sdc.be.impl.ComponentsUtils; +import org.openecomp.sdc.be.model.CapabilityDefinition; import org.openecomp.sdc.be.model.Component; import org.openecomp.sdc.be.model.ComponentInstance; import org.openecomp.sdc.be.model.ComponentInstanceProperty; @@ -62,12 +64,35 @@ public class ComponentInstancePropertyDeclarator extends DefaultPropertyDeclarat @Override public StorageOperationStatus unDeclarePropertiesAsInputs(Component component, InputDefinition input) { - List componentInstancePropertiesDeclaredAsInput = componentInstanceBusinessLogic.getComponentInstancePropertiesByInputId(component, input.getUniqueId()); - if (CollectionUtils.isEmpty(componentInstancePropertiesDeclaredAsInput)) { - return StorageOperationStatus.OK; + + Optional propertyByInputId = PropertiesUtils.getPropertyByInputId(component, + input.getUniqueId()); + if(propertyByInputId.isPresent()) { + List capabilityPropertyDeclaredAsInput = + PropertiesUtils.getCapabilityProperty(propertyByInputId.get(), input.getUniqueId()); + capabilityPropertyDeclaredAsInput.forEach(cmptInstanceProperty -> prepareValueBeforeDeleteOfCapProp(input, + cmptInstanceProperty)); + + Optional propertyCapabilityOptional = PropertiesUtils.getPropertyCapabilityOfChildInstance( + capabilityPropertyDeclaredAsInput.get(0).getParentUniqueId(), component.getCapabilities()); + if(!propertyCapabilityOptional.isPresent()) { + return StorageOperationStatus.OK; + } + + return toscaOperationFacade.updateInstanceCapabilityProperty(component, input.getInstanceUniqueId(), + capabilityPropertyDeclaredAsInput.get(0), propertyCapabilityOptional.get() ); + } else { + List componentInstancePropertiesDeclaredAsInput = componentInstanceBusinessLogic + .getComponentInstancePropertiesByInputId(component, input.getUniqueId()); + if (CollectionUtils.isEmpty(componentInstancePropertiesDeclaredAsInput)) { + return StorageOperationStatus.OK; + } + componentInstancePropertiesDeclaredAsInput.forEach(cmptInstanceProperty -> prepareValueBeforeDelete(input, + cmptInstanceProperty, cmptInstanceProperty.getPath())); + return toscaOperationFacade.updateComponentInstanceProperties(component, + componentInstancePropertiesDeclaredAsInput.get(0).getComponentInstanceId(), + componentInstancePropertiesDeclaredAsInput); } - componentInstancePropertiesDeclaredAsInput.forEach(cmptInstanceProperty -> prepareValueBeforeDelete(input, cmptInstanceProperty, cmptInstanceProperty.getPath())); - return toscaOperationFacade.updateComponentInstanceProperties(component, componentInstancePropertiesDeclaredAsInput.get(0).getComponentInstanceId(), componentInstancePropertiesDeclaredAsInput); } @Override diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/property/DefaultPropertyDeclarator.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/property/DefaultPropertyDeclarator.java index 46c1c009bc..bdb79c71bb 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/property/DefaultPropertyDeclarator.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/property/DefaultPropertyDeclarator.java @@ -20,12 +20,14 @@ import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang.StringUtils; import org.json.simple.JSONObject; +import org.openecomp.sdc.be.components.utils.PropertiesUtils; import org.openecomp.sdc.be.dao.titan.TitanOperationStatus; import org.openecomp.sdc.be.datatypes.elements.GetInputValueDataDefinition; import org.openecomp.sdc.be.datatypes.elements.GetPolicyValueDataDefinition; import org.openecomp.sdc.be.datatypes.elements.PropertiesOwner; import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition; import org.openecomp.sdc.be.impl.ComponentsUtils; +import org.openecomp.sdc.be.model.CapabilityDefinition; import org.openecomp.sdc.be.model.Component; import org.openecomp.sdc.be.model.ComponentInstancePropInput; import org.openecomp.sdc.be.model.IComponentInstanceConnectedElement; @@ -44,6 +46,7 @@ public abstract class DefaultPropertyDeclarator, StorageOperationStatus> declarePropertiesAsInputs(Component component, PROPERTYOWNER propertiesOwner, List propsToDeclare) { - PropertiesDeclarationData inputsProperties = createInputsAndOverridePropertiesValues(component.getUniqueId(), propertiesOwner, propsToDeclare); + PropertiesDeclarationData inputsProperties = createInputsAndOverridePropertiesValues(component, propertiesOwner, propsToDeclare); return updatePropertiesValues(component, propertiesOwner.getUniqueId(), inputsProperties.getPropertiesToUpdate()) .left() .map(updatePropsRes -> inputsProperties.getInputsToCreate()); @@ -201,17 +204,17 @@ public abstract class DefaultPropertyDeclarator input); } - private PropertiesDeclarationData createInputsAndOverridePropertiesValues(String componentId, PROPERTYOWNER propertiesOwner, List propsToDeclare) { + private PropertiesDeclarationData createInputsAndOverridePropertiesValues(Component component, PROPERTYOWNER propertiesOwner, List propsToDeclare) { List declaredProperties = new ArrayList<>(); List createdInputs = propsToDeclare.stream() - .map(propInput -> declarePropertyInput(componentId, propertiesOwner, declaredProperties, propInput)) + .map(propInput -> declarePropertyInput(component, propertiesOwner, declaredProperties, propInput)) .collect(Collectors.toList()); return new PropertiesDeclarationData(createdInputs, null, declaredProperties); } - private InputDefinition declarePropertyInput(String componentId, PROPERTYOWNER propertiesOwner, List declaredProperties, ComponentInstancePropInput propInput) { + private InputDefinition declarePropertyInput(Component component, PROPERTYOWNER propertiesOwner, List declaredProperties, ComponentInstancePropInput propInput) { PropertyDataDefinition prop = resolveProperty(declaredProperties, propInput); - InputDefinition inputDefinition = createInput(componentId, propertiesOwner, propInput, prop); + InputDefinition inputDefinition = createInput(component, propertiesOwner, propInput, prop); PROPERTYTYPE declaredProperty = createDeclaredProperty(prop); if(!declaredProperties.contains(declaredProperty)){ declaredProperties.add(declaredProperty); @@ -220,16 +223,28 @@ public abstract class DefaultPropertyDeclarator propertyCapability = PropertiesUtils.getPropertyCapabilityOfChildInstance(propInput + .getParentUniqueId(), component.getCapabilities()); + if (propertyCapability.isPresent()) { + String capName = propertyCapability.get().getName(); + if(capName.contains(".")) { + capName = capName.replaceAll("\\.", UNDERSCORE); + } + generatedInputPrefix = generatedInputPrefix == null || generatedInputPrefix.isEmpty()? + capName : generatedInputPrefix + UNDERSCORE + capName; + } + String generatedInputName = generateInputName(generatedInputPrefix, propInput); log.debug("createInput: propOwner.uniqueId={}, propInput.parentUniqueId={}", propertiesOwner.getUniqueId(), propInput.getParentUniqueId()); - return createInputFromProperty(componentId, propertiesOwner, generatedInputName, propInput, prop); + return createInputFromProperty(component.getUniqueId(), propertiesOwner, generatedInputName, propInput, prop); } private String generateInputName(String inputName, ComponentInstancePropInput propInput) { @@ -259,7 +274,7 @@ public abstract class DefaultPropertyDeclarator prepareValueBeforeDelete(InputDefinition inputForDelete, PropertyDataDefinition inputValue, List pathOfComponentInstances) { + Either deleteEither = prepareValueBeforeDelete(inputForDelete, inputValue); + + Either findDefaultValue = propertyOperation.findDefaultValueFromSecondPosition(pathOfComponentInstances, inputValue.getUniqueId(), + (String) inputValue.getDefaultValue()); + if (findDefaultValue.isRight()) { + deleteEither = Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(DaoStatusConverter.convertTitanStatusToStorageStatus(findDefaultValue.right().value())))); + return deleteEither; + + } + String defaultValue = findDefaultValue.left().value(); + inputValue.setDefaultValue(defaultValue); + log.debug("The returned default value in ResourceInstanceProperty is {}", defaultValue); + return deleteEither; + } + + Either prepareValueBeforeDeleteOfCapProp(InputDefinition inputForDelete, + PropertyDataDefinition inputValue) { + Either deleteEither = prepareValueBeforeDelete(inputForDelete, inputValue); + inputValue.setDefaultValue(inputForDelete.getDefaultValue()); + log.debug("The returned default value in ResourceInstanceProperty is {}", inputForDelete.getDefaultValue()); + return deleteEither; + } + + private Either prepareValueBeforeDelete(InputDefinition inputForDelete, + PropertyDataDefinition inputValue) { Either deleteEither = Either.left(inputForDelete); String value = inputValue.getValue(); Map mappedToscaTemplate = (Map) new Yaml().load(value); @@ -456,36 +496,28 @@ public abstract class DefaultPropertyDeclarator " +result.right().value().toString()); //continue, don't break operation + if (result.isLeft()) { + modifiedMappedToscaTemplate = (Map) result.left().value(); + } else { + log.warn("Map cleanup failed -> " + result.right().value() + .toString()); //continue, don't break operation + } value = gson.toJson(modifiedMappedToscaTemplate); } inputValue.setValue(value); List getInputsValues = inputValue.getGetInputValues(); - if(getInputsValues != null && !getInputsValues.isEmpty()){ - Optional op = getInputsValues.stream().filter(gi -> gi.getInputId().equals(inputForDelete.getUniqueId())).findAny(); - if(op.isPresent()){ - getInputsValues.remove(op.get()); - } + if (getInputsValues != null && !getInputsValues.isEmpty()) { + Optional op = + getInputsValues.stream().filter(gi -> gi.getInputId().equals(inputForDelete.getUniqueId())) + .findAny(); + op.ifPresent(getInputsValues::remove); } inputValue.setGetInputValues(getInputsValues); - - Either findDefaultValue = propertyOperation.findDefaultValueFromSecondPosition(pathOfComponentInstances, inputValue.getUniqueId(), inputValue.getDefaultValue()); - if (findDefaultValue.isRight()) { - deleteEither = Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(DaoStatusConverter.convertTitanStatusToStorageStatus(findDefaultValue.right().value())))); - return deleteEither; - - } - String defaultValue = findDefaultValue.left().value(); - inputValue.setDefaultValue(defaultValue); - log.debug("The returned default value in ResourceInstanceProperty is {}", defaultValue); return deleteEither; } diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/utils/ConsumptionUtils.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/utils/ConsumptionUtils.java new file mode 100644 index 0000000000..e90bcfb567 --- /dev/null +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/utils/ConsumptionUtils.java @@ -0,0 +1,127 @@ +/* + * 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.utils; + +import com.google.gson.Gson; +import fj.data.Either; +import org.apache.commons.collections.CollectionUtils; +import org.openecomp.sdc.be.components.impl.ResponseFormatManager; +import org.openecomp.sdc.be.dao.api.ActionStatus; +import org.openecomp.sdc.be.datatypes.elements.OperationInputDefinition; +import org.openecomp.sdc.be.datatypes.elements.OperationOutputDefinition; +import org.openecomp.sdc.be.datatypes.enums.JsonPresentationFields; +import org.openecomp.sdc.be.model.CapabilityDefinition; +import org.openecomp.sdc.be.model.ComponentInstanceProperty; +import org.openecomp.sdc.be.model.Operation; +import org.openecomp.sdc.be.model.PropertyDefinition; +import org.openecomp.sdc.be.model.tosca.ToscaFunctions; +import org.openecomp.sdc.be.model.tosca.ToscaPropertyType; +import org.openecomp.sdc.be.model.tosca.validators.PropertyTypeValidator; +import org.openecomp.sdc.be.types.ServiceConsumptionData; +import org.openecomp.sdc.exception.ResponseFormat; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +public class ConsumptionUtils { + + private ConsumptionUtils() { + + } + + public static Either handleConsumptionInputMappedToCapabilityProperty( + Operation operation, + OperationInputDefinition operationInputDefinition, ServiceConsumptionData serviceConsumptionData, + Map> capabilities, String componentName) { + + List componentCapabilityDefinitions = capabilities.values().stream() + .flatMap(Collection::stream) + .collect(Collectors.toList()); + if (CollectionUtils.isEmpty(componentCapabilityDefinitions)) { + return Either.left(operation); + } + + for (CapabilityDefinition capabilityDefinition : componentCapabilityDefinitions) { + String capabilityName = capabilityDefinition.getName(); + List capabilityProperties = capabilityDefinition.getProperties(); + if (CollectionUtils.isEmpty(capabilityProperties)) { + continue; + } + for (ComponentInstanceProperty capabilityProperty : capabilityProperties) { + String capabilityPropertyName = capabilityProperty.getName(); + String capabilityPropertyIdentifier = capabilityName + "_" + capabilityPropertyName; + if (capabilityPropertyIdentifier.equals(serviceConsumptionData.getValue())) { + boolean isInputTypeSimilarToOperation = + isAssignedValueFromValidType(operationInputDefinition.getType(), capabilityProperty); + if (!isInputTypeSimilarToOperation) { + return Either.right(getResponseFormatManager().getResponseFormat( + ActionStatus.INVALID_CONSUMPTION_TYPE, operationInputDefinition.getType())); + } + addCapabilityPropertyToInputValue(componentName, capabilityName, operation, + operationInputDefinition, capabilityProperty); + } + } + } + return Either.left(operation); + } + + private static void addCapabilityPropertyToInputValue(String componentName, String capabilityName, Operation operation, + OperationInputDefinition operationInputDefinition, + PropertyDefinition capabilityProperty) { + + List getPropertyValues = new ArrayList<>(); + getPropertyValues.add(componentName); + getPropertyValues.add(capabilityName); + getPropertyValues.add(capabilityProperty.getName()); + + Map> getProperty = new HashMap<>(); + getProperty.put(ToscaFunctions.GET_PROPERTY.getFunctionName(), getPropertyValues); + + operationInputDefinition.setSourceProperty(capabilityProperty.getUniqueId()); + operation.getInputs().delete(operationInputDefinition); + operationInputDefinition.setToscaPresentationValue(JsonPresentationFields.GET_PROPERTY, + getPropertyValues); + operationInputDefinition.setValue((new Gson()).toJson(getProperty)); + operation.getInputs().add(operationInputDefinition); + } + + public static boolean isAssignedValueFromValidType(String operationInputType, Object actualValue) { + if (actualValue instanceof String) { + // validate static value + ToscaPropertyType actualType = ToscaPropertyType.isValidType(operationInputType); + PropertyTypeValidator validator = actualType.getValidator(); + return validator.isValid((String)actualValue, operationInputType); + } else if (actualValue instanceof PropertyDefinition) { + // validate input / property value + String actualType = ((PropertyDefinition) actualValue).getType(); + return actualType.equalsIgnoreCase(operationInputType); + } else if (actualValue instanceof OperationOutputDefinition) { + // validate input / output value + String actualType = ((OperationOutputDefinition) actualValue).getType(); + return actualType.equalsIgnoreCase(operationInputType); + } + return false; + } + + private static ResponseFormatManager getResponseFormatManager() { + return ResponseFormatManager.getInstance(); + } +} diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/utils/InterfaceOperationUtils.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/utils/InterfaceOperationUtils.java index 0ee6264f4d..38cdeb8d40 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/utils/InterfaceOperationUtils.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/utils/InterfaceOperationUtils.java @@ -87,14 +87,18 @@ public class InterfaceOperationUtils { } public static boolean isOperationInputMappedToComponentInput(OperationInputDefinition input, - List inputs) { + List inputs) { if (CollectionUtils.isEmpty(inputs)) { return false; } - return inputs.stream().anyMatch(inp -> inp.getUniqueId().equals(input.getInputId())) - || (input.getInputId().contains(".") - && inputs.stream().anyMatch(inp -> inp.getUniqueId().equals( - input.getInputId().substring(0, input.getInputId().lastIndexOf('.'))))) ; + + boolean matchedInput = inputs.stream().anyMatch(inp -> inp.getUniqueId().equals(input.getInputId())); + if (!matchedInput && input.getInputId().contains(".")) { + return inputs.stream() + .anyMatch(inp -> inp.getUniqueId() + .equals(input.getInputId().substring(0, input.getInputId().lastIndexOf('.')))); + } + return matchedInput; } public static boolean isOperationInputMappedToOtherOperationOutput(String outputName, @@ -119,6 +123,20 @@ public class InterfaceOperationUtils { return getPropertyMap; } + public static Map> createMappedCapabilityPropertyDefaultValue(String capabilityName, + String propertyName) { + Map> getPropertyMap = new HashMap<>(); + List values = new ArrayList<>(); + values.add(InterfacesOperationsToscaUtil.SELF); + values.add(capabilityName); + + if (Objects.nonNull(propertyName) && !propertyName.isEmpty()) { + values.addAll(Arrays.asList(propertyName.split("\\."))); + } + getPropertyMap.put(ToscaFunctions.GET_PROPERTY.getFunctionName(), values); + return getPropertyMap; + } + /** * Get the list of outputs of other operations of all the interfaces in the component. * @param currentOperationIdentifier Fully qualified operation name e.g. org.test.interfaces.node.lifecycle.Abc.stop diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/utils/PropertiesUtils.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/utils/PropertiesUtils.java new file mode 100644 index 0000000000..7bea8356a7 --- /dev/null +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/utils/PropertiesUtils.java @@ -0,0 +1,171 @@ +/* + * 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.utils; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; +import java.util.function.Function; +import java.util.function.Predicate; +import java.util.stream.Collectors; + +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.collections.MapUtils; +import org.openecomp.sdc.be.datatypes.elements.GetInputValueDataDefinition; +import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum; +import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum; +import org.openecomp.sdc.be.model.CapabilityDefinition; +import org.openecomp.sdc.be.model.Component; +import org.openecomp.sdc.be.model.ComponentInstanceProperty; +import org.openecomp.sdc.be.model.InputDefinition; +import org.openecomp.sdc.be.model.PropertyDefinition; +import org.openecomp.sdc.be.model.Resource; + +import static org.openecomp.sdc.be.components.property.GetInputUtils.isGetInputValueForInput; + +public class PropertiesUtils { + + private PropertiesUtils() { + //Hiding implicit default constructor + } + + public static List getProperties(Component service) { + List properties = service.getProperties(); + if (properties == null) { + properties = new ArrayList<>(); + } + Set serviceProperties = new HashSet<>(properties); + if (service.getInputs() != null) { + Set inputs = service.getInputs().stream().map(PropertyDefinition::new) + .collect(Collectors.toSet()); + serviceProperties.addAll(inputs); + } + serviceProperties = + serviceProperties.stream().filter(distinctByKey(PropertyDefinition::getName)).collect(Collectors.toSet()); + return new ArrayList<>(serviceProperties); + } + + public static Optional isCapabilityProperty(String propertyUniqueId, + Component containerComponent) { + + Optional> capPropertiesOptional = getCapProperties(containerComponent); + + if(capPropertiesOptional.isPresent()) { + return capPropertiesOptional.get().stream().filter(propertyDefinition -> + propertyDefinition.getUniqueId().equals(propertyUniqueId)).findAny(); + } else { + return Optional.empty(); + } + } + + private static Optional> getCapProperties(Component containerComponent) { + Map> componentCapabilities = containerComponent.getCapabilities(); + if(MapUtils.isEmpty(componentCapabilities)){ + return Optional.empty(); + } + List capabilityDefinitionList = componentCapabilities.values() + .stream().flatMap(Collection::stream).collect(Collectors.toList()); + if(CollectionUtils.isEmpty(capabilityDefinitionList)){ + return Optional.empty(); + } + List allComponentInstanceCapProperties= new ArrayList<>(); + capabilityDefinitionList.stream().filter(capabilityDefinition -> CollectionUtils.isNotEmpty(capabilityDefinition + .getProperties())).collect(Collectors.toList()).forEach(capabilityDefinition -> + allComponentInstanceCapProperties.addAll(capabilityDefinition.getProperties())); + return Optional.of(allComponentInstanceCapProperties); + } + + public static Optional getPropertyCapabilityOfChildInstance(String propertyParentUniqueId, + Map> + componentCapabilities) { + if(MapUtils.isEmpty(componentCapabilities)){ + return Optional.empty(); + } + List capabilityDefinitionList = componentCapabilities.values() + .stream().flatMap(Collection::stream).collect(Collectors.toList()); + if(CollectionUtils.isEmpty(capabilityDefinitionList)){ + return Optional.empty(); + } + return capabilityDefinitionList.stream() + .filter(capabilityDefinition -> capabilityDefinition.getUniqueId().equals(propertyParentUniqueId) && + capabilityDefinition.getPath().size() == 1) + .findAny(); + } + + public static Optional getPropertyCapabilityFromAllCapProps(String propertyParentUniqueId, + List + capabilityDefinitionList) { + return capabilityDefinitionList.stream() + .filter(capabilityDefinition -> capabilityDefinition.getUniqueId().equals(propertyParentUniqueId)) + .findAny(); + } + + public static boolean isNodeProperty(String propertyName, List properties) { + + return !CollectionUtils.isEmpty(properties) && properties.stream().anyMatch(property -> property.getName() + .equals(propertyName)); + } + + private static Predicate distinctByKey(Function keyExtractor) { + Set seen = new HashSet<>(); + return t -> seen.add(keyExtractor.apply(t)); + } + + public static Optional getPropertyByInputId(Component component, String inputId) { + List componentInputs = component.getInputs(); + if(CollectionUtils.isEmpty(componentInputs)) { + return Optional.empty(); + } + Optional inputDefinition = componentInputs.stream().filter(cip -> cip.getUniqueId() + .equals(inputId)).findFirst(); + if(!inputDefinition.isPresent()) { + return Optional.empty(); + } + Optional> capProperties = getCapProperties(component); + if(!capProperties.isPresent()) { + return Optional.empty(); + } + + return capProperties.get().stream().filter(capProp -> CollectionUtils.isNotEmpty(capProp.getGetInputValues()) && + capProp.getGetInputValues().stream().anyMatch(capPropInp -> capPropInp.getInputId().equals(inputId)) && + capProp.getUniqueId().equals(inputDefinition.get().getPropertyId())).findAny(); + } + + public static List getCapabilityProperty(ComponentInstanceProperty capabilityProperty, + String inputId) { + List resList = new ArrayList<>(); + List inputsValues = capabilityProperty.getGetInputValues(); + if (CollectionUtils.isNotEmpty(inputsValues) && inputsValues.stream().anyMatch(inputData -> + isGetInputValueForInput(inputData, inputId))) { + resList.add(capabilityProperty); + } + return resList; + } + + public static boolean isNodeServiceProxy(Component component) { + if (component.getComponentType().equals(ComponentTypeEnum.SERVICE)) { + return true; + } + Resource resource = (Resource) component; + ResourceTypeEnum resType = resource.getResourceType(); + return resType.equals(ResourceTypeEnum.ServiceProxy); + } +} diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/utils/ProxyServicePropertiesUtils.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/utils/ProxyServicePropertiesUtils.java deleted file mode 100644 index b9b7ab690f..0000000000 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/utils/ProxyServicePropertiesUtils.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * 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.utils; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.function.Function; -import java.util.function.Predicate; -import java.util.stream.Collectors; -import org.openecomp.sdc.be.model.Component; -import org.openecomp.sdc.be.model.PropertyDefinition; - -public class ProxyServicePropertiesUtils { - - private ProxyServicePropertiesUtils() { - } - - public static List getProperties(Component service) { - List properties = service.getProperties(); - if (properties == null) { - properties = new ArrayList<>(); - } - Set serviceProperties = new HashSet<>(properties); - if (service.getInputs() != null) { - Set inputs = service.getInputs().stream().map(input -> new PropertyDefinition(input)) - .collect(Collectors.toSet()); - serviceProperties.addAll(inputs); - } - serviceProperties = - serviceProperties.stream().filter(distinctByKey(PropertyDefinition::getName)).collect(Collectors.toSet()); - return new ArrayList<>(serviceProperties); - } - - public static Predicate distinctByKey(Function keyExtractor) { - Set seen = new HashSet<>(); - return t -> seen.add(keyExtractor.apply(t)); - } -} 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 index 726e9dff82..2c69ee5b38 100644 --- 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 @@ -46,8 +46,8 @@ public class CapabilitiesValidation { org.openecomp.sdc.be.model.Component component, boolean isUpdate) { for(CapabilityDefinition capabilityDefinition : capabilities) { - Either validateCapabilityResponse = validateCapability( - capabilityDefinition, component, isUpdate); + Either validateCapabilityResponse = validateCapability(capabilityDefinition, + component, isUpdate); if (validateCapabilityResponse.isRight()) { return validateCapabilityResponse; } @@ -77,13 +77,11 @@ public class CapabilitiesValidation { 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); } @@ -93,8 +91,7 @@ public class CapabilitiesValidation { String minOccurrences = capabilityDefinition.getMinOccurrences(); if(maxOccurrences != null && minOccurrences != null) { Either capabilityOccurrencesValidationEither = - validateOccurrences(responseFormatManager, minOccurrences, - maxOccurrences); + validateOccurrences(responseFormatManager, minOccurrences, maxOccurrences); if (capabilityOccurrencesValidationEither.isRight()) { return Either.right(capabilityOccurrencesValidationEither.right().value()); } @@ -163,32 +160,28 @@ public class CapabilitiesValidation { return Either.left(Boolean.TRUE); } - private Either isCapabilityNameEmpty( - ResponseFormatManager responseFormatManager, String capabilityName) { + 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); + ResponseFormat errorResponse = responseFormatManager.getResponseFormat(ActionStatus.CAPABILITY_NAME_MANDATORY); return Either.right(errorResponse); } return Either.left(Boolean.TRUE); } - private Either isCapabilityTypeEmpty( - ResponseFormatManager responseFormatManager, String capabilityType) { + 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); + 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 ) { + private Either validateOccurrences (ResponseFormatManager responseFormatManager, + String minOccurrences, String maxOccurrences ) { try { if (StringUtils.isNotEmpty(maxOccurrences) && "UNBOUNDED".equalsIgnoreCase(maxOccurrences) && Integer.parseInt(minOccurrences) >= 0) { @@ -211,38 +204,29 @@ public class CapabilitiesValidation { return Either.left(Boolean.TRUE); } - private Either validateCapabilityNameUnique( - CapabilityDefinition capabilityDefinition, - org.openecomp.sdc.be.model.Component component, - boolean isUpdate) { + 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())); + 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())) { + 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; } } @@ -252,8 +236,7 @@ public class CapabilitiesValidation { private Either isCapabilityNameRegexValid(ResponseFormatManager responseFormatManager, String capabilityName) { if (!isValidCapabilityName(capabilityName)) { - LOGGER.error("Capability name {} is invalid, Only alphanumeric chars, underscore and dot allowed", - 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); diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/validation/InterfaceOperationValidation.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/validation/InterfaceOperationValidation.java index 30d006f501..2e94139b2b 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/validation/InterfaceOperationValidation.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/validation/InterfaceOperationValidation.java @@ -19,6 +19,7 @@ package org.openecomp.sdc.be.components.validation; import static org.openecomp.sdc.be.components.utils.InterfaceOperationUtils.getOperationOutputName; import static org.openecomp.sdc.be.components.utils.InterfaceOperationUtils.getOtherOperationOutputsOfComponent; import static org.openecomp.sdc.be.components.utils.InterfaceOperationUtils.isOperationInputMappedToComponentInput; +import static org.openecomp.sdc.be.components.utils.PropertiesUtils.isCapabilityProperty; import com.google.common.collect.Sets; @@ -523,7 +524,8 @@ public class InterfaceOperationValidation { List inputListToscaDataDefinition = operation.getInputs().getListToscaDataDefinition(); for (OperationInputDefinition inputDefinition : inputListToscaDataDefinition) { - if (isOperationInputMappedToComponentInput(inputDefinition, component.getInputs())) { + if (isOperationInputMappedToComponentInput(inputDefinition, component.getInputs()) + || isCapabilityProperty(inputDefinition.getInputId(), component).isPresent()) { isOperationInputToInputPropertyMappingValid = true; } else { mappingName = inputDefinition.getInputId().contains(".") @@ -553,7 +555,7 @@ public class InterfaceOperationValidation { if (!isOperationInputToOtherOperationOutputMappingValid) { LOGGER.error("Interface operation input parameter property {} not found in component input properties or" - + " outputs of other operations.", mappingName); + + "capability properties or outputs of other operations.", mappingName); ResponseFormat inputResponse = responseFormatManager .getResponseFormat(ActionStatus.INTERFACE_OPERATION_INPUT_PROPERTY_NOT_FOUND_IN_COMPONENT, mappingName, component.getComponentType().getValue()); diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ServiceConsumptionServlet.java b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ServiceConsumptionServlet.java index 990e3bc356..9ce5674cc3 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ServiceConsumptionServlet.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ServiceConsumptionServlet.java @@ -16,6 +16,8 @@ package org.openecomp.sdc.be.servlets; +import static org.openecomp.sdc.be.tosca.utils.InterfacesOperationsToscaUtil.SELF; + import com.google.gson.Gson; import com.google.gson.JsonParseException; import com.jcabi.aspects.Loggable; @@ -26,6 +28,7 @@ import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.stream.Collectors; import fj.data.Either; import io.swagger.annotations.Api; @@ -200,7 +203,11 @@ public class ServiceConsumptionServlet extends BeGenericServlet { List toscaFunctionList = (List) consumptionValueName; String consumptionInputValue = null; if (ToscaFunctions.GET_PROPERTY.getFunctionName().equals(toscaFunction)) { - consumptionInputValue = String.valueOf(toscaFunctionList.get(1)); + String propertyValue = toscaFunctionList.stream() + .map(Object::toString) + .filter(val -> !val.equals(SELF)) + .collect(Collectors.joining("_")); + consumptionInputValue = String.valueOf(propertyValue); } else if (ToscaFunctions.GET_OPERATION_OUTPUT.getFunctionName().equals(toscaFunction)) { //Return full output name consumptionInputValue = diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/ToscaExportHandler.java b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/ToscaExportHandler.java index 127d6f67af..5cafec2bda 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/ToscaExportHandler.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/ToscaExportHandler.java @@ -1177,7 +1177,9 @@ public class ToscaExportHandler { } private boolean isRequirementBelongToOwner(RelationshipInfo reqAndRelationshipPair, RequirementDefinition requirement, String fromInstanceId, Component originComponent) { - return StringUtils.equals(requirement.getOwnerId(), reqAndRelationshipPair.getRequirementOwnerId()) || (isCvfc(originComponent) && StringUtils.equals(fromInstanceId, reqAndRelationshipPair.getRequirementOwnerId())); + return StringUtils.equals(requirement.getOwnerId(), reqAndRelationshipPair.getRequirementOwnerId()) + || (isCvfc(originComponent) && StringUtils.equals(fromInstanceId, reqAndRelationshipPair.getRequirementOwnerId()) + || StringUtils.equals(requirement.getOwnerId(), originComponent.getUniqueId())); } private boolean isCvfc(Component component) { diff --git a/catalog-be/src/main/resources/config/error-configuration.yaml b/catalog-be/src/main/resources/config/error-configuration.yaml index fe1153139f..adc467c913 100644 --- a/catalog-be/src/main/resources/config/error-configuration.yaml +++ b/catalog-be/src/main/resources/config/error-configuration.yaml @@ -2137,7 +2137,7 @@ errors: # %1 - Interface Operation input property name, component type INTERFACE_OPERATION_INPUT_PROPERTY_NOT_FOUND_IN_COMPONENT: { code: 404, - message: "Error: Interface operation input parameter property '%1' not found in '%2' input properties or outputs of other operations.", + message: "Error: Interface operation input parameter property '%1' not found in '%2' input properties, capability properties or outputs of other operations.", messageId: "SVC4708" } #---------SVC4709----------------------------- @@ -2274,4 +2274,19 @@ errors: code: 400, message: "Error: Property name contains invalid characters. It should have only letters, numbers and underscores.", messageId: "SVC4727" + } + +#---------SVC4728------------------------------ + FAILED_TO_CREATE_OR_UPDATE_CAPABILITY_PROPERTIES: { + code: 500, + message: "Error: Failed to create or update capabilities properties", + messageId: "SVC4728" + } + +#---------SVC4729------------------------------ + # %1 - resource Id + CAPABILITY_PROPERTIES_NOT_FOUND: { + code: 400, + message: "Error: Capability properties not found in the resource '%1'.", + messageId: "SVC4729" } \ No newline at end of file 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 index 393ef58d1d..55b87f41cf 100644 --- 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 @@ -30,11 +30,14 @@ 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.elements.SchemaDefinition; 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.Component; +import org.openecomp.sdc.be.model.ComponentInstanceProperty; import org.openecomp.sdc.be.model.ComponentParametersView; import org.openecomp.sdc.be.model.LifecycleStateEnum; import org.openecomp.sdc.be.model.RelationshipInfo; @@ -111,17 +114,17 @@ public class CapabilitiesBusinessLogicTest { .thenReturn(StorageOperationStatus.OK); //CapabilityOperation - when(capabilitiesValidation.validateCapabilities(anyCollection(), anyObject(), anyBoolean()) - ).thenReturn(Either.left(true)); + 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")))); + "0", "10")))); when(capabilitiesOperation.updateCapabilities(anyString(), anyObject())) .thenReturn(Either.left(createMockCapabilityListToReturn( createCapability("capName", "capDesc", "capType", "source1", - "0", "10")))); + "0", "10")))); when(capabilitiesOperation.deleteCapabilities( anyObject(), anyString())) .thenReturn(StorageOperationStatus.OK); when(mockTitanDao.commit()).thenReturn(TitanOperationStatus.OK); @@ -141,7 +144,7 @@ public class CapabilitiesBusinessLogicTest { public void shouldPassCreateCapabilitiesFirstTimeInComponentForHappyScenario(){ List capabilityDefinitions = createMockCapabilityListToReturn( createCapability("capName", "capDesc", "capType", "source1", - "0", "10")); + "0", "10")); Resource resource = createComponent(false); resource.setComponentType(ComponentTypeEnum.RESOURCE); validateUserRoles(Role.ADMIN, Role.DESIGNER); @@ -149,7 +152,7 @@ public class CapabilitiesBusinessLogicTest { .thenReturn(Either.left(resource)); Either, ResponseFormat> capabilities = capabilitiesBusinessLogicMock .createCapabilities(componentId, capabilityDefinitions, user, - "createCapabilities", true); + "createCapabilities", true); Assert.assertTrue(capabilities.isLeft()); Assert.assertTrue(capabilities.left().value().stream().anyMatch(capabilityDefinition -> capabilityDefinition.getName().equals("capName"))); @@ -159,7 +162,7 @@ public class CapabilitiesBusinessLogicTest { public void shouldPassCreateCapabilitiesForHappyScenario(){ List capabilityDefinitions = createMockCapabilityListToReturn( createCapability("capName2", "capDesc", "capType", "source1", - "0", "10")); + "0", "10")); Resource resource = createComponent(true); resource.setComponentType(ComponentTypeEnum.RESOURCE); validateUserRoles(Role.ADMIN, Role.DESIGNER); @@ -178,7 +181,7 @@ public class CapabilitiesBusinessLogicTest { public void shouldFailCreateCapabilitiesWhenOperationFailedInTitan(){ List capabilityDefinitions = createMockCapabilityListToReturn( createCapability("capName2", "capDesc", "capType", "source1", - "0", "10")); + "0", "10")); Resource resource = createComponent(true); resource.setComponentType(ComponentTypeEnum.RESOURCE); validateUserRoles(Role.ADMIN, Role.DESIGNER); @@ -190,7 +193,7 @@ public class CapabilitiesBusinessLogicTest { .thenReturn(Either.left(resource)); Either, ResponseFormat> capabilities = capabilitiesBusinessLogicMock .createCapabilities(componentId, capabilityDefinitions, user, - "createCapabilities", true); + "createCapabilities", true); Assert.assertTrue(capabilities.isRight()); } @@ -199,7 +202,7 @@ public class CapabilitiesBusinessLogicTest { List capabilityDefinitions = createMockCapabilityListToReturn( createCapability("capName", "capDesc updated", "capType", "source1", - "6", "11")); + "6", "11")); Resource resource = createComponent(true); resource.setComponentType(ComponentTypeEnum.RESOURCE); validateUserRoles(Role.ADMIN, Role.DESIGNER); @@ -220,7 +223,7 @@ public class CapabilitiesBusinessLogicTest { List capabilityDefinitions = createMockCapabilityListToReturn( createCapability("capName", "capDesc updated", "capTypeUpdate", "source1", - "6", "11")); + "6", "11")); Resource resource = createComponent(true); resource.setComponentType(ComponentTypeEnum.RESOURCE); validateUserRoles(Role.ADMIN, Role.DESIGNER); @@ -228,6 +231,8 @@ public class CapabilitiesBusinessLogicTest { .thenReturn(Either.left(resource)); when(toscaOperationFacade.getParentComponents(anyString())) .thenReturn(Either.right(StorageOperationStatus.NOT_FOUND)); + when((capabilitiesOperation.deleteCapabilityProperties(any(Component.class), anyString()))) + .thenReturn(StorageOperationStatus.OK); Either, ResponseFormat> capabilities = capabilitiesBusinessLogicMock .updateCapabilities(componentId, capabilityDefinitions, user, "updateCapabilities",true); @@ -241,7 +246,7 @@ public class CapabilitiesBusinessLogicTest { List capabilityDefinitions = createMockCapabilityListToReturn( createCapability("capName", "capDesc updated", "capTypeUpdate1", "source1", - "6", "11")); + "6", "11")); Resource resource = createComponent(true); resource.setComponentType(ComponentTypeEnum.RESOURCE); @@ -258,6 +263,8 @@ public class CapabilitiesBusinessLogicTest { .thenReturn(Either.left(resource)); when(toscaOperationFacade.getParentComponents(anyString())) .thenReturn(Either.right(StorageOperationStatus.NOT_FOUND)); + when((capabilitiesOperation.deleteCapabilityProperties(any(Component.class), anyString()))) + .thenReturn(StorageOperationStatus.OK); Either, ResponseFormat> capabilities = capabilitiesBusinessLogicMock .updateCapabilities(componentId, capabilityDefinitions, user, "updateCapabilities",true); @@ -267,10 +274,10 @@ public class CapabilitiesBusinessLogicTest { } @Test - public void shouldFailUpdateCapabilitiesWhenOperaitonFailedInTitan(){ + public void shouldFailUpdateCapabilitiesWhenOperationFailedInTitan(){ List capabilityDefinitions = createMockCapabilityListToReturn( createCapability("capName2", "capDesc", "capType", "source1", - "0", "10")); + "0", "10")); Resource resource = createComponent(true); resource.setComponentType(ComponentTypeEnum.RESOURCE); validateUserRoles(Role.ADMIN, Role.DESIGNER); @@ -296,6 +303,8 @@ public class CapabilitiesBusinessLogicTest { .thenReturn(Either.left(resource)); when(toscaOperationFacade.getParentComponents(anyString())) .thenReturn(Either.right(StorageOperationStatus.NOT_FOUND)); + when((capabilitiesOperation.deleteCapabilityProperties(any(Component.class), anyString()))) + .thenReturn(StorageOperationStatus.OK); Either deleteCapabilityEither = capabilitiesBusinessLogicMock.deleteCapability(componentId, capabilityId, user, true); Assert.assertTrue(deleteCapabilityEither.isLeft()); @@ -362,6 +371,38 @@ public class CapabilitiesBusinessLogicTest { } + private ComponentInstanceProperty createCIP(String type, String name) { + ComponentInstanceProperty instanceProperty = new ComponentInstanceProperty(); + instanceProperty.setType(type); + instanceProperty.setName(name); + instanceProperty.setDescription("prop_description"); + instanceProperty.setParentUniqueId(capabilityId); + instanceProperty.setSchema(new SchemaDefinition()); + return instanceProperty; + } + + @Test + public void shouldPassCreateCapabilitiesWithPropertiesForHappyScenario(){ + CapabilityDefinition capability = createCapability("capName", "capDesc", "capType", "source1", + "0", "10"); + capability.setProperties(Collections.singletonList(createCIP("name", "type"))); + List capabilityDefinitions = createMockCapabilityListToReturn(capability); + Resource resource = createComponent(false); + resource.setComponentType(ComponentTypeEnum.RESOURCE); + validateUserRoles(Role.ADMIN, Role.DESIGNER); + when(toscaOperationFacade.getToscaElement(anyString(), any(ComponentParametersView.class))) + .thenReturn(Either.left(resource)); + when(capabilitiesOperation.createOrUpdateCapabilityProperties(anyString(), any())).thenReturn(StorageOperationStatus.OK); + 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"))); + Assert.assertTrue(capabilities.left().value().stream().anyMatch(capabilityDefinition -> + capabilityDefinition.getProperties().size() == 1)); + } + private Resource createComponent(boolean needCapability) { Resource resource = new Resource(); resource.setName("Resource1"); @@ -375,17 +416,17 @@ public class CapabilitiesBusinessLogicTest { if(needCapability) { List capabilityDefinitions = createMockCapabilityListToReturn( createCapability("capName", "capDesc", "capType", "source1", - "0", "10")); + "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); + 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; } @@ -410,7 +451,6 @@ public class CapabilitiesBusinessLogicTest { capabilityDefinition.setMaxOccurrences(maxOccurrences); capabilityDefinition.setMinOccurrences(minOccurrences); capabilityDefinition.setUniqueId(capabilityId); - return capabilityDefinition; } diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/InterfaceOperationBusinessLogicTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/InterfaceOperationBusinessLogicTest.java index 963823c261..d5b1f06b82 100644 --- a/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/InterfaceOperationBusinessLogicTest.java +++ b/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/InterfaceOperationBusinessLogicTest.java @@ -23,6 +23,7 @@ import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.when; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; @@ -45,10 +46,13 @@ import org.openecomp.sdc.be.dao.cassandra.ArtifactCassandraDao; import org.openecomp.sdc.be.dao.cassandra.CassandraOperationStatus; import org.openecomp.sdc.be.dao.jsongraph.TitanDao; import org.openecomp.sdc.be.dao.titan.TitanOperationStatus; +import org.openecomp.sdc.be.datatypes.elements.SchemaDefinition; 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.ArtifactDefinition; +import org.openecomp.sdc.be.model.CapabilityDefinition; +import org.openecomp.sdc.be.model.ComponentInstanceProperty; import org.openecomp.sdc.be.model.InputDefinition; import org.openecomp.sdc.be.model.InterfaceDefinition; import org.openecomp.sdc.be.model.Resource; @@ -145,6 +149,44 @@ public class InterfaceOperationBusinessLogicTest { Assert.assertTrue(interfaceOperationEither.isLeft()); } + @Test + public void createInterfaceOperationTestOnExistingInterfaceInputsFromCapProp() { + when(interfaceLifecycleOperation.getAllInterfaceLifecycleTypes()) + .thenReturn(Either.left(Collections.emptyMap())); + when(interfaceOperation.updateInterfaces(any(), any())).thenReturn(Either.left( + Collections.singletonList(InterfaceOperationTestUtils.createMockInterface(interfaceId, operationId, operationName)))); + + CapabilityDefinition capabilityDefinition = new CapabilityDefinition(); + capabilityDefinition.setName("cap" + Math.random()); + capabilityDefinition.setType("tosca.capabilities.network.Bindable"); + capabilityDefinition.setOwnerId(resourceId); + capabilityDefinition.setUniqueId("capUniqueId"); + + List properties = new ArrayList<>(); + ComponentInstanceProperty instanceProperty = new ComponentInstanceProperty(); + instanceProperty.setUniqueId("ComponentInput1_uniqueId"); + instanceProperty.setType("Integer"); + instanceProperty.setName("prop_name"); + instanceProperty.setDescription("prop_description_prop_desc"); + instanceProperty.setOwnerId("capUniqueId"); + instanceProperty.setSchema(new SchemaDefinition()); + properties.add(instanceProperty); + capabilityDefinition.setProperties(properties); + Map> capabilityMap = new HashMap<>(); + capabilityMap.put(capabilityDefinition.getType(), Collections.singletonList(capabilityDefinition)); + + resource.setCapabilities(capabilityMap); + when(toscaOperationFacade.getToscaElement(resourceId)).thenReturn(Either.left(resource)); + + Either, ResponseFormat> interfaceOperationEither = + interfaceOperationBusinessLogic.createInterfaceOperation(resourceId, + Collections.singletonList(InterfaceOperationTestUtils.createMockInterface(interfaceId, + operationId, operationName)), + user, true); + Assert.assertTrue(interfaceOperationEither.isLeft()); + } + + @Test public void createInterfaceOperationWithoutInterfaceTest() { resource.getInterfaces().clear(); diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/utils/PropertiesUtilsTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/utils/PropertiesUtilsTest.java new file mode 100644 index 0000000000..7e15eaa862 --- /dev/null +++ b/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/utils/PropertiesUtilsTest.java @@ -0,0 +1,195 @@ +/* + * 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.utils; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.when; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; +import org.openecomp.sdc.be.components.utils.PropertiesUtils; +import org.openecomp.sdc.be.components.utils.ResourceBuilder; +import org.openecomp.sdc.be.datatypes.elements.GetInputValueDataDefinition; +import org.openecomp.sdc.be.datatypes.elements.SchemaDefinition; +import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum; +import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum; +import org.openecomp.sdc.be.model.CapabilityDefinition; +import org.openecomp.sdc.be.model.ComponentInstanceProperty; +import org.openecomp.sdc.be.model.InputDefinition; +import org.openecomp.sdc.be.model.PropertyDefinition; +import org.openecomp.sdc.be.model.Resource; +import org.openecomp.sdc.be.model.Service; +@RunWith(MockitoJUnitRunner.class) +public class PropertiesUtilsTest { + @Mock + Service service; + + + @Test + public void testProxyServiceProperties(){ + when(service.getProperties()).thenReturn(Arrays.asList(buildPropertyDefinition("a"),buildPropertyDefinition("b"))); + when(service.getInputs()).thenReturn(Arrays.asList(buildInputDefiniton("a"),buildInputDefiniton("c"))); + + final List properties = PropertiesUtils.getProperties(service); + assertEquals(3, properties.size()); + } + + @Test + public void testProxyServiceNullInputs(){ + when(service.getProperties()).thenReturn(Arrays.asList(buildPropertyDefinition("a"),buildPropertyDefinition("b"))); + when(service.getInputs()).thenReturn(null); + + final List properties = PropertiesUtils.getProperties(service); + assertEquals(2, properties.size()); + } + + @Test + public void testProxyServiceNullProperties(){ + when(service.getProperties()).thenReturn(null); + when(service.getInputs()).thenReturn(Arrays.asList(buildInputDefiniton("a"),buildInputDefiniton("c"))); + + final List properties = PropertiesUtils.getProperties(service); + assertEquals(2, properties.size()); + } + + @Test + public void testGetCapabilityProperty() { + + Assert.assertEquals(1, PropertiesUtils.getCapabilityProperty(createProperties(), + "inputId").size()); + } + + @Test + public void testGetPropertyCapabilityOfChildInstance() { + CapabilityDefinition capabilityDefinition = createCapabilityDefinition(); + capabilityDefinition.setPath(Collections.singletonList("path")); + Map> capMap = new HashMap<>(); + capMap.put(capabilityDefinition.getType(), Collections.singletonList(capabilityDefinition)); + Assert.assertTrue(PropertiesUtils.getPropertyCapabilityOfChildInstance("capUniqueId", + capMap).isPresent()); + } + + @Test + public void testGetPropertyCapabilityFromAllCapProps() { + CapabilityDefinition capabilityDefinition = createCapabilityDefinition(); + Map> capMap = new HashMap<>(); + capMap.put(capabilityDefinition.getType(), Collections.singletonList(capabilityDefinition)); + Assert.assertTrue(PropertiesUtils.getPropertyCapabilityOfChildInstance("capUniqueId", + capMap).isPresent()); + } + + @Test + + public void testGetPropertyByInputId() { + Resource resource = new ResourceBuilder().setComponentType(ComponentTypeEnum.RESOURCE).setUniqueId("resourceId") + .setName("name").build(); + CapabilityDefinition capabilityDefinition = createCapabilityDefinition(); + + List properties = new ArrayList<>(); + ComponentInstanceProperty instanceProperty = createProperties(); + + List valueDataDefinitionList = new ArrayList<>(); + GetInputValueDataDefinition getInputValueDataDefinition = new GetInputValueDataDefinition(); + getInputValueDataDefinition.setInputId("inputId"); + getInputValueDataDefinition.setPropName("prop_name"); + valueDataDefinitionList.add(getInputValueDataDefinition); + + instanceProperty.setGetInputValues(valueDataDefinitionList); + properties.add(instanceProperty); + capabilityDefinition.setProperties(properties); + Map> capabilityMap = new HashMap<>(); + capabilityMap.put(capabilityDefinition.getType(), Collections.singletonList(capabilityDefinition)); + resource.setCapabilities(capabilityMap); + + InputDefinition inputDefinition = new InputDefinition(); + inputDefinition.setUniqueId("inputId"); + inputDefinition.setInputId("inputId"); + inputDefinition.setPropertyId("inputId"); + resource.setInputs(Collections.singletonList(inputDefinition)); + Assert.assertTrue(PropertiesUtils.getPropertyByInputId(resource, "inputId").isPresent()); + } + + @Test + public void testIsNodeServiceProxy() { + Resource resource = new ResourceBuilder().setComponentType(ComponentTypeEnum.RESOURCE).setUniqueId("resourceId") + .setName("name").build(); + resource.setResourceType(ResourceTypeEnum.ServiceProxy); + Assert.assertTrue( PropertiesUtils.isNodeServiceProxy(resource)); + } + + @Test + public void testProxyServiceAllNull(){ + when(service.getProperties()).thenReturn(null); + when(service.getInputs()).thenReturn(null); + + final List properties = PropertiesUtils.getProperties(service); + assertEquals(0, properties.size()); + } + + private PropertyDefinition buildPropertyDefinition(String name){ + PropertyDefinition retVal = new PropertyDefinition(); + retVal.setName(name); + return retVal; + } + + private InputDefinition buildInputDefiniton(String name){ + InputDefinition retVal = new InputDefinition(); + retVal.setName(name); + return retVal; + } + + private ComponentInstanceProperty createProperties() { + ComponentInstanceProperty instanceProperty = new ComponentInstanceProperty(); + instanceProperty.setUniqueId("inputId"); + instanceProperty.setType("Integer"); + instanceProperty.setName("prop_name"); + instanceProperty.setDescription("prop_description_prop_desc"); + instanceProperty.setOwnerId("capUniqueId"); + instanceProperty.setValue("{\"get_input\":\"extcp20_order\"}"); + instanceProperty.setSchema(new SchemaDefinition()); + + List valueDataDefinitionList = new ArrayList<>(); + GetInputValueDataDefinition getInputValueDataDefinition = new GetInputValueDataDefinition(); + getInputValueDataDefinition.setInputId("inputId"); + getInputValueDataDefinition.setPropName("prop_name"); + valueDataDefinitionList.add(getInputValueDataDefinition); + instanceProperty.setGetInputValues(valueDataDefinitionList); + return instanceProperty; + } + + private CapabilityDefinition createCapabilityDefinition() { + CapabilityDefinition capabilityDefinition = new CapabilityDefinition(); + capabilityDefinition.setName("cap" + Math.random()); + capabilityDefinition.setType("tosca.capabilities.network.Bindable"); + capabilityDefinition.setOwnerId("resourceId"); + capabilityDefinition.setUniqueId("capUniqueId"); + List path = new ArrayList<>(); + path.add("path1"); + capabilityDefinition.setPath(path); + return capabilityDefinition; + } + +} diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/components/property/CapabilityTestUtils.java b/catalog-be/src/test/java/org/openecomp/sdc/be/components/property/CapabilityTestUtils.java new file mode 100644 index 0000000000..fc0edd9fd1 --- /dev/null +++ b/catalog-be/src/test/java/org/openecomp/sdc/be/components/property/CapabilityTestUtils.java @@ -0,0 +1,51 @@ +/* + * 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.property; + +import org.openecomp.sdc.be.datatypes.elements.SchemaDefinition; +import org.openecomp.sdc.be.model.CapabilityDefinition; +import org.openecomp.sdc.be.model.ComponentInstanceProperty; + +import java.util.ArrayList; +import java.util.List; + +public class CapabilityTestUtils { + + public static ComponentInstanceProperty createProperties() { + ComponentInstanceProperty instanceProperty = new ComponentInstanceProperty(); + instanceProperty.setUniqueId("ComponentInput1_uniqueId"); + instanceProperty.setType("Integer"); + instanceProperty.setName("prop_name"); + instanceProperty.setDescription("prop_description_prop_desc"); + instanceProperty.setOwnerId("capUniqueId"); + instanceProperty.setValue("{\"get_input\":\"extcp20_order\"}"); + instanceProperty.setSchema(new SchemaDefinition()); + return instanceProperty; + } + + public static CapabilityDefinition createCapabilityDefinition() { + CapabilityDefinition capabilityDefinition = new CapabilityDefinition(); + capabilityDefinition.setName("cap" + Math.random()); + capabilityDefinition.setType("tosca.capabilities.network.Bindable"); + capabilityDefinition.setOwnerId("resourceId"); + capabilityDefinition.setUniqueId("capUniqueId"); + List path = new ArrayList<>(); + path.add("path1"); + capabilityDefinition.setPath(path); + return capabilityDefinition; + } +} diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/components/property/ComponentInstancePropertyDeclaratorTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/components/property/ComponentInstancePropertyDeclaratorTest.java index f59adada9a..deb634e232 100644 --- a/catalog-be/src/test/java/org/openecomp/sdc/be/components/property/ComponentInstancePropertyDeclaratorTest.java +++ b/catalog-be/src/test/java/org/openecomp/sdc/be/components/property/ComponentInstancePropertyDeclaratorTest.java @@ -13,6 +13,7 @@ import org.openecomp.sdc.be.components.utils.ResourceBuilder; import org.openecomp.sdc.be.dao.utils.MapUtil; import org.openecomp.sdc.be.datatypes.elements.GetInputValueDataDefinition; import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition; +import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum; import org.openecomp.sdc.be.model.*; import org.openecomp.sdc.be.model.jsontitan.operations.ToscaOperationFacade; import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus; @@ -24,9 +25,12 @@ import java.util.stream.Collectors; import java.util.stream.Stream; import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.verifyZeroInteractions; import static org.mockito.Mockito.when; +import static org.openecomp.sdc.be.components.property.CapabilityTestUtils.createCapabilityDefinition; +import static org.openecomp.sdc.be.components.property.CapabilityTestUtils.createProperties; @RunWith(MockitoJUnitRunner.class) @@ -64,6 +68,64 @@ public class ComponentInstancePropertyDeclaratorTest extends PropertyDeclaratorT verifyUpdatedProperties(properties, capturedInstanceProperties, inputs); } + @Test + public void declareCapabilitiesPropertiesAsInputs() { + prop1.setParentUniqueId("capUniqueId"); + List properties = Collections.singletonList(prop1); + List propsToDeclare = createInstancePropInputList(properties); + when(toscaOperationFacade.addComponentInstancePropertiesToComponent(eq(resource), instancePropertiesCaptor + .capture())).thenReturn(Either.left(Collections.emptyMap())); + + CapabilityDefinition capabilityDefinition = createCapabilityDefinition(); + + List capPropList = new ArrayList<>(); + ComponentInstanceProperty instanceProperty = createProperties(); + capPropList.add(instanceProperty); + capabilityDefinition.setProperties(capPropList); + + capabilityDefinition.setPath(Collections.singletonList("path")); + Map> capabilityMap = new HashMap<>(); + capabilityMap.put(capabilityDefinition.getType(), Collections.singletonList(capabilityDefinition)); + resource.setCapabilities(capabilityMap); + + Either, StorageOperationStatus> createdInputs = testInstance + .declarePropertiesAsInputs(resource, "inst1", propsToDeclare); + Assert.assertTrue(createdInputs.isLeft()); + } + + @Test + public void testUnDeclarePropertiesAsInputs() throws Exception { + Component component = new ResourceBuilder().setComponentType(ComponentTypeEnum.RESOURCE).setUniqueId("resourceId") + .setName("resourceName").build(); + InputDefinition input = new InputDefinition(); + input.setUniqueId("ComponentInput1_uniqueId"); + input.setPropertyId("ComponentInput1_uniqueId"); + + CapabilityDefinition capabilityDefinition = createCapabilityDefinition(); + + List properties = new ArrayList<>(); + ComponentInstanceProperty instanceProperty = createProperties(); + + List valueDataDefinitionList = new ArrayList<>(); + GetInputValueDataDefinition getInputValueDataDefinition = new GetInputValueDataDefinition(); + getInputValueDataDefinition.setInputId("ComponentInput1_uniqueId"); + getInputValueDataDefinition.setPropName("prop_name"); + valueDataDefinitionList.add(getInputValueDataDefinition); + + instanceProperty.setGetInputValues(valueDataDefinitionList); + properties.add(instanceProperty); + capabilityDefinition.setProperties(properties); + Map> capabilityMap = new HashMap<>(); + capabilityMap.put(capabilityDefinition.getType(), Collections.singletonList(capabilityDefinition)); + component.setCapabilities(capabilityMap); + component.setInputs(Collections.singletonList(input)); + when(toscaOperationFacade.updateInstanceCapabilityProperty(any(Resource.class), any(), + any(ComponentInstanceProperty.class), any(CapabilityDefinition.class))).thenReturn(StorageOperationStatus.OK); + + StorageOperationStatus result = testInstance.unDeclarePropertiesAsInputs(component, input); + Assert.assertEquals(StorageOperationStatus.OK, result); + } + @Test public void declarePropertiesAsInputs_multipleNonComplexProperty() { List properties = Arrays.asList(prop1, prop2); diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/components/utils/ConsumptionUtilsTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/components/utils/ConsumptionUtilsTest.java new file mode 100644 index 0000000000..619c2949d2 --- /dev/null +++ b/catalog-be/src/test/java/org/openecomp/sdc/be/components/utils/ConsumptionUtilsTest.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.be.components.utils; + + +import fj.data.Either; +import org.junit.Assert; +import org.junit.Test; +import org.openecomp.sdc.be.datatypes.elements.ListDataDefinition; +import org.openecomp.sdc.be.datatypes.elements.OperationInputDefinition; +import org.openecomp.sdc.be.model.CapabilityDefinition; +import org.openecomp.sdc.be.model.ComponentInstanceProperty; +import org.openecomp.sdc.be.model.Operation; +import org.openecomp.sdc.be.types.ServiceConsumptionData; +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.openecomp.sdc.be.components.property.CapabilityTestUtils.createCapabilityDefinition; +import static org.openecomp.sdc.be.components.property.CapabilityTestUtils.createProperties; + +public class ConsumptionUtilsTest { + + @Test + public void testHandleConsumptionInputMappedToCapabilityProperty() { + + Operation operation = new Operation(); + operation.setUniqueId("uniqueId"); + OperationInputDefinition operationInputDefinition = new OperationInputDefinition(); + operationInputDefinition.setUniqueId("uniqueId"); + operationInputDefinition.setInputId("uniqueId"); + operationInputDefinition.setType("Integer"); + + List operationInputDefinitions = new ArrayList<>(); + operationInputDefinitions.add(operationInputDefinition); + ListDataDefinition listDataDefinition = new ListDataDefinition<>(operationInputDefinitions); + operation.setInputs(listDataDefinition); + CapabilityDefinition capabilityDefinition = createCapabilityDefinition(); + ServiceConsumptionData serviceConsumptionData = new ServiceConsumptionData(); + serviceConsumptionData.setInputId("uniqueId"); + serviceConsumptionData.setValue(capabilityDefinition.getName() + "_prop_name" ); + + List capPropList = new ArrayList<>(); + ComponentInstanceProperty instanceProperty = createProperties(); + capPropList.add(instanceProperty); + capabilityDefinition.setProperties(capPropList); + + capabilityDefinition.setPath(Collections.singletonList("path")); + Map> capabilityMap = new HashMap<>(); + capabilityMap.put(capabilityDefinition.getType(), Collections.singletonList(capabilityDefinition)); + + Either operationResponseFormatEither = ConsumptionUtils + .handleConsumptionInputMappedToCapabilityProperty(operation, operationInputDefinition, + serviceConsumptionData, capabilityMap, "componentName"); + + Assert.assertTrue(operationResponseFormatEither.isLeft()); + } +} \ No newline at end of file diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/components/utils/InterfaceOperationUtilsTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/components/utils/InterfaceOperationUtilsTest.java index 1258bc04a9..74c7b8d841 100644 --- a/catalog-be/src/test/java/org/openecomp/sdc/be/components/utils/InterfaceOperationUtilsTest.java +++ b/catalog-be/src/test/java/org/openecomp/sdc/be/components/utils/InterfaceOperationUtilsTest.java @@ -129,4 +129,10 @@ public class InterfaceOperationUtilsTest { Assert.assertFalse(InterfaceOperationUtils.isArtifactInUse(resource, operationId1, "uniqId1")); } + @Test + public void testCreateMappedCapabilityPropertyDefaultValue() { + Assert.assertTrue(!InterfaceOperationUtils + .createMappedCapabilityPropertyDefaultValue("capName", "propName").isEmpty()); + } + } \ 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 index b4856b96b4..4c3ad329d2 100644 --- 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 @@ -101,6 +101,36 @@ public class CapabilitiesValidationTest { Assert.assertTrue(validateCapabilitiesResponseEither.isRight()); } + @Test + public void shouldPassWhenCapabilityMaxOccurrencesIsUnbounded() { + List capabilityDefinitions = new ArrayList<>(); + capabilityDefinitions.add(createCapability("capName1", "capDesc", "capType", "source1", + "111", "UNBOUNDED")); + Either validateCapabilitiesResponseEither = capabilitiesValidationUtilTest + .validateCapabilities(capabilityDefinitions, component, false); + Assert.assertTrue(validateCapabilitiesResponseEither.isLeft()); + } + + @Test + public void shouldFailWhenCapabilityMinOccurrencesIsNegative() { + List capabilityDefinitions = new ArrayList<>(); + capabilityDefinitions.add(createCapability("capName1", "capDesc", "capType", "source1", + "-1", "3")); + Either validateCapabilitiesResponseEither = capabilitiesValidationUtilTest + .validateCapabilities(capabilityDefinitions, component, false); + Assert.assertTrue(validateCapabilitiesResponseEither.isRight()); + } + + @Test + public void shouldThrowExceptionWhenMin_MaxOccurrencesIsNotInteger() { + List capabilityDefinitions = new ArrayList<>(); + capabilityDefinitions.add(createCapability("capName1", "capDesc", "capType", "source1", + "occur", "3")); + Either validateCapabilitiesResponseEither = capabilitiesValidationUtilTest + .validateCapabilities(capabilityDefinitions, component, false); + Assert.assertTrue(validateCapabilitiesResponseEither.isRight()); + } + @Test public void shouldFailWhenCapabilityNotFoundForUpdate() { List capabilityDefinitions = new ArrayList<>(); @@ -114,6 +144,47 @@ public class CapabilitiesValidationTest { Assert.assertTrue(validateCapabilitiesResponseEither.isRight()); } + @Test + public void shouldFailWhenCapabilityMapIsEmptyInComponentForUpdate() { + List capabilityDefinitions = new ArrayList<>(); + CapabilityDefinition capabilityToUpdate = createCapability("capName1", "capDesc", "capType", "source1", + "1", "3"); + capabilityToUpdate.setUniqueId("uniqueId2"); + capabilityDefinitions.add(capabilityToUpdate); + Component resource = new Resource(); + List componentCap = new ArrayList<>(); + Map> capabilityMap = new HashMap<>(); + capabilityMap.put("capTypeC", componentCap); + + resource.setCapabilities(capabilityMap); + Either validateCapabilitiesResponseEither = capabilitiesValidationUtilTest + .validateCapabilities(capabilityDefinitions, resource, true); + Assert.assertTrue(validateCapabilitiesResponseEither.isRight()); + } + + @Test + public void shouldFailWhenCapabilityMapIsNullInComponentForUpdate() { + List capabilityDefinitions = new ArrayList<>(); + CapabilityDefinition capabilityToUpdate = createCapability("capName1", "capDesc", "capType", "source1", + "1", "3"); + capabilityToUpdate.setUniqueId("uniqueId2"); + + capabilityDefinitions.add(capabilityToUpdate); + Either validateCapabilitiesResponseEither = capabilitiesValidationUtilTest + .validateCapabilities(capabilityDefinitions, new Resource(), true); + Assert.assertTrue(validateCapabilitiesResponseEither.isRight()); + } + + @Test + public void shouldFailWhenCapabilityNameContainsSpecialSymbolExceptDot() { + List capabilityDefinitions = new ArrayList<>(); + capabilityDefinitions.add(createCapability("cap@name", "capDesc", "capType", "source1", + "0", "10")); + Either validateCapabilitiesResponseEither = capabilitiesValidationUtilTest + .validateCapabilities(capabilityDefinitions, component, false); + Assert.assertTrue(validateCapabilitiesResponseEither.isRight()); + } + private CapabilityDefinition createCapability(String name, String description, String type, String validSourceTypes, String minOccurrences, String maxOccurrences) { @@ -126,7 +197,6 @@ public class CapabilitiesValidationTest { capabilityDefinition.setMinOccurrences(minOccurrences); capabilityDefinition.setUniqueId("uniqueId"); - return capabilityDefinition; } @@ -143,9 +213,9 @@ public class CapabilitiesValidationTest { List capabilityDefinitions = new ArrayList<>(); capabilityDefinitions.add(createCapability("capNameC", "capDesc", "capType", "source1", "0", "10")); - Map> capabilityMap = new HashMap<>(); - capabilityMap.put("capTypeC", capabilityDefinitions); - resource.setCapabilities(capabilityMap); + Map> capabilityMap = new HashMap<>(); + capabilityMap.put("capTypeC", capabilityDefinitions); + resource.setCapabilities(capabilityMap); return resource; } 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 6fd2eb26c8..dc4da54ff6 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 @@ -155,6 +155,7 @@ public enum ActionStatus { 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, + FAILED_TO_CREATE_OR_UPDATE_CAPABILITY_PROPERTIES, CAPABILITY_PROPERTIES_NOT_FOUND, RELATIONSHIP_TYPE_ALREADY_EXIST, MISSING_RELATIONSHIP_TYPE, CAPABILITY_TYPE_CANNOT_BE_EMPTY, diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/ComponentParametersView.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/ComponentParametersView.java index 3edb8ded6c..4e7903a890 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/ComponentParametersView.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/ComponentParametersView.java @@ -46,7 +46,7 @@ public class ComponentParametersView { private boolean ignoreComponentInstancesAttributesFrom = false; private boolean ignoreInputs = false; private boolean ignoreComponentInstancesInputs = false; - private boolean ignoreCapabiltyProperties = true; + private boolean ignoreCapabiltyProperties = false; private boolean ignoreServicePath = true; private boolean ignorePolicies = false; private boolean ignoreNodeFilterRequirements = false; @@ -95,6 +95,7 @@ public class ComponentParametersView { this.setIgnoreCapabilities(false); this.setIgnoreRequirements(false); this.setIgnoreNodeFilter(false); + this.setIgnoreCapabiltyProperties(false); break; case COMPONENT_INSTANCES_PROPERTIES: this.setIgnoreComponentInstances(false); //we need this in order to get the calculate capabilities requirements @@ -103,6 +104,7 @@ public class ComponentParametersView { case CAPABILITIES: this.setIgnoreComponentInstances(false);//we need this in order to get the calculate capabilities requirements this.setIgnoreCapabilities(false); + this.setIgnoreCapabiltyProperties(false); break; case REQUIREMENTS: this.setIgnoreComponentInstances(false); 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 6dfd1fcffb..d44865c399 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 @@ -1485,7 +1485,7 @@ public abstract class BaseOperation { return titanOperationStatus; } - private GraphVertex throwStorageException(TitanOperationStatus status) { + protected GraphVertex throwStorageException(TitanOperationStatus status) { throw new StorageException(status); } 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 index a8337b6c4f..9d7f64c24a 100644 --- 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 @@ -17,13 +17,23 @@ package org.openecomp.sdc.be.model.jsontitan.operations; import fj.data.Either; +import org.apache.commons.collections.MapUtils; +import org.openecomp.sdc.be.dao.jsongraph.GraphVertex; import org.openecomp.sdc.be.dao.jsongraph.types.EdgeLabelEnum; +import org.openecomp.sdc.be.dao.jsongraph.types.JsonParseFlagEnum; 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.elements.MapPropertiesDataDefinition; +import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition; import org.openecomp.sdc.be.datatypes.enums.JsonPresentationFields; +import org.openecomp.sdc.be.datatypes.tosca.ToscaDataDefinition; import org.openecomp.sdc.be.model.CapabilityDefinition; import org.openecomp.sdc.be.model.Component; +import org.openecomp.sdc.be.model.ComponentParametersView; +import org.openecomp.sdc.be.model.jsontitan.datamodel.TopologyTemplate; +import org.openecomp.sdc.be.model.jsontitan.datamodel.ToscaElement; +import org.openecomp.sdc.be.model.operations.StorageException; import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -31,20 +41,19 @@ import org.slf4j.LoggerFactory; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Map; @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) { + public Either, StorageOperationStatus> addCapabilities(String componentId, + List capabilityDefinitions) { return addOrUpdateCapabilities(componentId, capabilityDefinitions, false); } - public Either, StorageOperationStatus> updateCapabilities( - String componentId, - List capabilityDefinitions) { + public Either, StorageOperationStatus> updateCapabilities(String componentId, + List capabilityDefinitions) { return addOrUpdateCapabilities(componentId, capabilityDefinitions, true); } @@ -52,33 +61,31 @@ public class CapabilitiesOperation extends BaseOperation { List capabilityDefinitions, boolean isUpdateAction) { StorageOperationStatus statusRes = performUpdateToscaAction(isUpdateAction, - componentId, Collections - .singletonList(convertToListCapabilityDataDefinition(capabilityDefinitions))); + 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); + 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, + public StorageOperationStatus deleteCapabilities(Component component, String capabilityIdToDelete) { + return deleteToscaDataElements(component.getUniqueId(), EdgeLabelEnum.CAPABILITIES, Collections.singletonList(capabilityIdToDelete)); } - private static ListCapabilityDataDefinition convertToListCapabilityDataDefinition( - List capabilities) { + public StorageOperationStatus deleteCapabilityProperties(Component component, String capabilityPropIdToDelete) { + return deleteToscaDataElements(component.getUniqueId(), EdgeLabelEnum.CAPABILITIES_PROPERTIES, + Collections.singletonList(capabilityPropIdToDelete)); + } + + private static ListCapabilityDataDefinition convertToListCapabilityDataDefinition(List capabilities) { List capabilityDefinitions = new ArrayList<>(capabilities); return new ListCapabilityDataDefinition(capabilityDefinitions); } - private StorageOperationStatus performUpdateToscaAction(boolean isUpdate, - String componentId, + private StorageOperationStatus performUpdateToscaAction(boolean isUpdate, String componentId, List toscaDataList) { if (isUpdate) { return updateToscaDataOfToscaElement(componentId, EdgeLabelEnum.CAPABILITIES, @@ -88,4 +95,61 @@ public class CapabilitiesOperation extends BaseOperation { VertexTypeEnum.CAPABILITIES, toscaDataList, JsonPresentationFields.TYPE); } } + + private StorageOperationStatus createOrUpdateCapabilityProperties(String componentId, TopologyTemplate toscaElement, + Map propertiesMap) { + GraphVertex toscaElementV = titanDao.getVertexById(componentId, JsonParseFlagEnum.NoParse) + .left().on(this::throwStorageException); + Map capabilitiesProperties = toscaElement.getCapabilitiesProperties(); + if(MapUtils.isNotEmpty(capabilitiesProperties)) { + + capabilitiesProperties.forEach((key, val) -> { + Map mapToscaDataDefinition = val.getMapToscaDataDefinition(); + mapToscaDataDefinition.forEach((key1, val1) -> { + + propertiesMap.forEach((propKey, propVal) -> { + Map propValMapToscaDataDefinition = propVal.getMapToscaDataDefinition(); + propValMapToscaDataDefinition.forEach((propKey1, propVal1) -> { + if(propKey1.equals(key1) && val1.getUniqueId().equals(propVal1.getUniqueId())) { + ToscaDataDefinition.mergeDataMaps(mapToscaDataDefinition, propValMapToscaDataDefinition); + } + }); + }); + }); + }); + + ToscaDataDefinition.mergeDataMaps(propertiesMap, capabilitiesProperties); + } + + return topologyTemplateOperation.updateFullToscaData(toscaElementV, + EdgeLabelEnum.CAPABILITIES_PROPERTIES, VertexTypeEnum.CAPABILITIES_PROPERTIES, propertiesMap); + } + + public StorageOperationStatus createOrUpdateCapabilityProperties(String componentId, + Map propertiesMap) { + StorageOperationStatus propertiesStatusRes = null; + if(MapUtils.isNotEmpty(propertiesMap)) { + propertiesStatusRes = createOrUpdateCapabilityProperties(componentId, getTopologyTemplate(componentId), + propertiesMap); + } + + return propertiesStatusRes; + } + + private TopologyTemplate getTopologyTemplate(String componentId) { + return (TopologyTemplate)topologyTemplateOperation + .getToscaElement(componentId, getFilterComponentWithCapProperties()) + .left() + .on(this::throwStorageException); + } + private ComponentParametersView getFilterComponentWithCapProperties() { + ComponentParametersView filter = new ComponentParametersView(); + filter.setIgnoreCapabiltyProperties(false); + return filter; + } + + private ToscaElement throwStorageException(StorageOperationStatus status) { + throw new StorageException(status); + } + } 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 b0bfc153f4..5ddc5287ed 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 @@ -253,11 +253,24 @@ public class TopologyTemplateOperation extends ToscaElementOperation { } private StorageOperationStatus associateCapPropertiesToResource(GraphVertex topologyTemplateVertex, TopologyTemplate topologyTemplate) { - Map calculatedCapProperties = topologyTemplate.getCalculatedCapabilitiesProperties(); - if (calculatedCapProperties != null && !calculatedCapProperties.isEmpty()) { - Either assosiateElementToData = associateElementToData(topologyTemplateVertex, VertexTypeEnum.CALCULATED_CAP_PROPERTIES, EdgeLabelEnum.CALCULATED_CAP_PROPERTIES, calculatedCapProperties); - if (assosiateElementToData.isRight()) { - return assosiateElementToData.right().value(); + Map calculatedCapProperties = topologyTemplate + .getCalculatedCapabilitiesProperties(); + if (MapUtils.isNotEmpty(calculatedCapProperties)) { + Either associateElementToData = associateElementToData + (topologyTemplateVertex, VertexTypeEnum.CALCULATED_CAP_PROPERTIES, + EdgeLabelEnum.CALCULATED_CAP_PROPERTIES, calculatedCapProperties); + if (associateElementToData.isRight()) { + return associateElementToData.right().value(); + } + } + + Map capabilitiesProperties = topologyTemplate.getCapabilitiesProperties(); + if (MapUtils.isNotEmpty(capabilitiesProperties)) { + Either associateElementToData = + associateElementToData(topologyTemplateVertex, VertexTypeEnum.CAPABILITIES_PROPERTIES, + EdgeLabelEnum.CAPABILITIES_PROPERTIES, capabilitiesProperties); + if (associateElementToData.isRight()) { + return associateElementToData.right().value(); } } return StorageOperationStatus.OK; @@ -888,6 +901,16 @@ public class TopologyTemplateOperation extends ToscaElementOperation { return result.right().value(); } } + Either, TitanOperationStatus> capPropResult = + getDataFromGraph(componentV, EdgeLabelEnum.CAPABILITIES_PROPERTIES); + if (capPropResult.isLeft()) { + topologyTemplate.setCapabilitiesProperties(capPropResult.left().value()); + } else { + if (capPropResult.right().value() != TitanOperationStatus.NOT_FOUND) { + return capPropResult.right().value(); + } + } + return TitanOperationStatus.OK; } @@ -1173,6 +1196,11 @@ public class TopologyTemplateOperation extends ToscaElementOperation { log.debug("Failed to disassociate instance inputs for {} error {}", toscaElementVertex.getUniqueId(), status); return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status)); } + status = titanDao.disassociateAndDeleteLast(toscaElementVertex, Direction.OUT, EdgeLabelEnum.CAPABILITIES_PROPERTIES); + if (status != TitanOperationStatus.OK) { + log.debug("Failed to disassociate capabilities properties for {} error {}", toscaElementVertex.getUniqueId(), status); + Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status)); + } status = titanDao.disassociateAndDeleteLast(toscaElementVertex, Direction.OUT, EdgeLabelEnum.CALCULATED_CAPABILITIES); if (status != TitanOperationStatus.OK) { log.debug("Failed to disassociate calculated capabiliites for {} error {}", toscaElementVertex.getUniqueId(), status); @@ -1521,10 +1549,6 @@ public class TopologyTemplateOperation extends ToscaElementOperation { } } - private GraphVertex throwStorageException(TitanOperationStatus status) { - throw new StorageException(status); - } - private ToscaElement getOriginToscaElement(ComponentInstanceDataDefinition instance) { log.debug("#getOriginToscaElement - origin name: {}", instance.getComponentName()); ToscaElementTypeEnum elementType = detectToscaType(instance.getOriginType()); @@ -1558,11 +1582,12 @@ public class TopologyTemplateOperation extends ToscaElementOperation { filter.setIgnoreRequirements(false); return filter; } - public void updateCapReqOwnerId(String componentId, TopologyTemplate toscaElement) { + public void updateCapReqPropertiesOwnerId(String componentId, TopologyTemplate toscaElement) { GraphVertex toscaElementV = titanDao.getVertexById(componentId, JsonParseFlagEnum.NoParse) .left().on(this::throwStorageException); updateCapOwnerId(toscaElement, componentId); updateReqOwnerId(toscaElement, componentId); + updatePropertiesOwnerId(toscaElement, componentId); topologyTemplateOperation .updateFullToscaData(toscaElementV, EdgeLabelEnum.CAPABILITIES, @@ -1570,6 +1595,9 @@ public class TopologyTemplateOperation extends ToscaElementOperation { topologyTemplateOperation .updateFullToscaData(toscaElementV, EdgeLabelEnum.REQUIREMENTS, VertexTypeEnum.REQUIREMENTS, toscaElement.getRequirements()); + topologyTemplateOperation + .updateFullToscaData(toscaElementV, EdgeLabelEnum.PROPERTIES, + VertexTypeEnum.PROPERTIES, toscaElement.getProperties()); } private void updateCapOwnerId(ToscaElement toscaElement, String ownerId) { @@ -1586,4 +1614,11 @@ public class TopologyTemplateOperation extends ToscaElementOperation { } } + private void updatePropertiesOwnerId(ToscaElement toscaElement, String ownerId) { + Map properties = toscaElement.getProperties(); + if(MapUtils.isNotEmpty(properties)) { + properties.values().forEach(propertyDataDefinition -> propertyDataDefinition.setParentUniqueId(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 8456486bef..4482f7f943 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 @@ -1236,23 +1236,28 @@ public class ToscaOperationFacade { public Either>, StorageOperationStatus> addComponentInstancePropertiesToComponent(Component containerComponent, Map> instProperties) { requireNonNull(instProperties); - StorageOperationStatus status; + StorageOperationStatus status = null; for (Entry> entry : instProperties.entrySet()) { List props = entry.getValue(); String componentInstanceId = entry.getKey(); - List instanceProperties = containerComponent.getComponentInstancesProperties().get(componentInstanceId); + + Map> containerComponentCapabilities = containerComponent.getCapabilities(); + if (!isEmpty(props)) { for (ComponentInstanceProperty property : props) { - Optional instanceProperty = instanceProperties.stream() - .filter(p -> p.getUniqueId().equals(property.getUniqueId())) - .findAny(); - if (instanceProperty.isPresent()) { - status = updateComponentInstanceProperty(containerComponent, componentInstanceId, property); - } else { - status = addComponentInstanceProperty(containerComponent, componentInstanceId, property); + String propertyParentUniqueId = property.getParentUniqueId(); + Optional + capPropDefinition = getPropertyCapability(propertyParentUniqueId, containerComponent); + if(capPropDefinition.isPresent() && MapUtils.isNotEmpty(containerComponentCapabilities)) { + status = populateAndUpdateInstanceCapProperty(containerComponent, componentInstanceId, + containerComponentCapabilities, property, capPropDefinition.get()); } - if (status != StorageOperationStatus.OK) { - log.debug("Failed to update instance property {} for instance {} error {} ", property, componentInstanceId, status); + if(status == null) { + List instanceProperties = containerComponent + .getComponentInstancesProperties().get(componentInstanceId); + status = updateInstanceProperty(containerComponent, componentInstanceId, instanceProperties, property); + } + if(status != StorageOperationStatus.OK) { return Either.right(status); } } @@ -1261,6 +1266,103 @@ public class ToscaOperationFacade { return Either.left(instProperties); } + private StorageOperationStatus populateAndUpdateInstanceCapProperty(Component containerComponent, String componentInstanceId, + Map> containerComponentCapabilities, + ComponentInstanceProperty property, + CapabilityDefinition capabilityDefinition) { + List capabilityDefinitions = containerComponentCapabilities.get(capabilityDefinition.getType()); + if(CollectionUtils.isEmpty(capabilityDefinitions)) { + return null; + } + Optional capDefToGetProp = capabilityDefinitions.stream() + .filter(cap -> cap.getUniqueId().equals(capabilityDefinition.getUniqueId()) && cap.getPath().size() == 1).findAny(); + if(capDefToGetProp.isPresent()) { + return updateInstanceCapabilityProperty(containerComponent, componentInstanceId, property, capDefToGetProp.get()); + } + return null; + } + + private static Optional getPropertyCapability(String propertyParentUniqueId, + Component containerComponent) { + + Map> componentCapabilities = containerComponent.getCapabilities(); + if(MapUtils.isEmpty(componentCapabilities)){ + return Optional.empty(); + } + List capabilityDefinitionList = componentCapabilities.values() + .stream().flatMap(Collection::stream).collect(Collectors.toList()); + if(CollectionUtils.isEmpty(capabilityDefinitionList)){ + return Optional.empty(); + } + return capabilityDefinitionList.stream() + .filter(capabilityDefinition -> capabilityDefinition.getUniqueId().equals(propertyParentUniqueId)) + .findAny(); + } + + private StorageOperationStatus updateInstanceProperty(Component containerComponent, String componentInstanceId, + List instanceProperties, + ComponentInstanceProperty property) { + StorageOperationStatus status; + Optional instanceProperty = instanceProperties.stream() + .filter(p -> p.getUniqueId().equals(property.getUniqueId())) + .findAny(); + if (instanceProperty.isPresent()) { + status = updateComponentInstanceProperty(containerComponent, componentInstanceId, property); + } else { + status = addComponentInstanceProperty(containerComponent, componentInstanceId, property); + } + if (status != StorageOperationStatus.OK) { + log.debug("Failed to update instance property {} for instance {} error {} ", property, componentInstanceId, status); + return status; + } + return StorageOperationStatus.OK; + } + + public StorageOperationStatus updateInstanceCapabilityProperty(Component containerComponent, String componentInstanceId, + ComponentInstanceProperty property, + CapabilityDefinition capabilityDefinition) { + Optional fetchedCIOptional = containerComponent.getComponentInstanceById(componentInstanceId); + if(!fetchedCIOptional.isPresent()) { + return StorageOperationStatus.GENERAL_ERROR; + } + Either getComponentRes = + getToscaFullElement(fetchedCIOptional.get().getComponentUid()); + if(getComponentRes.isRight()) { + return StorageOperationStatus.GENERAL_ERROR; + } + Optional componentOptional = isNodeServiceProxy(getComponentRes.left().value()); + String propOwner; + if(!componentOptional.isPresent()) { + propOwner = componentInstanceId; + } else { + propOwner = fetchedCIOptional.get().getSourceModelUid(); + } + StorageOperationStatus status; + StringBuffer sb = new StringBuffer(componentInstanceId); + sb.append(ModelConverter.CAP_PROP_DELIM).append(propOwner).append(ModelConverter.CAP_PROP_DELIM) + .append(capabilityDefinition.getType()).append(ModelConverter.CAP_PROP_DELIM).append(capabilityDefinition.getName()); + String capKey = sb.toString(); + status = updateComponentInstanceCapabiltyProperty(containerComponent, componentInstanceId, capKey, property); + if (status != StorageOperationStatus.OK) { + log.debug("Failed to update instance capability property {} for instance {} error {} ", property, + componentInstanceId, status); + return status; + } + return StorageOperationStatus.OK; + } + + private Optional isNodeServiceProxy(Component component) { + if (component.getComponentType().equals(ComponentTypeEnum.SERVICE)) { + return Optional.empty(); + } + Resource resource = (Resource) component; + ResourceTypeEnum resType = resource.getResourceType(); + if(resType.equals(ResourceTypeEnum.ServiceProxy)) { + return Optional.of(component); + } + return Optional.empty(); + } + public StorageOperationStatus associateDeploymentArtifactsToInstances(Map> instDeploymentArtifacts, String componentId, User user) { Either getVertexEither = titanDao.getVertexById(componentId, JsonParseFlagEnum.NoParse); @@ -2634,8 +2736,8 @@ public class ToscaOperationFacade { } return Either.left(parentComponents); } - public void updateCapReqOwnerId(String componentId) { + public void updateCapReqPropertiesOwnerId(String componentId) { topologyTemplateOperation - .updateCapReqOwnerId(componentId, getTopologyTemplate(componentId)); + .updateCapReqPropertiesOwnerId(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 cfd00a5313..9412c5c70b 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 @@ -464,7 +464,9 @@ public class ModelConverter { if (CollectionUtils.isNotEmpty(capPrps)) { MapPropertiesDataDefinition dataToCreate = new MapPropertiesDataDefinition(); for (ComponentInstanceProperty cip : capPrps) { - dataToCreate.put(cip.getName(), new PropertyDataDefinition(cip)); + PropertyDataDefinition propertyDataDefinition = new PropertyDataDefinition(cip); + propertyDataDefinition.setParentUniqueId(cap.getUniqueId()); + dataToCreate.put(cip.getName(), propertyDataDefinition); } toscaCapPropMap.put(s + CAP_PROP_DELIM + cap.getName(), dataToCreate); } @@ -1384,16 +1386,51 @@ public class ModelConverter { private static void setCapabilitiesToComponent(TopologyTemplate topologyTemplate, Component component) { Map capabilities = topologyTemplate.getCapabilities(); - Map> componentCapabilities = component.getCapabilities(); + Map capabilitiesProperties = topologyTemplate.getCapabilitiesProperties(); + Map> allCapabilities = new HashMap<>(); + if(MapUtils.isNotEmpty(capabilities)) { - if(componentCapabilities == null) { - componentCapabilities = new HashMap<>(); - } - componentCapabilities.putAll(groupCapabilityByType(capabilities)); - component.setCapabilities(componentCapabilities); + allCapabilities.putAll(groupCapabilityByType(capabilities)); + } + + if(MapUtils.isNotEmpty(capabilitiesProperties)) { + capabilitiesProperties.forEach((s, capProp)-> { + String[] result = s.split(CAP_PROP_DELIM); + if (capProp != null) { + Map capMap = capProp.getMapToscaDataDefinition(); + + if (MapUtils.isNotEmpty(capMap)) { + List capPropsList = capMap.values().stream() + .map(ComponentInstanceProperty::new).collect(Collectors.toList()); + + List cap = allCapabilities.get(result[0]); + if (cap !=null) { + Optional op = cap.stream().filter(c -> c.getName() + .equals(result[1])).findFirst(); + op.ifPresent(capabilityDefinition -> capabilityDefinition.setProperties(capPropsList)); + } + } + } + } + ); + } + Map> componentCapabilities = component.getCapabilities(); + if(MapUtils.isNotEmpty(componentCapabilities)) { + mergeCapabilityMap(allCapabilities, componentCapabilities); } + component.setCapabilities(allCapabilities); + } + private static void mergeCapabilityMap(Map> map1, + Map> map2) { + map1.forEach((key1, val1) -> map2.forEach((key2, val2) -> { + if(key1.equals(key2)) { + val2.addAll(val1); + } + })); + map1.putAll(map2); } + private static Map> groupCapabilityByType(Map capabilities) { Map> groupedCapabilities = new HashMap<>(); diff --git a/catalog-model/src/test/java/org/openecomp/sdc/be/model/jsontitan/operations/CapabilitiesOperationTest.java b/catalog-model/src/test/java/org/openecomp/sdc/be/model/jsontitan/operations/CapabilitiesOperationTest.java new file mode 100644 index 0000000000..0c9c35b62a --- /dev/null +++ b/catalog-model/src/test/java/org/openecomp/sdc/be/model/jsontitan/operations/CapabilitiesOperationTest.java @@ -0,0 +1,87 @@ +/* + * 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.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.openecomp.sdc.be.dao.jsongraph.GraphVertex; +import org.openecomp.sdc.be.dao.jsongraph.TitanDao; +import org.openecomp.sdc.be.dao.titan.TitanOperationStatus; +import org.openecomp.sdc.be.datatypes.elements.MapPropertiesDataDefinition; +import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition; +import org.openecomp.sdc.be.model.jsontitan.datamodel.TopologyTemplate; +import org.openecomp.sdc.be.model.jsontitan.utils.CapabilityTestUtils; +import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus; + +import java.util.HashMap; +import java.util.Map; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyMap; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.when; + +public class CapabilitiesOperationTest { + + @InjectMocks + CapabilitiesOperation operation = new CapabilitiesOperation(); + @Mock + private TitanDao mockTitanDao; + @Mock + private TopologyTemplateOperation topologyTemplateOperation; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + + when(mockTitanDao.commit()).thenReturn(TitanOperationStatus.OK); + when(mockTitanDao.getVertexById(anyString(), any())).thenReturn(Either.left(new GraphVertex())); + + when(topologyTemplateOperation.updateFullToscaData(any(), any(), any(), anyMap())).thenReturn(StorageOperationStatus.OK); + TopologyTemplate topologyTemplate = new TopologyTemplate(); + + Map capPropsForTopologyTemplate = CapabilityTestUtils + .createCapPropsForTopologyTemplate(topologyTemplate); + topologyTemplate.setCapabilitiesProperties(capPropsForTopologyTemplate); + + when(topologyTemplateOperation.getToscaElement(anyString(), any())).thenReturn(Either.left(topologyTemplate)); + } + + @Test + public void testCreateOrUpdateCapabilitiesProperties() { + + Map mapToscaDataDefinition = new HashMap<>(); + PropertyDataDefinition propertyDataDefinition = new PropertyDataDefinition(); + propertyDataDefinition.setUniqueId("ComponentInput1_uniqueId"); + propertyDataDefinition.setName("propName"); + mapToscaDataDefinition.put(propertyDataDefinition.getUniqueId(), propertyDataDefinition); + MapPropertiesDataDefinition mapPropertiesDataDefinition = new MapPropertiesDataDefinition(mapToscaDataDefinition); + + Map propertiesMap = new HashMap<>(); + propertiesMap.put(propertyDataDefinition.getUniqueId(), mapPropertiesDataDefinition); + + StorageOperationStatus operationStatus = operation.createOrUpdateCapabilityProperties("componentId", + propertiesMap); + + Assert.assertEquals(StorageOperationStatus.OK, operationStatus); + } +} \ No newline at end of file diff --git a/catalog-model/src/test/java/org/openecomp/sdc/be/model/jsontitan/utils/CapabilityTestUtils.java b/catalog-model/src/test/java/org/openecomp/sdc/be/model/jsontitan/utils/CapabilityTestUtils.java new file mode 100644 index 0000000000..6f6b7eacad --- /dev/null +++ b/catalog-model/src/test/java/org/openecomp/sdc/be/model/jsontitan/utils/CapabilityTestUtils.java @@ -0,0 +1,85 @@ +/* + * 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.utils; + +import org.openecomp.sdc.be.datatypes.elements.CapabilityDataDefinition; +import org.openecomp.sdc.be.datatypes.elements.ListCapabilityDataDefinition; +import org.openecomp.sdc.be.datatypes.elements.MapPropertiesDataDefinition; +import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition; +import org.openecomp.sdc.be.datatypes.elements.SchemaDefinition; +import org.openecomp.sdc.be.model.CapabilityDefinition; +import org.openecomp.sdc.be.model.ComponentInstanceProperty; +import org.openecomp.sdc.be.model.jsontitan.datamodel.TopologyTemplate; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class CapabilityTestUtils { + + public static Map createCapPropsForTopologyTemplate(TopologyTemplate topologyTemplate) { + Map capabilitiesMap = new HashMap<>(); + + List capabilityDefinitions = new ArrayList<>(); + CapabilityDefinition capabilityDefinition = createCapabilityDefinition(); + + capabilityDefinitions.add(capabilityDefinition); + ListCapabilityDataDefinition listCapabilityDataDefinition = new ListCapabilityDataDefinition(capabilityDefinitions); + capabilitiesMap.put(capabilityDefinition.getType(), listCapabilityDataDefinition); + topologyTemplate.setCapabilities(capabilitiesMap); + + List capPropList = new ArrayList<>(); + ComponentInstanceProperty instanceProperty = createProperties(); + capPropList.add(instanceProperty); + + MapPropertiesDataDefinition dataToCreate = new MapPropertiesDataDefinition(); + for (ComponentInstanceProperty cip : capPropList) { + PropertyDataDefinition propertyDataDefinition = new PropertyDataDefinition(cip); + dataToCreate.put(cip.getName(), propertyDataDefinition); + } + + Map capabilitiesProperties = new HashMap<>(); + capabilitiesProperties.put(capabilityDefinition.getType() + ModelConverter.CAP_PROP_DELIM + + capabilityDefinition.getName(), dataToCreate); + return capabilitiesProperties; + } + + private static CapabilityDefinition createCapabilityDefinition() { + CapabilityDefinition capabilityDefinition = new CapabilityDefinition(); + capabilityDefinition.setName("cap" + Math.random()); + capabilityDefinition.setType("tosca.capabilities.network.Bindable"); + capabilityDefinition.setOwnerId("resourceId"); + capabilityDefinition.setUniqueId("capUniqueId"); + List path = new ArrayList<>(); + path.add("path1"); + capabilityDefinition.setPath(path); + return capabilityDefinition; + } + + private static ComponentInstanceProperty createProperties() { + ComponentInstanceProperty instanceProperty = new ComponentInstanceProperty(); + instanceProperty.setUniqueId("ComponentInput1_uniqueId"); + instanceProperty.setType("Integer"); + instanceProperty.setName("prop_name"); + instanceProperty.setDescription("prop_description_prop_desc"); + instanceProperty.setOwnerId("capUniqueId"); + instanceProperty.setValue("{\"get_input\":\"extcp20_order\"}"); + instanceProperty.setSchema(new SchemaDefinition()); + return instanceProperty; + } +} diff --git a/catalog-model/src/test/java/org/openecomp/sdc/be/model/jsontitan/utils/ModelConverterTest.java b/catalog-model/src/test/java/org/openecomp/sdc/be/model/jsontitan/utils/ModelConverterTest.java index f8713c6b78..a927f5a461 100644 --- a/catalog-model/src/test/java/org/openecomp/sdc/be/model/jsontitan/utils/ModelConverterTest.java +++ b/catalog-model/src/test/java/org/openecomp/sdc/be/model/jsontitan/utils/ModelConverterTest.java @@ -34,6 +34,7 @@ import org.junit.runner.RunWith; import org.mockito.InjectMocks; import org.mockito.junit.MockitoJUnitRunner; import org.openecomp.sdc.be.dao.jsongraph.types.VertexTypeEnum; +import org.openecomp.sdc.be.datatypes.elements.MapPropertiesDataDefinition; import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum; import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum; import org.openecomp.sdc.be.model.Resource; @@ -42,6 +43,9 @@ import org.openecomp.sdc.be.model.Component; import org.openecomp.sdc.be.model.jsontitan.datamodel.TopologyTemplate; import org.openecomp.sdc.be.model.jsontitan.datamodel.NodeType; import org.openecomp.sdc.be.model.jsontitan.datamodel.ToscaElementTypeEnum; + +import java.util.Map; + import static org.assertj.core.api.Assertions.assertThat; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; @@ -78,6 +82,21 @@ public class ModelConverterTest { assertThat(component.getToscaType()).isEqualTo(ToscaElementTypeEnum.TOPOLOGY_TEMPLATE.getValue()); } + @Test + public void testConvertFromToscaElementServiceWithSelfCapabilities() + { + TopologyTemplate topologyTemplate = new TopologyTemplate(); + + Map capabilitiesProperties = CapabilityTestUtils + .createCapPropsForTopologyTemplate(topologyTemplate); + + topologyTemplate.setCapabilitiesProperties(capabilitiesProperties); + + topologyTemplate.setComponentType(ComponentTypeEnum.SERVICE); + Component component = test.convertFromToscaElement(topologyTemplate); + assertThat(component.getToscaType()).isEqualTo(ToscaElementTypeEnum.TOPOLOGY_TEMPLATE.getValue()); + } + @Test public void testConvertFromToscaElementResource() { diff --git a/catalog-ui/src/app/models/capability-types.ts b/catalog-ui/src/app/models/capability-types.ts index fc01f540a7..278d3d397c 100644 --- a/catalog-ui/src/app/models/capability-types.ts +++ b/catalog-ui/src/app/models/capability-types.ts @@ -15,6 +15,7 @@ */ import {ToscaPresentationData} from "./tosca-presentation"; +import {PropertyModel} from "./properties"; export class CapabilityTypesMap { capabilityTypesMap: CapabilityTypesMapData; @@ -30,12 +31,14 @@ export class CapabilityTypesMapData { export class CapabilityTypeModel { derivedFrom: string; + properties: Array; toscaPresentation: ToscaPresentationData; constructor(capabilityType?: CapabilityTypeModel) { if (capabilityType) { this.derivedFrom = capabilityType.derivedFrom; this.toscaPresentation = capabilityType.toscaPresentation; + this.properties = capabilityType.properties; } } } \ No newline at end of file diff --git a/catalog-ui/src/app/models/capability.ts b/catalog-ui/src/app/models/capability.ts index caef2e87dd..4a4f821e0c 100644 --- a/catalog-ui/src/app/models/capability.ts +++ b/catalog-ui/src/app/models/capability.ts @@ -45,6 +45,13 @@ export class CapabilitiesGroup { }); return this[key]; } + + public static getFlattenedCapabilities(capabilitiesGroup: CapabilitiesGroup): Array { + return _.reduce( + _.toArray(capabilitiesGroup), + (allCaps, capArr) => allCaps.concat(capArr), + []); + } } export class Capability implements RequirementCapabilityModel{ diff --git a/catalog-ui/src/app/models/properties-inputs/property-be-model.ts b/catalog-ui/src/app/models/properties-inputs/property-be-model.ts index 15b9534b99..5d25142e5a 100644 --- a/catalog-ui/src/app/models/properties-inputs/property-be-model.ts +++ b/catalog-ui/src/app/models/properties-inputs/property-be-model.ts @@ -18,7 +18,7 @@ * ============LICENSE_END========================================================= */ -import { PropertyInputDetail, SchemaPropertyGroupModel, SchemaProperty } from "app/models"; +import {PropertyInputDetail, SchemaPropertyGroupModel, SchemaProperty, ToscaPresentationData} from "app/models"; import { PROPERTY_DATA, PROPERTY_TYPES } from 'app/utils'; export enum DerivedPropertyType { SIMPLE, @@ -47,6 +47,7 @@ export class PropertyBEModel { getInputValues: Array; getPolicyValues: Array; name: string; + origName: string; parentUniqueId: string; password: boolean; required: boolean; @@ -58,6 +59,7 @@ export class PropertyBEModel { parentPropertyType: string; subPropertyInputPath: string; inputPath: string; + toscaPresentation: ToscaPresentationData; constructor(property?: PropertyBEModel) { if (property) { @@ -66,6 +68,7 @@ export class PropertyBEModel { this.description = property.description; this.fromDerived = property.fromDerived; this.name = property.name; + this.origName = property.origName; this.parentUniqueId = property.parentUniqueId; this.password = property.password; this.required = property.required; @@ -78,6 +81,7 @@ export class PropertyBEModel { this.getInputValues = property.getInputValues; this.parentPropertyType = property.parentPropertyType; this.subPropertyInputPath = property.subPropertyInputPath; + this.toscaPresentation = property.toscaPresentation; this.getPolicyValues = property.getPolicyValues; this.inputPath = property.inputPath; } diff --git a/catalog-ui/src/app/models/properties-inputs/property-fe-model.ts b/catalog-ui/src/app/models/properties-inputs/property-fe-model.ts index c0af885d18..664d128313 100644 --- a/catalog-ui/src/app/models/properties-inputs/property-fe-model.ts +++ b/catalog-ui/src/app/models/properties-inputs/property-fe-model.ts @@ -40,6 +40,7 @@ export class PropertyFEModel extends PropertyBEModel { valueObjOrig: any; //this is valueObj representation as saved in server valueObjIsChanged: boolean; derivedDataType: DerivedPropertyType; + origName: string; constructor(property: PropertyBEModel){ super(property); @@ -52,6 +53,7 @@ export class PropertyFEModel extends PropertyBEModel { this.valueObj = null; this.updateValueObjOrig(); this.resetValueObjValidation(); + this.origName = this.name; } diff --git a/catalog-ui/src/app/models/tosca-presentation.ts b/catalog-ui/src/app/models/tosca-presentation.ts index 3fdddde448..7cdc5c6be5 100644 --- a/catalog-ui/src/app/models/tosca-presentation.ts +++ b/catalog-ui/src/app/models/tosca-presentation.ts @@ -21,6 +21,7 @@ export class ToscaPresentationData { validTargetTypes: Array; modificationTime: number; uniqueId: string; + ownerId: string; constructor(toscaPresentation?: ToscaPresentationData) { if (toscaPresentation) { @@ -30,6 +31,7 @@ export class ToscaPresentationData { this.validTargetTypes = toscaPresentation.validTargetTypes; this.modificationTime = toscaPresentation.modificationTime; this.uniqueId = toscaPresentation.uniqueId; + this.ownerId = toscaPresentation.ownerId; } } } diff --git a/catalog-ui/src/app/modules/directive-module.ts b/catalog-ui/src/app/modules/directive-module.ts index 126f99ff09..720d29f8ce 100644 --- a/catalog-ui/src/app/modules/directive-module.ts +++ b/catalog-ui/src/app/modules/directive-module.ts @@ -249,7 +249,7 @@ directiveModule.directive('ng2ServicePathSelector', downgradeComponent({ directiveModule.directive('ng2ServiceConsumption', downgradeComponent({ component: ServiceConsumptionComponent, - inputs: ['parentService', 'selectedService', 'selectedServiceInstanceId', 'instancesMappedList','parentServiceInputs', 'readonly'], + inputs: ['parentService', 'selectedService', 'selectedServiceInstanceId', 'instancesMappedList', 'parentServiceInputs', 'instancesCapabilitiesMap', 'readonly'], outputs: [] }) as angular.IDirectiveFactory); diff --git a/catalog-ui/src/app/ng2/components/logic/service-consumption/service-consumption.component.ts b/catalog-ui/src/app/ng2/components/logic/service-consumption/service-consumption.component.ts index ef8d63df97..ebcf9eba22 100644 --- a/catalog-ui/src/app/ng2/components/logic/service-consumption/service-consumption.component.ts +++ b/catalog-ui/src/app/ng2/components/logic/service-consumption/service-consumption.component.ts @@ -29,7 +29,9 @@ import { PropertyFEModel, PropertyBEModel, InputBEModel, - InterfaceModel + InterfaceModel, + CapabilitiesGroup, + Capability } from 'app/models'; import {ServiceConsumptionCreatorComponent} from 'app/ng2/pages/service-consumption-editor/service-consumption-editor.component'; @@ -59,6 +61,7 @@ export class ConsumptionInputDetails extends ConsumptionInput { assignValueLabel: string; associatedProps: Array; associatedInterfaces: Array; + associatedCapabilities: Array; origVal: string; isValid: boolean; @@ -70,6 +73,7 @@ export class ConsumptionInputDetails extends ConsumptionInput { this.assignValueLabel = input.assignValueLabel; this.associatedProps = input.associatedProps; this.associatedInterfaces = input.associatedInterfaces; + this.associatedCapabilities = input.associatedCapabilities; this.origVal = input.value || ""; this.isValid = input.isValid; } @@ -128,15 +132,18 @@ export class ServiceConsumptionComponent { @Input() selectedService: Service; @Input() selectedServiceInstanceId: string; @Input() instancesMappedList: Array; + @Input() instancesCapabilitiesMap: Map>; @Input() readonly: boolean; selectedInstanceSiblings: Array; selectedInstancePropertiesList: Array = []; + selectedInstanceCapabilitisList: Array = []; constructor(private ModalServiceNg2: ModalService, private serviceServiceNg2: ServiceServiceNg2, private componentServiceNg2: ComponentServiceNg2, private componentInstanceServiceNg2:ComponentInstanceServiceNg2) {} ngOnInit() { this.updateSelectedInstancePropertiesAndSiblings(); + this.updateSelectedServiceCapabilities(); } ngOnChanges(changes) { @@ -146,9 +153,11 @@ export class ServiceConsumptionComponent { this.selectedService = changes.selectedService.currentValue; } this.updateSelectedInstancePropertiesAndSiblings(); + this.updateSelectedServiceCapabilities(); } if(changes.instancesMappedList && !_.isEqual(changes.instancesMappedList.currentValue, changes.instancesMappedList.previousValue)) { this.updateSelectedInstancePropertiesAndSiblings(); + this.updateSelectedServiceCapabilities(); } } @@ -166,6 +175,13 @@ export class ServiceConsumptionComponent { this.selectedInstanceSiblings = _.filter(this.instancesMappedList, coInstance => coInstance.id !== this.selectedServiceInstanceId); } + updateSelectedServiceCapabilities() { + this.selectedInstanceCapabilitisList = _.filter( + CapabilitiesGroup.getFlattenedCapabilities(this.selectedService.capabilities), + cap => cap.properties && cap.ownerId === this.selectedService.uniqueId + ); + } + expandCollapseInterfaceGroup(currInterface) { currInterface.isExpanded = !currInterface.isExpanded; } @@ -190,7 +206,9 @@ export class ServiceConsumptionComponent { parentServiceInputs: this.parentServiceInputs, selectedServiceProperties: this.selectedInstancePropertiesList, selectedServiceInstanceId: this.selectedServiceInstanceId, - selectedInstanceSiblings: this.selectedInstanceSiblings + selectedInstanceSiblings: this.selectedInstanceSiblings, + selectedInstanceCapabilitisList: this.selectedInstanceCapabilitisList, + siblingsCapabilitiesList: this.instancesCapabilitiesMap } ); this.modalInstance.instance.open(); diff --git a/catalog-ui/src/app/ng2/pages/interface-operation/interface-operation.page.component.ts b/catalog-ui/src/app/ng2/pages/interface-operation/interface-operation.page.component.ts index 9db24b6071..c2a9582ed4 100644 --- a/catalog-ui/src/app/ng2/pages/interface-operation/interface-operation.page.component.ts +++ b/catalog-ui/src/app/ng2/pages/interface-operation/interface-operation.page.component.ts @@ -9,14 +9,20 @@ import {Observable} from "rxjs/Observable"; import {ModalComponent} from 'app/ng2/components/ui/modal/modal.component'; import {ModalService} from 'app/ng2/services/modal.service'; -import {ModalModel, ButtonModel, InputBEModel, OperationModel, InterfaceModel, WORKFLOW_ASSOCIATION_OPTIONS} from 'app/models'; +import { + InputBEModel, + OperationModel, + InterfaceModel, + WORKFLOW_ASSOCIATION_OPTIONS, + CapabilitiesGroup, + Capability +} from 'app/models'; import {IModalConfig, IModalButtonComponent} from "sdc-ui/lib/angular/modals/models/modal-config"; import {SdcUiComponents} from "sdc-ui/lib/angular"; import {ModalButtonComponent} from "sdc-ui/lib/angular/components"; import {ComponentServiceNg2} from 'app/ng2/services/component-services/component.service'; -import {ComponentGenericResponse} from 'app/ng2/services/responses/component-generic-response'; import {WorkflowServiceNg2} from 'app/ng2/services/workflow.service'; import {PluginsService} from "app/ng2/services/plugins.service"; @@ -114,6 +120,7 @@ export class InterfaceOperationComponent { modalTranslation: ModalTranslation; workflowIsOnline: boolean; workflows: Array; + capabilities: CapabilitiesGroup; @Input() component: IComponent; @Input() readonly: boolean; @@ -141,7 +148,8 @@ export class InterfaceOperationComponent { Observable.forkJoin( this.ComponentServiceNg2.getInterfaces(this.component), this.ComponentServiceNg2.getComponentInputs(this.component), - this.ComponentServiceNg2.getInterfaceTypes(this.component) + this.ComponentServiceNg2.getInterfaceTypes(this.component), + this.ComponentServiceNg2.getCapabilitiesAndRequirements(this.component.componentType, this.component.uniqueId) ).subscribe((response: Array) => { const callback = (workflows) => { this.isLoading = false; @@ -150,6 +158,7 @@ export class InterfaceOperationComponent { this.inputs = response[1].inputs; this.interfaceTypes = response[2]; this.workflows = workflows; + this.capabilities = response[3].capabilities; }; if (this.enableWorkflowAssociation && this.workflowIsOnline) { this.WorkflowServiceNg2.getWorkflows().subscribe( @@ -267,7 +276,8 @@ export class InterfaceOperationComponent { readonly: this.readonly, interfaceTypes: this.interfaceTypes, validityChangedCallback: this.enableOrDisableSaveButton, - workflowIsOnline: this.workflowIsOnline + workflowIsOnline: this.workflowIsOnline, + capabilities: _.filter(CapabilitiesGroup.getFlattenedCapabilities(this.capabilities), (capability: Capability) => capability.ownerId === this.component.uniqueId) }; const modalConfig: IModalConfig = { diff --git a/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/operation-creator.component.html b/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/operation-creator.component.html index 8f70f7f584..ec056ad6f2 100644 --- a/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/operation-creator.component.html +++ b/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/operation-creator.component.html @@ -184,16 +184,17 @@ + *ngFor="let param of tableParameters" + class="data-row" + [isInputParam]="currentTab === TYPE_INPUT" + [isAssociateWorkflow]="isUsingExistingWF()" + [param]="param" + [inputProps]="inputProperties" + [capabilitiesProps]="componentCapabilities" + [operationOutputs]="operationOutputs" + [onRemoveParam]="onRemoveParam" + [readonly]="readonly" + [validityChanged]="validityChanged"> diff --git a/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/operation-creator.component.ts b/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/operation-creator.component.ts index a574460478..e12905654b 100644 --- a/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/operation-creator.component.ts +++ b/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/operation-creator.component.ts @@ -5,7 +5,15 @@ import {Subscription} from "rxjs/Subscription"; import {TranslateService} from "app/ng2/shared/translator/translate.service"; import {WorkflowServiceNg2} from 'app/ng2/services/workflow.service'; -import {InterfaceModel, OperationModel, OperationParameter, InputBEModel, RadioButtonModel, WORKFLOW_ASSOCIATION_OPTIONS} from 'app/models'; +import { + InterfaceModel, + OperationModel, + OperationParameter, + InputBEModel, + RadioButtonModel, + WORKFLOW_ASSOCIATION_OPTIONS, + Capability +} from 'app/models'; import {IDropDownOption} from "sdc-ui/lib/angular/form-elements/dropdown/dropdown-models"; import {Tabs, Tab} from "app/ng2/components/ui/tabs/tabs.component"; @@ -39,7 +47,8 @@ export interface OperationCreatorInput { readonly: boolean, interfaceTypes: { [interfaceType: string]: Array }, validityChangedCallback: Function, - workflowIsOnline: boolean; + workflowIsOnline: boolean, + capabilities: Array } @Component({ @@ -59,6 +68,7 @@ export class OperationCreatorComponent implements OperationCreatorInput { interfaceTypes: { [interfaceType: string]: Array }; operationNames: Array = []; validityChangedCallback: Function; + capabilities: Array; allWorkflows: Array; workflows: Array = []; @@ -73,6 +83,7 @@ export class OperationCreatorComponent implements OperationCreatorInput { outputParameters: Array = []; noAssignOutputParameters: Array = []; assignOutputParameters: { [key: string]: { [key: string]: Array; }; } = {}; + componentCapabilities: Array = []; tableParameters: Array = []; operationOutputs: Array = []; @@ -171,6 +182,7 @@ export class OperationCreatorComponent implements OperationCreatorInput { } } this.reconstructOperation(); + this.filterCapabilities(); this.validityChanged(); this.updateTable(); } @@ -217,6 +229,10 @@ export class OperationCreatorComponent implements OperationCreatorInput { } + filterCapabilities() { + this.componentCapabilities = _.filter(this.capabilities, (cap: Capability) => cap.properties); + } + buildParams = () => { if (this.inputOperation.outputs) { diff --git a/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/param-row/param-row.component.html b/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/param-row/param-row.component.html index 3ac9328487..4a4782eaee 100644 --- a/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/param-row/param-row.component.html +++ b/catalog-ui/src/app/ng2/pages/interface-operation/operation-creator/param-row/param-row.component.html @@ -58,6 +58,15 @@ {{output.label}} + + + ; @Input() operationOutputs: Array; + @Input() capabilitiesProps: Array; @Input() onRemoveParam: Function; @Input() isAssociateWorkflow: boolean; @Input() readonly: boolean; @@ -34,6 +34,7 @@ export class ParamRowComponent { propTypeEnum: Array = []; operationOutputCats: Array<{ operationName: string, outputs: Array }> = []; filteredInputProps: Array = []; + filteredCapabilitiesProps: Array<{capabilityName: string, properties: Array}> = []; constructor(private dataTypeService: DataTypeService) {} @@ -113,6 +114,26 @@ export class ParamRowComponent { category => category.outputs.length > 0 ); + this.filteredCapabilitiesProps = _.filter( + _.map( + this.capabilitiesProps, + cap => { + return { + capabilityName: cap.name, + properties: _.map( + _.filter(cap.properties, prop => !this.param.type || prop.type === this.param.type), + prop => new DropdownValueType( + prop.uniqueId, + prop.name, + prop.type + ) + ) + }; + } + ), + capability => capability.properties.length > 0 + ); + if (this.param.inputId) { const selProp = this.getSelectedProp(); if (selProp && selProp.type === this.param.type) { @@ -181,6 +202,12 @@ export class ParamRowComponent { (acc, cat) => [...acc, ...cat.outputs], []), (out: DropdownValueType) => this.param.inputId === out.value + ) || _.find( + _.reduce( + this.filteredCapabilitiesProps, + (acc, cap) => [...acc, ...cap.properties], + []), + (prop: DropdownValueType) => this.param.inputId === prop.value ); } diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.ts b/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.ts index 9f406f8c76..061439800f 100644 --- a/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.ts +++ b/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.ts @@ -21,11 +21,32 @@ import * as _ from "lodash"; import {Component, ViewChild, Inject, TemplateRef} from "@angular/core"; import { PropertiesService } from "../../services/properties.service"; -import { PropertyFEModel, InstanceFePropertiesMap, InstanceBePropertiesMap, InstancePropertiesAPIMap, Component as ComponentData, FilterPropertiesAssignmentData, ModalModel, ButtonModel } from "app/models"; +import { + PropertyFEModel, + InstanceFePropertiesMap, + InstanceBePropertiesMap, + InstancePropertiesAPIMap, + Component as ComponentData, + FilterPropertiesAssignmentData, + ModalModel, + ButtonModel, + Capability, + ToscaPresentationData +} from "app/models"; import { ResourceType } from "app/utils"; import {ComponentServiceNg2} from "../../services/component-services/component.service"; import {ComponentInstanceServiceNg2} from "../../services/component-instance-services/component-instance.service" -import { InputBEModel, InputFEModel, ComponentInstance, GroupInstance, PolicyInstance, PropertyBEModel, DerivedFEProperty, SimpleFlatProperty } from "app/models"; +import { + InputBEModel, + InputFEModel, + ComponentInstance, + GroupInstance, + PolicyInstance, + PropertyBEModel, + DerivedFEProperty, + SimpleFlatProperty, + CapabilitiesGroup +} from "app/models"; import { KeysPipe } from 'app/ng2/pipes/keys.pipe'; import {WorkspaceMode, EVENTS} from "../../../utils/constants"; import {EventListenerService} from "app/services/event-listener-service" @@ -45,6 +66,7 @@ import { SdcUiComponents } from "sdc-ui/lib/angular"; //import { ModalService as ModalServiceSdcUI} from "sdc-ui/lib/angular/modals/modal.service"; import { IModalButtonComponent } from "sdc-ui/lib/angular/modals/models/modal-config"; import { UnsavedChangesComponent } from "app/ng2/components/ui/forms/unsaved-changes/unsaved-changes.component"; +import {Observable} from "rxjs"; import { DataTypeService } from "app/ng2/services/data-type.service"; import { DataTypeModel } from "app/models"; import { PROPERTY_DATA, PROPERTY_TYPES } from "app/utils"; @@ -96,6 +118,8 @@ export class PropertiesAssignmentComponent { savingChangedData:boolean; stateChangeStartUnregister:Function; serviceBePropertiesMap: InstanceBePropertiesMap; + serviceBeCapabilitiesPropertiesMap: InstanceBePropertiesMap; + selectedInstance_FlattenCapabilitiesList: Array; @ViewChild('hierarchyNavTabs') hierarchyNavTabs: Tabs; @ViewChild('propertyInputTabs') propertyInputTabs: Tabs; @@ -243,12 +267,14 @@ export class PropertiesAssignmentComponent { this.loadingProperties = true; if (instance instanceof ComponentInstance) { let instanceBePropertiesMap: InstanceBePropertiesMap = new InstanceBePropertiesMap(); + this.selectedInstance_FlattenCapabilitiesList = instance.capabilities ? CapabilitiesGroup.getFlattenedCapabilities(instance.capabilities) : []; if (this.isInput(instance.originType)) { this.componentInstanceServiceNg2 .getComponentInstanceInputs(this.component, instance) .subscribe(response => { instanceBePropertiesMap[instance.uniqueId] = response; this.processInstancePropertiesResponse(instanceBePropertiesMap, true); + this.processInstanceCapabilitiesPropertiesResponse(false); this.loadingProperties = false; }, error => { }); //ignore error @@ -260,6 +286,7 @@ export class PropertiesAssignmentComponent { .subscribe(response => { instanceBePropertiesMap[instance.uniqueId] = response; this.processInstancePropertiesResponse(instanceBePropertiesMap, false); + this.processInstanceCapabilitiesPropertiesResponse(false); this.loadingProperties = false; }, error => { }); //ignore error @@ -305,6 +332,40 @@ export class PropertiesAssignmentComponent { this.checkedChildPropertiesCount = 0; }; + processInstanceCapabilitiesPropertiesResponse = (originTypeIsVF: boolean) => { + let selectedComponentInstanceData = (this.selectedInstanceData); + let currentUniqueId = this.selectedInstanceData.uniqueId; + this.serviceBeCapabilitiesPropertiesMap = new InstanceBePropertiesMap(); + let isCapabilityOwnedByInstance: boolean; + this.serviceBeCapabilitiesPropertiesMap[currentUniqueId] = _.reduce( + this.selectedInstance_FlattenCapabilitiesList, + (result, cap: Capability) => { + isCapabilityOwnedByInstance = cap.ownerId === currentUniqueId || + selectedComponentInstanceData.isServiceProxy() && cap.ownerId === selectedComponentInstanceData.sourceModelUid; + if (cap.properties && isCapabilityOwnedByInstance) { + _.forEach(cap.properties, prop => { + if (!prop.origName) { + prop.origName = prop.name; + prop.name = cap.name + '_' + prop.name;//for display. (before save - the name returns to its orig value: prop.name) + } + }); + return result.concat(cap.properties); + } + return result; + }, []); + let instanceFECapabilitiesPropertiesMap = this.propertiesUtils.convertPropertiesMapToFEAndCreateChildren(this.serviceBeCapabilitiesPropertiesMap, originTypeIsVF, this.inputs); //create flattened children, disable declared props, and init values + //update FECapabilitiesProperties with their origName according to BeCapabilitiesProperties + _.forEach(instanceFECapabilitiesPropertiesMap[currentUniqueId], prop => { + prop.origName = _.find(this.serviceBeCapabilitiesPropertiesMap[currentUniqueId], p => p.uniqueId === prop.uniqueId).origName; + }); + //concatenate capabilitiesProps to all props list + this.instanceFePropertiesMap[currentUniqueId] = (this.instanceFePropertiesMap[currentUniqueId] || []).concat(instanceFECapabilitiesPropertiesMap[currentUniqueId]); + this.checkedPropertiesCount = 0; + }; + + isCapabilityProperty = (prop: PropertyBEModel) => { + return _.find(this.selectedInstance_FlattenCapabilitiesList, cap => cap.uniqueId === prop.parentUniqueId); + }; /*** VALUE CHANGE EVENTS ***/ dataChanged = (item:PropertyFEModel|InputFEModel) => { @@ -439,6 +500,33 @@ export class PropertiesAssignmentComponent { let inputsToCreate: InstancePropertiesAPIMap = new InstancePropertiesAPIMap(selectedComponentInstancesInputs, selectedComponentInstancesProperties, selectedGroupInstancesProperties, selectedPolicyInstancesProperties); + //move changed capabilities properties from componentInstanceInputsMap obj to componentInstanceProperties + inputsToCreate.componentInstanceProperties[this.selectedInstanceData.uniqueId] = + (inputsToCreate.componentInstanceProperties[this.selectedInstanceData.uniqueId] || []).concat( + _.filter( + inputsToCreate.componentInstanceInputsMap[this.selectedInstanceData.uniqueId], + (prop: PropertyBEModel) => this.isCapabilityProperty(prop) + ) + ); + inputsToCreate.componentInstanceInputsMap[this.selectedInstanceData.uniqueId] = _.filter( + inputsToCreate.componentInstanceInputsMap[this.selectedInstanceData.uniqueId], + prop => !this.isCapabilityProperty(prop) + ); + if (inputsToCreate.componentInstanceInputsMap[this.selectedInstanceData.uniqueId].length === 0) { + delete inputsToCreate.componentInstanceInputsMap[this.selectedInstanceData.uniqueId]; + } + + let isCapabilityPropertyChanged = false; + _.forEach( + inputsToCreate.componentInstanceProperties[this.selectedInstanceData.uniqueId], + (prop: PropertyBEModel) => { + prop.name = prop.origName || prop.name; + if (this.isCapabilityProperty(prop)) { + isCapabilityPropertyChanged = true; + } + } + ); + this.componentServiceNg2 .createInput(this.component, inputsToCreate, this.isSelf()) .subscribe(response => { @@ -451,6 +539,9 @@ export class PropertiesAssignmentComponent { this.inputs.push(newInput); this.updatePropertyValueAfterDeclare(newInput); }); + if (isCapabilityPropertyChanged) { + this.reloadInstanceCapabilities(); + } }, error => {}); //ignore error }; @@ -625,18 +716,37 @@ export class PropertiesAssignmentComponent { // make request and its handlers let request; let handleSuccess, handleError; + let changedInputsProperties = [], changedCapabilitiesProperties = []; if (this.isPropertiesTabSelected) { const changedProperties: PropertyBEModel[] = this.changedData.map((changedProp) => { changedProp = changedProp; const propBE = new PropertyBEModel(changedProp); + propBE.toscaPresentation = new ToscaPresentationData(); + propBE.toscaPresentation.ownerId = changedProp.parentUniqueId; propBE.value = changedProp.getJSONValue(); + propBE.name = changedProp.origName || changedProp.name; + delete propBE.origName; return propBE; }); + changedCapabilitiesProperties = _.filter(changedProperties, prop => this.isCapabilityProperty(prop)); if (this.selectedInstanceData instanceof ComponentInstance) { if (this.isInput(this.selectedInstanceData.originType)) { - request = this.componentInstanceServiceNg2 - .updateInstanceInputs(this.component, this.selectedInstanceData.uniqueId, changedProperties); + changedInputsProperties = _.filter(changedProperties, prop => !this.isCapabilityProperty(prop)); + if (changedInputsProperties.length && changedCapabilitiesProperties.length) { + request = Observable.forkJoin( + this.componentInstanceServiceNg2.updateInstanceInputs(this.component, this.selectedInstanceData.uniqueId, changedInputsProperties), + this.componentInstanceServiceNg2.updateInstanceProperties(this.component, this.selectedInstanceData.uniqueId, changedCapabilitiesProperties) + ); + } + else if (changedInputsProperties.length) { + request = this.componentInstanceServiceNg2 + .updateInstanceInputs(this.component, this.selectedInstanceData.uniqueId, changedInputsProperties); + } + else if (changedCapabilitiesProperties.length) { + request = this.componentInstanceServiceNg2 + .updateInstanceProperties(this.component, this.selectedInstanceData.uniqueId, changedCapabilitiesProperties); + } handleSuccess = (response) => { // reset each changed property with new value and remove it from changed properties list response.forEach((resInput) => { @@ -714,6 +824,9 @@ export class PropertiesAssignmentComponent { request.subscribe( (response) => { this.savingChangedData = false; + if (changedCapabilitiesProperties.length) { + this.reloadInstanceCapabilities(); + } handleSuccess && handleSuccess(response); this.updateHasChangedData(); resolve(response); @@ -728,6 +841,19 @@ export class PropertiesAssignmentComponent { }); }; + reloadInstanceCapabilities = (): void => { + let currentInstanceIndex = _.findIndex(this.instances, instance => instance.uniqueId == this.selectedInstanceData.uniqueId); + this.componentServiceNg2.getComponentResourceInstances(this.component).subscribe(result => { + let instanceCapabilitiesData: CapabilitiesGroup = _.reduce(result.componentInstances, (res, instance) => { + if (instance.uniqueId === this.selectedInstanceData.uniqueId) { + return instance.capabilities; + } + return res; + }, new CapabilitiesGroup()); + (this.instances[currentInstanceIndex]).capabilities = instanceCapabilitiesData; + }); + }; + reverseChangedData = ():void => { // make reverse item handler let handleReverseItem; @@ -814,8 +940,10 @@ export class PropertiesAssignmentComponent { updatePropertyValueAfterDeclare = (input: InputFEModel) => { if (this.instanceFePropertiesMap[input.instanceUniqueId]) { + let instanceName = input.instanceUniqueId.slice(input.instanceUniqueId.lastIndexOf('.') + 1); let propertyForUpdatindVal = _.find(this.instanceFePropertiesMap[input.instanceUniqueId], (feProperty: PropertyFEModel) => { - return feProperty.name == input.relatedPropertyName; + return feProperty.uniqueId === input.propertyId && + (feProperty.name == input.relatedPropertyName || input.name === instanceName.concat('_').concat(feProperty.name.replace(/[.]/g, '_'))); }); let inputPath = (input.inputPath && input.inputPath != propertyForUpdatindVal.name) ? input.inputPath : undefined; propertyForUpdatindVal.setAsDeclared(inputPath); //set prop as declared before assigning value diff --git a/catalog-ui/src/app/ng2/pages/req-and-capabilities-editor/capabilities-editor/capabilities-editor.component.ts b/catalog-ui/src/app/ng2/pages/req-and-capabilities-editor/capabilities-editor/capabilities-editor.component.ts index 82e2e464cc..32a73efa85 100644 --- a/catalog-ui/src/app/ng2/pages/req-and-capabilities-editor/capabilities-editor/capabilities-editor.component.ts +++ b/catalog-ui/src/app/ng2/pages/req-and-capabilities-editor/capabilities-editor/capabilities-editor.component.ts @@ -62,6 +62,10 @@ export class CapabilitiesEditorComponent { let selectedCapabilityTypeObj: CapabilityTypeModel = this.input.capabilityTypesList.find(capType => capType.toscaPresentation.type === selectedCapType.value); this.capabilityData.description = selectedCapabilityTypeObj.toscaPresentation.description; this.capabilityData.validSourceTypes = selectedCapabilityTypeObj.toscaPresentation.validTargetTypes; + this.capabilityData.properties = _.forEach( + _.toArray(selectedCapabilityTypeObj.properties), + prop => prop.uniqueId = null //a requirement for the BE + ); } this.validityChanged(); } diff --git a/catalog-ui/src/app/ng2/pages/service-consumption-editor/service-consumption-editor.component.html b/catalog-ui/src/app/ng2/pages/service-consumption-editor/service-consumption-editor.component.html index e77d880176..2c4e2886a1 100644 --- a/catalog-ui/src/app/ng2/pages/service-consumption-editor/service-consumption-editor.component.html +++ b/catalog-ui/src/app/ng2/pages/service-consumption-editor/service-consumption-editor.component.html @@ -77,6 +77,15 @@ {{output.name}} + + + diff --git a/catalog-ui/src/app/ng2/pages/service-consumption-editor/service-consumption-editor.component.ts b/catalog-ui/src/app/ng2/pages/service-consumption-editor/service-consumption-editor.component.ts index 25f412671f..2c86cc5c5c 100644 --- a/catalog-ui/src/app/ng2/pages/service-consumption-editor/service-consumption-editor.component.ts +++ b/catalog-ui/src/app/ng2/pages/service-consumption-editor/service-consumption-editor.component.ts @@ -17,7 +17,17 @@ import * as _ from "lodash"; import { Component } from '@angular/core'; import {ServiceServiceNg2} from "app/ng2/services/component-services/service.service"; -import {Service, ServiceInstanceObject, InstanceFePropertiesMap, InstanceBePropertiesMap, PropertyBEModel, InputBEModel, OperationModel, InterfaceModel} from 'app/models'; +import { + Service, + ServiceInstanceObject, + InstanceFePropertiesMap, + InstanceBePropertiesMap, + PropertyBEModel, + InputBEModel, + OperationModel, + InterfaceModel, + Capability +} from 'app/models'; import {ConsumptionInput, ConsumptionInputDetails, ServiceOperation} from 'app/ng2/components/logic/service-consumption/service-consumption.component'; import {PropertiesUtils} from "app/ng2/pages/properties-assignment/services/properties.utils"; import { PROPERTY_DATA } from 'app/utils'; @@ -33,7 +43,7 @@ import { PROPERTY_DATA } from 'app/utils'; export class ServiceConsumptionCreatorComponent { input: { - interfaceId: string; + interfaceId: string, serviceOperationIndex: number, serviceOperations: Array, parentService: Service, @@ -41,7 +51,9 @@ export class ServiceConsumptionCreatorComponent { parentServiceInputs: Array, selectedServiceProperties: Array, selectedServiceInstanceId: String, - selectedInstanceSiblings: Array + selectedInstanceSiblings: Array, + selectedInstanceCapabilitisList: Array, + siblingsCapabilitiesList: Map> }; sourceTypes: Array = []; serviceOperationsList: Array; @@ -80,16 +92,24 @@ export class ServiceConsumptionCreatorComponent { initSourceTypes() { this.sourceTypes = [ - { label: this.SOURCE_TYPES.STATIC, value: this.SOURCE_TYPES.STATIC, options: [], interfaces: []}, + { + label: this.SOURCE_TYPES.STATIC, + value: this.SOURCE_TYPES.STATIC, + options: [], + interfaces: [], + capabilities: [] + }, { label: this.SOURCE_TYPES.SELF + ' (' + this.selectedService.name + ')', value: this.selectedServiceInstanceId, options: this.selectedServiceProperties, - interfaces: this.selectedService.interfaces + interfaces: this.selectedService.interfaces, + capabilities: this.input.selectedInstanceCapabilitisList }, { label: this.parentService.name, value: this.parentService.uniqueId, options: this.parentServiceInputs, - interfaces: [] + interfaces: [], + capabilities: [] } ]; _.forEach(this.input.selectedInstanceSiblings, sib => @@ -97,7 +117,8 @@ export class ServiceConsumptionCreatorComponent { label: sib.name, value: sib.id, options: _.unionBy(sib.inputs, sib.properties, 'uniqueId'), - interfaces: sib.interfaces + interfaces: sib.interfaces, + capabilities: this.input.siblingsCapabilitiesList[sib.id] }) ); } @@ -160,6 +181,7 @@ export class ServiceConsumptionCreatorComponent { consumptionInputDetails.assignValueLabel = this.getAssignValueLabel(sourceVal); consumptionInputDetails.associatedProps = filteredListsObj.associatedPropsList; consumptionInputDetails.associatedInterfaces = filteredListsObj.associatedInterfacesList; + consumptionInputDetails.associatedCapabilities = filteredListsObj.associatedCapabilitiesList; return new ConsumptionInputDetails(consumptionInputDetails); }); } @@ -171,6 +193,7 @@ export class ServiceConsumptionCreatorComponent { let filteredListsObj = this.getFilteredProps(consumptionInput.source, consumptionInput.type); consumptionInput.associatedProps = filteredListsObj.associatedPropsList; consumptionInput.associatedInterfaces = filteredListsObj.associatedInterfacesList; + consumptionInput.associatedCapabilities = filteredListsObj.associatedCapabilitiesList; if(consumptionInput.source === this.SOURCE_TYPES.STATIC) { if(PROPERTY_DATA.SIMPLE_TYPES.indexOf(consumptionInput.type) !== -1) { consumptionInput.value = consumptionInput.defaultValue || ""; @@ -184,7 +207,7 @@ export class ServiceConsumptionCreatorComponent { private getFilteredProps(sourceVal, inputType) { let currentSourceObj = this.sourceTypes.find(s => s.value === sourceVal); - let associatedInterfacesList = [], associatedPropsList = []; + let associatedInterfacesList = [], associatedPropsList = [], associatedCapabilitiesPropsList: Array = []; if(currentSourceObj) { if (currentSourceObj.interfaces) { associatedInterfacesList = this.getFilteredInterfaceOutputs(currentSourceObj, inputType); @@ -195,10 +218,22 @@ export class ServiceConsumptionCreatorComponent { } return result; }, []); + associatedCapabilitiesPropsList = + _.reduce(currentSourceObj.capabilities, + (filteredCapsList, capability: Capability) => { + let filteredProps = _.filter(capability.properties, prop => prop.type === inputType); + if (filteredProps.length) { + let cap = new Capability(capability); + cap.properties = filteredProps; + filteredCapsList.push(cap); + } + return filteredCapsList + }, []); } return { associatedPropsList: associatedPropsList, - associatedInterfacesList: associatedInterfacesList + associatedInterfacesList: associatedInterfacesList, + associatedCapabilitiesList: associatedCapabilitiesPropsList } } diff --git a/catalog-ui/src/app/ng2/services/component-services/service.service.ts b/catalog-ui/src/app/ng2/services/component-services/service.service.ts index 406ac77ec4..dce4e814ec 100644 --- a/catalog-ui/src/app/ng2/services/component-services/service.service.ts +++ b/catalog-ui/src/app/ng2/services/component-services/service.service.ts @@ -115,7 +115,9 @@ export class ServiceServiceNg2 extends ComponentServiceNg2 { COMPONENT_FIELDS.COMPONENT_INSTANCES_INTERFACES, COMPONENT_FIELDS.COMPONENT_INSTANCES_PROPERTIES, COMPONENT_FIELDS.COMPONENT_INSTANCES_INPUTS, - COMPONENT_FIELDS.COMPONENT_INPUTS + COMPONENT_FIELDS.COMPONENT_INPUTS, + COMPONENT_FIELDS.COMPONENT_INSTANCES, + COMPONENT_FIELDS.COMPONENT_CAPABILITIES ]); } diff --git a/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/service-consumption/service-consumption-view-model.ts b/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/service-consumption/service-consumption-view-model.ts index 20e99b0d39..737002303b 100644 --- a/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/service-consumption/service-consumption-view-model.ts +++ b/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/service-consumption/service-consumption-view-model.ts @@ -16,7 +16,17 @@ import {ICompositionViewModelScope} from "../../composition-view-model"; -import {Service, PropertiesGroup, InputsGroup, ServiceInstanceObject, InterfaceModel, InputBEModel} from 'app/models'; +import { + Service, + PropertiesGroup, + InputsGroup, + ServiceInstanceObject, + InterfaceModel, + InputBEModel, + CapabilitiesGroup, + Capability, + ComponentInstance +} from 'app/models'; import {ComponentGenericResponse} from "app/ng2/services/responses/component-generic-response"; import {ServiceServiceNg2} from "app/ng2/services/component-services/service.service"; @@ -27,6 +37,8 @@ interface IServiceConsumptionViewModelScope extends ICompositionViewModelScope { componentInstancesInputs: InputsGroup; componentInstancesInterfaces: Map>; componentInputs: Array; + componentCapabilities: Array; + instancesCapabilitiesMap: Map>; } @@ -49,10 +61,20 @@ export class ServiceConsumptionViewModel { this.$scope.componentInstancesInputs = genericResponse.componentInstancesInputs; this.$scope.componentInstancesInterfaces = genericResponse.componentInstancesInterfaces; this.$scope.componentInputs = genericResponse.inputs; + this.buildInstancesCapabilitiesMap(genericResponse.componentInstances); this.updateInstanceAttributes(); }); } + buildInstancesCapabilitiesMap = (componentInstances: Array): void => { + this.$scope.instancesCapabilitiesMap = new Map(); + let flattenCapabilities = []; + _.forEach(componentInstances, componentInstance => { + flattenCapabilities = CapabilitiesGroup.getFlattenedCapabilities(componentInstance.capabilities); + this.$scope.instancesCapabilitiesMap[componentInstance.uniqueId] = _.filter(flattenCapabilities, cap => cap.properties && cap.ownerId === componentInstance.uniqueId); + }); + } + private updateInstanceAttributes = ():void => { if (this.$scope.isComponentInstanceSelected() && this.$scope.componentInstancesProperties) { this.$scope.instancesMappedList = this.$scope.service.componentInstances.map(coInstance => new ServiceInstanceObject({ diff --git a/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/service-consumption/service-consumption-view.html b/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/service-consumption/service-consumption-view.html index 835ded33f6..8404a7f653 100644 --- a/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/service-consumption/service-consumption-view.html +++ b/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/service-consumption/service-consumption-view.html @@ -14,6 +14,7 @@ [selected-service-instance-id]="currentComponent.selectedInstance.uniqueId" [instances-mapped-list]="instancesMappedList" [parent-service-inputs]="componentInputs" + [instances-capabilities-map]="instancesCapabilitiesMap" [readonly]="isViewMode() || !isDesigner()"> diff --git a/catalog-ui/src/app/view-models/workspace/tabs/req-and-capabilities/req-and-capabilities-editable-view.html b/catalog-ui/src/app/view-models/workspace/tabs/req-and-capabilities/req-and-capabilities-editable-view.html index 14bc49e28b..8e1822193b 100644 --- a/catalog-ui/src/app/view-models/workspace/tabs/req-and-capabilities/req-and-capabilities-editable-view.html +++ b/catalog-ui/src/app/view-models/workspace/tabs/req-and-capabilities/req-and-capabilities-editable-view.html @@ -96,8 +96,8 @@
- {{req.name}} + tooltip-content="{{(!req.isCreatedManually ? req.ownerName + '.' : '') + req.name}}"> + {{(!req.isCreatedManually ? req.ownerName + '.' : '') + req.name}}
@@ -148,17 +148,22 @@
There are no capabilities to display -
-
- {{capability.name}} + tooltip-content="{{(!capability.isCreatedManually ? capability.ownerName + '.' : '') + capability.name}}"> + + + {{(!capability.isCreatedManually ? capability.ownerName + '.' : '') + capability.name}} +
@@ -188,6 +193,51 @@ data-ng-click="onDeleteCap($event, capability)">
+
+

Properties

+
+
+
+
+ {{header.title}} + +
+
+ +
+
+
+ {{property.name}} +
+
+ {{property.type}} +
+
+ {{property.schema.property.type}} +
+
+ {{property.description}} +
+
+
+ +
+
+
diff --git a/catalog-ui/src/app/view-models/workspace/tabs/req-and-capabilities/req-and-capabilities.less b/catalog-ui/src/app/view-models/workspace/tabs/req-and-capabilities/req-and-capabilities.less index fa6623f089..928f6719c6 100644 --- a/catalog-ui/src/app/view-models/workspace/tabs/req-and-capabilities/req-and-capabilities.less +++ b/catalog-ui/src/app/view-models/workspace/tabs/req-and-capabilities/req-and-capabilities.less @@ -319,63 +319,100 @@ } } } - .table-container-flex .table .head .head-row { - text-align: left; - &.description { - flex: 2; - } - &.other { - flex: 0.25; - text-align: center; - } - &.occurrences { - flex: 0.75; - } - } - .data-row { - .ellipsis-text { - overflow: hidden; - text-overflow: ellipsis; - } - &:not(.editable-row) { - background: @tlv_color_t; - cursor: default; - color: @main_color_n; - } - &.editable-row { - cursor: pointer; - .table-col-general:hover { - color: @main_color_b; + .table-container-flex .table { + .head .head-row { + text-align: left; + &.description { + flex: 2; } - } - .description-col { - flex: 2; - } - .occurrences-col { - flex: 0.75; - } - .other-col { - display: flex; - justify-content: center; - align-items: center; - flex: 0.25; - .trash-icon { - visibility: hidden; + &.other { + flex: 0.25; + text-align: center; + } + &.occurrences { + flex: 0.75; } } - &:hover { - .trash-icon { - visibility: visible; + .body .data-row { + border-bottom: none; + border-top: @main_color_o solid 1px; + .ellipsis-text { + overflow: hidden; + text-overflow: ellipsis; + } + &:not(.editable-row) { + background-color: @tlv_color_t; + cursor: default; + color: @main_color_n; + } + &.editable-row { + cursor: pointer; + .table-col-general:hover { + color: @main_color_b; + } + } + &.selected { + background-color: @tlv_color_v; + .name-col { + color: @main_color_a; + } + .sprite-new.arrow-up-small { + background-position: -858px -137px; + margin-bottom: 2px; + } } + .description-col { + flex: 2; + } + .occurrences-col { + flex: 0.75; + } + .other-col { + display: flex; + justify-content: center; + align-items: center; + flex: 0.25; + .trash-icon { + visibility: hidden; + } + } + &:hover { + .trash-icon { + visibility: visible; + } + } + .multiline-ellipsis { + line-height: 1.5em; + padding: 1px 0 1px 0; + /deep/ .ellipsis-directive-more-less { + float: none; + margin-left: 5px; + color: @main_color_a; + } + } + } + } + + .item-opened.properties-section { + border: 4px solid @tlv_color_v !important; + max-height: 263px; + overflow: auto; + .properties-title { + .s_10; + margin-top: 10px; } - .multiline-ellipsis { - line-height: 1.5em; - padding: 1px 0 1px 0; - /deep/ .ellipsis-directive-more-less { - float: none; - margin-left: 5px; - color: @main_color_a; + .properties-table { + &.table-container-flex { + margin-top: 18px; + } + .table { + .head { + border-bottom: 1px solid @main_color_o; + } + .head, .table-col-general { + background-color: @main_color_p; + } } } } -} +} \ No newline at end of file diff --git a/catalog-ui/src/assets/styles/mixins_old.less b/catalog-ui/src/assets/styles/mixins_old.less index 7deed223df..0e32684282 100644 --- a/catalog-ui/src/assets/styles/mixins_old.less +++ b/catalog-ui/src/assets/styles/mixins_old.less @@ -244,6 +244,11 @@ /* Added by ikram - */ .s_1 {.font-color > .s; .font-type > ._1;} + +.s_10 { + .font-color > .s; + .font-type > ._10; +} .s_12 {.font-color > .s; .font-type > ._12;} .z_9 {.font-color > .z; .font-type > ._9;} 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 index ecdb48619b..18e3997bab 100644 --- 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 @@ -16,36 +16,45 @@ package org.openecomp.sdc.ci.tests.capability; +import fj.data.Either; import org.junit.Rule; import org.junit.rules.TestName; +import org.openecomp.sdc.be.datatypes.elements.SchemaDefinition; +import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum; +import org.openecomp.sdc.be.model.ComponentInstanceProperty; +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.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.AtomicOperationUtils; 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.ArrayList; 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.getResourceObject; import static org.openecomp.sdc.ci.tests.utils.general.AtomicOperationUtils.getServiceObject; +import static org.testng.AssertJUnit.fail; public class CapabilitiesTest extends ComponentBaseTest { @Rule - public static final TestName name = new TestName(); + public static TestName name = new TestName(); - private ServiceReqDetails component; - private User user = null; + private static User user = null; + private static Service service; + private static Resource resource; + private static Resource pnfResource; public CapabilitiesTest() { super(name, CapabilitiesTest.class.getName()); @@ -54,63 +63,297 @@ public class CapabilitiesTest extends ComponentBaseTest { @BeforeTest public void init() throws Exception { user = ElementFactory.getDefaultUser(UserRoleEnum.DESIGNER); - component = ElementFactory.getDefaultService(); - component.setName("comp_cap" + Math.random()); - ServiceRestUtils.createService(component, user); + + // Create default service + Either createDefaultServiceEither = + AtomicOperationUtils.createDefaultService(UserRoleEnum.DESIGNER, true); + if (createDefaultServiceEither.isRight()) { + fail("Error creating default service"); + } + service = createDefaultServiceEither.left().value(); + + // Create default resource + Either createDefaultResourceEither = + AtomicOperationUtils.createResourceByType(ResourceTypeEnum.VF, UserRoleEnum.DESIGNER, true); + if (createDefaultResourceEither.isRight()) { + fail("Error creating default resource"); + } + resource = createDefaultResourceEither.left().value(); + + // Create default PNF resource + Either createDefaultPNFResourceEither = + AtomicOperationUtils.createResourceByType(ResourceTypeEnum.PNF, UserRoleEnum.DESIGNER, true); + if (createDefaultPNFResourceEither.isRight()) { + fail("Error creating default pnf resource"); + } + pnfResource = createDefaultPNFResourceEither.left().value(); } @Test - public void createCapabilityTest() throws Exception { + public void createCapabilityOnServiceTest() throws Exception { CapabilityDetails capability = createCapability(); - RestResponse restResponse = CapabilityRestUtils.createCapability(component.getUniqueId(), - Collections.singletonList(capability), user); - logger.info("createCapability Response Code:" + restResponse.getErrorCode()); + RestResponse restResponse = CapabilityRestUtils.createCapability(service, Collections.singletonList(capability), + user); + logger.info("createCapability On Service Response Code:" + restResponse.getErrorCode()); + Assert.assertEquals((int) restResponse.getErrorCode(), BaseRestUtils.STATUS_CODE_SUCCESS); + } + + @Test(dependsOnMethods = "createCapabilityOnServiceTest") + public void updateCapabilityOnServiceTest() throws Exception { + + CapabilityDetails capability = createCapability(); + capability.setMaxOccurrences("10"); + capability.setMinOccurrences("4"); + RestResponse restResponse = CapabilityRestUtils.updateCapability(service, Collections.singletonList(capability), + user); + logger.info("updateCapability On Service Response Code:" + restResponse.getErrorCode()); + Assert.assertEquals((int) restResponse.getErrorCode(), BaseRestUtils.STATUS_CODE_SUCCESS); + } + + @Test(dependsOnMethods = "updateCapabilityOnServiceTest") + public void getCapabilityFromServiceTest() throws Exception { + Service serviceObject = getServiceObject(service.getUniqueId()); + + List capabilityDefinitionList = serviceObject.getCapabilities() + .values().stream().flatMap(Collection::stream).collect(Collectors.toList()); + + RestResponse restResponse = CapabilityRestUtils.getCapability(service, + capabilityDefinitionList.get(0).getUniqueId(), user); + logger.info("getCapabilityTest from Service Response Code:" + restResponse.getErrorCode()); Assert.assertEquals((int) restResponse.getErrorCode(), BaseRestUtils.STATUS_CODE_SUCCESS); } + @Test(dependsOnMethods = "getCapabilityFromServiceTest") + public void deleteCapabilityFromServiceTest() throws Exception { + Service serviceObject = getServiceObject(service.getUniqueId()); + + List capabilityDefinitionList = serviceObject.getCapabilities() + .values().stream().flatMap(Collection::stream).collect(Collectors.toList()); + RestResponse restResponse = CapabilityRestUtils.deleteCapability(service, + capabilityDefinitionList.get(0).getUniqueId(), user); + logger.info("deleteCapabilityTest from Service Response Code:" + restResponse.getErrorCode()); + Assert.assertEquals((int) restResponse.getErrorCode(), BaseRestUtils.STATUS_CODE_SUCCESS); + } - @Test(dependsOnMethods = "createCapabilityTest") - public void updateCapabilityTest() throws Exception { + @Test + public void createCapabilityWithPropertiesOnServiceTest() throws Exception { + + CapabilityDetails capability = createCapability(); + List properties = new ArrayList<>(); + ComponentInstanceProperty instanceProperty = new ComponentInstanceProperty(); + instanceProperty.setType("prop_type"); + instanceProperty.setName("prop_name"); + instanceProperty.setDescription("prop_description"); + instanceProperty.setSchema(new SchemaDefinition()); + properties.add(instanceProperty); + capability.setProperties(properties); + RestResponse restResponse = CapabilityRestUtils.createCapability(service, Collections.singletonList(capability), + user); + logger.info("createCapability On Service Response Code:" + restResponse.getErrorCode()); + Assert.assertEquals((int) restResponse.getErrorCode(), BaseRestUtils.STATUS_CODE_SUCCESS); + } + + @Test(dependsOnMethods = "createCapabilityWithPropertiesOnServiceTest") + public void updateCapabilityWithPropertiesOnServiceTest() 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()); + + List properties = new ArrayList<>(); + ComponentInstanceProperty instanceProperty = new ComponentInstanceProperty(); + instanceProperty.setType("prop_type_updated"); + instanceProperty.setName("prop_name_updated"); + instanceProperty.setDescription("prop_description_prop_desc"); + instanceProperty.setSchema(new SchemaDefinition()); + properties.add(instanceProperty); + capability.setProperties(properties); + RestResponse restResponse = CapabilityRestUtils.updateCapability(service, Collections.singletonList(capability), + user); + logger.info("updateCapability On Service Response Code:" + restResponse.getErrorCode()); + Assert.assertEquals((int) restResponse.getErrorCode(), BaseRestUtils.STATUS_CODE_SUCCESS); + } + + @Test + public void createCapabilityOnVfTest() throws Exception { + + CapabilityDetails capability = createCapability(); + RestResponse restResponse = CapabilityRestUtils.createCapability(resource, Collections.singletonList(capability), + user); + logger.info("createCapability On Vf Response Code:" + restResponse.getErrorCode()); + Assert.assertEquals((int) restResponse.getErrorCode(), BaseRestUtils.STATUS_CODE_SUCCESS); + } + + @Test(dependsOnMethods = "createCapabilityOnVfTest") + public void updateCapabilityOnVfTest() throws Exception { + + CapabilityDetails capability = createCapability(); + capability.setMaxOccurrences("10"); + capability.setMinOccurrences("4"); + RestResponse restResponse = CapabilityRestUtils.updateCapability(resource, Collections.singletonList(capability), + user); + logger.info("updateCapability On Vf Response Code:" + restResponse.getErrorCode()); + Assert.assertEquals((int) restResponse.getErrorCode(), BaseRestUtils.STATUS_CODE_SUCCESS); + } + + @Test(dependsOnMethods = "updateCapabilityOnVfTest") + public void getCapabilityFromVfTest() throws Exception { + Resource resourceObject = getResourceObject(resource.getUniqueId()); + + List capabilityDefinitionList = resourceObject.getCapabilities() + .values().stream().flatMap(Collection::stream).collect(Collectors.toList()); + + RestResponse restResponse = CapabilityRestUtils.getCapability(resource, + capabilityDefinitionList.get(0).getUniqueId(), user); + logger.info("getCapabilityTest from Vf Response Code:" + restResponse.getErrorCode()); + Assert.assertEquals((int) restResponse.getErrorCode(), BaseRestUtils.STATUS_CODE_SUCCESS); + } + + @Test(dependsOnMethods = "getCapabilityFromVfTest") + public void deleteCapabilityFromVfTest() throws Exception { + Resource resourceObject = getResourceObject(resource.getUniqueId()); + + List capabilityDefinitionList = resourceObject.getCapabilities() + .values().stream().flatMap(Collection::stream).collect(Collectors.toList()); + + RestResponse restResponse = CapabilityRestUtils.deleteCapability(resource, + capabilityDefinitionList.get(0).getUniqueId(), user); + logger.info("deleteCapabilityTest from Vf Response Code:" + restResponse.getErrorCode()); + Assert.assertEquals((int) restResponse.getErrorCode(), BaseRestUtils.STATUS_CODE_SUCCESS); + } + + @Test + public void createCapabilityWithPropertiesOnVfTest() throws Exception { + + CapabilityDetails capability = createCapability(); + List properties = new ArrayList<>(); + ComponentInstanceProperty instanceProperty = new ComponentInstanceProperty(); + instanceProperty.setType("prop_type"); + instanceProperty.setName("prop_name"); + instanceProperty.setDescription("prop_description"); + instanceProperty.setSchema(new SchemaDefinition()); + properties.add(instanceProperty); + capability.setProperties(properties); + RestResponse restResponse = CapabilityRestUtils.createCapability(resource, Collections.singletonList(capability), + user); + logger.info("createCapability On Vf 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()); + @Test(dependsOnMethods = "createCapabilityWithPropertiesOnVfTest") + public void updateCapabilityWithPropertiesOnVfTest() throws Exception { - List capabilityDefinitionList = service.getCapabilities().values() - .stream().flatMap(Collection::stream).collect(Collectors.toList()); + CapabilityDetails capability = createCapability(); + capability.setMaxOccurrences("10"); + capability.setMinOccurrences("4"); - RestResponse restResponse = CapabilityRestUtils.getCapability(component.getUniqueId(), - capabilityDefinitionList.get(0).getUniqueId(), user); - logger.info("getCapabilityTest Response Code:" + restResponse.getErrorCode()); + List properties = new ArrayList<>(); + ComponentInstanceProperty instanceProperty = new ComponentInstanceProperty(); + instanceProperty.setType("prop_type_updated"); + instanceProperty.setName("prop_name_updated"); + instanceProperty.setDescription("prop_description_prop_desc"); + instanceProperty.setSchema(new SchemaDefinition()); + properties.add(instanceProperty); + capability.setProperties(properties); + RestResponse restResponse = CapabilityRestUtils.updateCapability(resource, Collections.singletonList(capability), + user); + logger.info("updateCapability On Vf 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()); + @Test + public void createCapabilityOnPnfTest() throws Exception { + + CapabilityDetails capability = createCapability(); + RestResponse restResponse = CapabilityRestUtils.createCapability(pnfResource, Collections.singletonList(capability), + user); + logger.info("createCapability On Pnf Response Code:" + restResponse.getErrorCode()); + Assert.assertEquals((int) restResponse.getErrorCode(), BaseRestUtils.STATUS_CODE_SUCCESS); + } + + @Test(dependsOnMethods = "createCapabilityOnPnfTest") + public void updateCapabilityOnPnfTest() throws Exception { - RestResponse restResponse = CapabilityRestUtils.deleteCapability(component.getUniqueId(), - capabilityDefinitionList.get(0).getUniqueId(), user); - logger.info("deleteCapabilityTest Response Code:" + restResponse.getErrorCode()); + CapabilityDetails capability = createCapability(); + capability.setMaxOccurrences("10"); + capability.setMinOccurrences("4"); + RestResponse restResponse = CapabilityRestUtils.updateCapability(pnfResource, Collections.singletonList(capability), + user); + logger.info("updateCapability On Pnf Response Code:" + restResponse.getErrorCode()); Assert.assertEquals((int) restResponse.getErrorCode(), BaseRestUtils.STATUS_CODE_SUCCESS); } - private CapabilityDetails createCapability() { - CapabilityDetails capabilityDetails = new CapabilityDetails(); + @Test(dependsOnMethods = "updateCapabilityOnPnfTest") + public void getCapabilityFromPnfTest() throws Exception { + Resource pnfResourceObject = getResourceObject(pnfResource.getUniqueId()); + + List capabilityDefinitionList = pnfResourceObject.getCapabilities() + .values().stream().flatMap(Collection::stream).collect(Collectors.toList()); + + RestResponse restResponse = CapabilityRestUtils.getCapability(pnfResource, + capabilityDefinitionList.get(0).getUniqueId(), user); + logger.info("getCapabilityTest from Pnf Response Code:" + restResponse.getErrorCode()); + Assert.assertEquals((int) restResponse.getErrorCode(), BaseRestUtils.STATUS_CODE_SUCCESS); + } + + @Test(dependsOnMethods = "getCapabilityFromPnfTest") + public void deleteCapabilityFromPnfTest() throws Exception { + Resource pnfResourceObject = getResourceObject(pnfResource.getUniqueId()); + + List capabilityDefinitionList = pnfResourceObject.getCapabilities() + .values().stream().flatMap(Collection::stream).collect(Collectors.toList()); + + RestResponse restResponse = CapabilityRestUtils.deleteCapability(pnfResource, + capabilityDefinitionList.get(0).getUniqueId(), user); + logger.info("deleteCapabilityTest from Pnf Response Code:" + restResponse.getErrorCode()); + Assert.assertEquals((int) restResponse.getErrorCode(), BaseRestUtils.STATUS_CODE_SUCCESS); + } + + @Test + public void createCapabilityWithPropertiesOnPnfTest() throws Exception { + + CapabilityDetails capability = createCapability(); + List properties = new ArrayList<>(); + ComponentInstanceProperty instanceProperty = new ComponentInstanceProperty(); + instanceProperty.setType("prop_type"); + instanceProperty.setName("prop_name"); + instanceProperty.setDescription("prop_description"); + instanceProperty.setSchema(new SchemaDefinition()); + properties.add(instanceProperty); + capability.setProperties(properties); + RestResponse restResponse = CapabilityRestUtils.createCapability(pnfResource, Collections.singletonList(capability), + user); + logger.info("createCapability On Pnf Response Code:" + restResponse.getErrorCode()); + Assert.assertEquals((int) restResponse.getErrorCode(), BaseRestUtils.STATUS_CODE_SUCCESS); + } + + @Test(dependsOnMethods = "createCapabilityWithPropertiesOnPnfTest") + public void updateCapabilityWithPropertiesOnPnfTest() throws Exception { + + CapabilityDetails capability = createCapability(); + capability.setMaxOccurrences("10"); + capability.setMinOccurrences("4"); + + List properties = new ArrayList<>(); + ComponentInstanceProperty instanceProperty = new ComponentInstanceProperty(); + instanceProperty.setType("prop_type_updated"); + instanceProperty.setName("prop_name_updated"); + instanceProperty.setDescription("prop_description_prop_desc"); + instanceProperty.setSchema(new SchemaDefinition()); + properties.add(instanceProperty); + capability.setProperties(properties); + RestResponse restResponse = CapabilityRestUtils.updateCapability(pnfResource, + Collections.singletonList(capability), user); + logger.info("updateCapability On Pnf 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"); 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 index 954a16a63d..bbed28b654 100644 --- 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 @@ -16,11 +16,16 @@ package org.openecomp.sdc.ci.tests.datatypes; +import org.openecomp.sdc.be.model.ComponentInstanceProperty; + +import java.util.List; + public class CapabilityDetails { private String name; private String type; private String maxOccurrences; private String minOccurrences; + private List properties; public String getName() { return name; @@ -53,4 +58,12 @@ public class CapabilityDetails { public void setMinOccurrences(String minOccurrences) { this.minOccurrences = minOccurrences; } + + public List getProperties() { + return properties; + } + + public void setProperties(List properties) { + this.properties = properties; + } } 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 index 1959aa8b9a..488ed249f5 100644 --- 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 @@ -17,6 +17,8 @@ package org.openecomp.sdc.ci.tests.utils.rest; import com.google.gson.Gson; +import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum; +import org.openecomp.sdc.be.model.Component; import org.openecomp.sdc.be.model.User; import org.openecomp.sdc.ci.tests.api.Urls; import org.openecomp.sdc.ci.tests.config.Config; @@ -27,14 +29,13 @@ 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, + public static RestResponse createCapability(Component component, List capabilityDetailsList, User user) throws Exception{ Config config = Config.instance(); String url = String.format(Urls.CREATE_CAPABILITY, config.getCatalogBeHost(), config.getCatalogBePort(), - COMPONENT_TYPE, componentId); + ComponentTypeEnum.findParamByType(component.getComponentType()), component.getUniqueId()); String data = "{ \"capabilities\" : {" + "\"" +capabilityDetailsList.get(0).getType()+ "\"" +" : " + gson.toJson(capabilityDetailsList) + " } }"; @@ -42,12 +43,12 @@ public class CapabilityRestUtils extends BaseRestUtils { return sendPost(url, data , user.getUserId(), acceptHeaderData); } - public static RestResponse updateCapability(String componentId, + public static RestResponse updateCapability(Component component, List capabilityDetailsList, User user) throws Exception{ Config config = Config.instance(); String url = String.format(Urls.UPDATE_CAPABILITY, config.getCatalogBeHost(), config.getCatalogBePort(), - COMPONENT_TYPE, componentId); + ComponentTypeEnum.findParamByType(component.getComponentType()), component.getUniqueId()); String data = "{ \"capabilities\" : {" + "\"" +capabilityDetailsList.get(0).getType()+ "\"" +" : " + gson.toJson(capabilityDetailsList) + " } }"; @@ -55,21 +56,21 @@ public class CapabilityRestUtils extends BaseRestUtils { return sendPost(url, data , user.getUserId(), acceptHeaderData); } - public static RestResponse deleteCapability(String componentId, + public static RestResponse deleteCapability(Component component, 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); + ComponentTypeEnum.findParamByType(component.getComponentType()), component.getUniqueId(), requirementId); return sendDelete(url, user.getUserId()); } - public static RestResponse getCapability(String componentId, + public static RestResponse getCapability(Component component, 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); + ComponentTypeEnum.findParamByType(component.getComponentType()), component.getUniqueId(), requirementId); return sendDelete(url, user.getUserId()); } -- cgit 1.2.3-korg