diff options
author | andre.schmid <andre.schmid@est.tech> | 2022-08-10 14:50:08 +0100 |
---|---|---|
committer | Vasyl Razinkov <vasyl.razinkov@est.tech> | 2022-09-08 18:24:44 +0000 |
commit | 92b18f188105d5ba4b2c469cdfaedc7d2953d593 (patch) | |
tree | df7c7562faa99a76b0e6b5bc079de8d514b35006 /catalog-be/src/main/java | |
parent | c0c2637f201f488a74cb1916f05eece0cc207e9d (diff) |
Support TOSCA functions in Node Filters
Adds support to use tosca functions as value in the node property
filters and substitution filters
Change-Id: Id242691cc9ddd233245b58f052b9f0e2c7bbd66b
Issue-ID: SDC-4128
Signed-off-by: André Schmid <andre.schmid@est.tech>
Diffstat (limited to 'catalog-be/src/main/java')
22 files changed, 1067 insertions, 691 deletions
diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/csar/YamlTemplateParsingHandler.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/csar/YamlTemplateParsingHandler.java index 25d5c1f43e..82aa1343c1 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/csar/YamlTemplateParsingHandler.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/csar/YamlTemplateParsingHandler.java @@ -103,7 +103,12 @@ import org.openecomp.sdc.be.datatypes.elements.OperationDataDefinition; import org.openecomp.sdc.be.datatypes.elements.OperationInputDefinition; import org.openecomp.sdc.be.datatypes.elements.PolicyTargetType; import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition; -import org.openecomp.sdc.be.datatypes.elements.RequirementSubstitutionFilterPropertyDataDefinition; +import org.openecomp.sdc.be.datatypes.elements.PropertyFilterConstraintDataDefinition; +import org.openecomp.sdc.be.datatypes.elements.SubstitutionFilterPropertyDataDefinition; +import org.openecomp.sdc.be.datatypes.elements.ToscaFunction; +import org.openecomp.sdc.be.datatypes.enums.ConstraintType; +import org.openecomp.sdc.be.datatypes.enums.FilterValueType; +import org.openecomp.sdc.be.datatypes.enums.PropertyFilterTargetType; import org.openecomp.sdc.be.model.CapabilityDefinition; import org.openecomp.sdc.be.model.Component; import org.openecomp.sdc.be.model.ComponentInstanceProperty; @@ -128,6 +133,7 @@ import org.openecomp.sdc.be.tosca.model.ToscaInterfaceDefinition; import org.openecomp.sdc.be.tosca.utils.OperationArtifactUtil; import org.openecomp.sdc.be.ui.model.OperationUi; import org.openecomp.sdc.be.ui.model.PropertyAssignmentUi; +import org.openecomp.sdc.be.utils.PropertyFilterConstraintDataDefinitionHelper; import org.openecomp.sdc.be.utils.TypeUtils; import org.openecomp.sdc.common.log.wrappers.Logger; import org.yaml.snakeyaml.parser.ParserException; @@ -236,8 +242,8 @@ public class YamlTemplateParsingHandler { return ImportUtils.getProperties(toscaJson).left().on(err -> new HashMap<>()); } - private ListDataDefinition<RequirementSubstitutionFilterPropertyDataDefinition> getSubstitutionFilterProperties(Map<String, Object> toscaJson) { - ListDataDefinition<RequirementSubstitutionFilterPropertyDataDefinition> propertyList = new ListDataDefinition<>(); + private ListDataDefinition<SubstitutionFilterPropertyDataDefinition> getSubstitutionFilterProperties(Map<String, Object> toscaJson) { + ListDataDefinition<SubstitutionFilterPropertyDataDefinition> propertyList = new ListDataDefinition<>(); Map<String, Object> substitutionFilters = findFirstToscaMapElement(toscaJson, SUBSTITUTION_FILTERS).left().on(err -> new HashMap<>()); if (MapUtils.isEmpty(substitutionFilters)) { return propertyList; @@ -248,25 +254,41 @@ public class YamlTemplateParsingHandler { return propertyList; } for (Map<String, List<Map<String, Object>>> filterProps : substitutionFilterProperties) { - for (Map.Entry<String, List<Map<String, Object>>> filterPropsMap : filterProps.entrySet()) { - for (Map<String, Object> mapValue : filterPropsMap.getValue()) { - RequirementSubstitutionFilterPropertyDataDefinition requirementSubstitutionFilterPropertyDataDefinition = - new RequirementSubstitutionFilterPropertyDataDefinition(); - requirementSubstitutionFilterPropertyDataDefinition.setName(filterPropsMap.getKey()); - requirementSubstitutionFilterPropertyDataDefinition.setConstraints( - getSubstitutionFilterConstraints(filterPropsMap.getKey(), mapValue)); - propertyList.add(requirementSubstitutionFilterPropertyDataDefinition); + for (Map.Entry<String, List<Map<String, Object>>> propertyFilterEntry : filterProps.entrySet()) { + final String propertyName = propertyFilterEntry.getKey(); + for (Map<String, Object> filterValueMap : propertyFilterEntry.getValue()) { + final var substitutionFilterPropertyDataDefinition = new SubstitutionFilterPropertyDataDefinition(); + substitutionFilterPropertyDataDefinition.setName(propertyName); + substitutionFilterPropertyDataDefinition.setConstraints(createSubstitutionFilterConstraints(propertyName, filterValueMap)); + propertyList.add(substitutionFilterPropertyDataDefinition); } } } return propertyList; } - private List<String> getSubstitutionFilterConstraints(String name, Map<String, Object> value) { - List<String> constraints = new ArrayList<>(); - for (Map.Entry<String, Object> valueMap : value.entrySet()) { - constraints.add(name + ": {" + valueMap.getKey() + ": " + valueMap.getValue() + "}"); + private List<PropertyFilterConstraintDataDefinition> createSubstitutionFilterConstraints(final String name, final Map<String, Object> value) { + final List<PropertyFilterConstraintDataDefinition> constraints = new ArrayList<>(); + for (final Map.Entry<String, Object> valueEntry : value.entrySet()) { + final var propertyFilterConstraint = new PropertyFilterConstraintDataDefinition(); + propertyFilterConstraint.setPropertyName(name); + propertyFilterConstraint.setOperator(ConstraintType.findByType(valueEntry.getKey()).orElse(null)); + propertyFilterConstraint.setTargetType(PropertyFilterTargetType.PROPERTY); + final Optional<ToscaFunction> toscaFunction = PropertyFilterConstraintDataDefinitionHelper + .createToscaFunctionFromLegacyConstraintValue(valueEntry.getValue()); + if (toscaFunction.isPresent()) { + final ToscaFunction toscaFunction1 = toscaFunction.get(); + propertyFilterConstraint.setValue(toscaFunction1); + propertyFilterConstraint.setValueType( + PropertyFilterConstraintDataDefinitionHelper.convertFromToscaFunctionType(toscaFunction1.getType()).orElse(null) + ); + } else { + propertyFilterConstraint.setValue(valueEntry.getValue()); + propertyFilterConstraint.setValueType(FilterValueType.STATIC); + } + constraints.add(propertyFilterConstraint); } + return constraints; } diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ComponentNodeFilterBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ComponentNodeFilterBusinessLogic.java index 65b5794687..ff65d84416 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ComponentNodeFilterBusinessLogic.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ComponentNodeFilterBusinessLogic.java @@ -21,9 +21,7 @@ package org.openecomp.sdc.be.components.impl; import static org.openecomp.sdc.common.log.enums.EcompLoggerErrorCode.BUSINESS_PROCESS_ERROR; import fj.data.Either; -import java.util.ArrayList; import java.util.Arrays; -import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Map.Entry; @@ -31,21 +29,19 @@ import java.util.Optional; import org.openecomp.sdc.be.components.impl.exceptions.BusinessLogicException; import org.openecomp.sdc.be.components.impl.exceptions.ComponentException; import org.openecomp.sdc.be.components.impl.utils.CINodeFilterUtils; -import org.openecomp.sdc.be.components.impl.utils.NodeFilterConstraintAction; import org.openecomp.sdc.be.components.validation.NodeFilterValidator; import org.openecomp.sdc.be.dao.api.ActionStatus; -import org.openecomp.sdc.be.datamodel.utils.ConstraintConvertor; import org.openecomp.sdc.be.datatypes.elements.CINodeFilterDataDefinition; import org.openecomp.sdc.be.datatypes.elements.ListDataDefinition; +import org.openecomp.sdc.be.datatypes.elements.PropertyFilterDataDefinition; import org.openecomp.sdc.be.datatypes.elements.RequirementNodeFilterCapabilityDataDefinition; -import org.openecomp.sdc.be.datatypes.elements.RequirementNodeFilterPropertyDataDefinition; import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum; import org.openecomp.sdc.be.datatypes.enums.NodeFilterConstraintType; import org.openecomp.sdc.be.model.Component; import org.openecomp.sdc.be.model.ComponentInstance; -import org.openecomp.sdc.be.model.ComponentInstanceProperty; import org.openecomp.sdc.be.model.UploadNodeFilterInfo; import org.openecomp.sdc.be.model.User; +import org.openecomp.sdc.be.model.dto.FilterConstraintDto; import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ArtifactsOperations; import org.openecomp.sdc.be.model.jsonjanusgraph.operations.InterfaceOperation; import org.openecomp.sdc.be.model.jsonjanusgraph.operations.NodeFilterOperation; @@ -55,6 +51,7 @@ import org.openecomp.sdc.be.model.operations.api.IGroupOperation; import org.openecomp.sdc.be.model.operations.api.IGroupTypeOperation; import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus; import org.openecomp.sdc.be.model.operations.impl.InterfaceLifecycleOperation; +import org.openecomp.sdc.be.ui.mapper.FilterConstraintMapper; import org.openecomp.sdc.be.ui.model.UIConstraint; import org.openecomp.sdc.be.user.Role; import org.openecomp.sdc.common.log.wrappers.Logger; @@ -85,8 +82,8 @@ public class ComponentNodeFilterBusinessLogic extends BaseBusinessLogic { final boolean shouldLock, final ComponentTypeEnum componentTypeEnum) throws BusinessLogicException { final Component component = getComponent(componentId); - final Optional<ComponentInstance> componentInstance = getComponentInstance(componentInstanceId, component); - Optional<CINodeFilterDataDefinition> filterDataDefinition = getCiNodeFilterDataDefinition(componentInstance); + Optional<CINodeFilterDataDefinition> filterDataDefinition = + component.getComponentInstanceById(componentInstanceId).map(ComponentInstance::getNodeFilter); if (filterDataDefinition.isPresent()) { return filterDataDefinition; } @@ -123,8 +120,8 @@ public class ComponentNodeFilterBusinessLogic extends BaseBusinessLogic { public Optional<String> deleteNodeFilterIfExists(final String componentId, final String componentInstanceId, final boolean shouldLock, final ComponentTypeEnum componentTypeEnum) throws BusinessLogicException { final Component component = getComponent(componentId); - final Optional<CINodeFilterDataDefinition> nodeFilterDataDefinition = getCiNodeFilterDataDefinition(componentInstanceId, component); - if (!nodeFilterDataDefinition.isPresent()) { + final Optional<CINodeFilterDataDefinition> nodeFilterDataDefinition = getComponentInstanceNodeFilter(componentInstanceId, component); + if (nodeFilterDataDefinition.isEmpty()) { return Optional.ofNullable(componentInstanceId); } final Either<String, StorageOperationStatus> result; @@ -156,43 +153,29 @@ public class ComponentNodeFilterBusinessLogic extends BaseBusinessLogic { return Optional.ofNullable(result.left().value()); } - private String getComponentInstancePropertyType(Component component, String componentInstanceId, String propertyName) { - List<ComponentInstanceProperty> componentInstanceProperties = component.getComponentInstancesProperties().get(componentInstanceId); - if (!componentInstanceProperties.isEmpty()) { - for (ComponentInstanceProperty componentInstanceProperty : componentInstanceProperties) { - if (componentInstanceProperty.getName().equals(propertyName)) { - return componentInstanceProperty.getType(); - } - } - } - return null; - } - public Optional<CINodeFilterDataDefinition> addNodeFilter(final String componentId, final String componentInstanceId, - final NodeFilterConstraintAction action, final String propertyName, - final String constraint, final boolean shouldLock, + final FilterConstraintDto filterConstraint, final boolean shouldLock, final ComponentTypeEnum componentTypeEnum, - final NodeFilterConstraintType nodeFilterConstraintType, final String capabilityName) - throws BusinessLogicException { + final NodeFilterConstraintType nodeFilterConstraintType, + final String capabilityName) throws BusinessLogicException { final Component component = getComponent(componentId); - CINodeFilterDataDefinition nodeFilterDataDefinition = validateAndReturnNodeFilterDefinition(componentInstanceId, action, constraint, - component, nodeFilterConstraintType, capabilityName); + validateNodeFilter(component, componentInstanceId, filterConstraint); + CINodeFilterDataDefinition nodeFilterDataDefinition = getComponentInstanceNodeFilterOrThrow(componentInstanceId, component); boolean wasLocked = false; try { if (shouldLock) { lockComponent(component.getUniqueId(), component, "Add Node Filter on Component"); wasLocked = true; } - final RequirementNodeFilterPropertyDataDefinition requirementNodeFilterPropertyDataDefinition = new RequirementNodeFilterPropertyDataDefinition(); - requirementNodeFilterPropertyDataDefinition.setName(propertyName); - requirementNodeFilterPropertyDataDefinition.setConstraints(Collections.singletonList(constraint)); - requirementNodeFilterPropertyDataDefinition.setType(getComponentInstancePropertyType(component, componentInstanceId, propertyName)); - final Either<CINodeFilterDataDefinition, StorageOperationStatus> result = addNewNodeFilter(componentId, componentInstanceId, - nodeFilterConstraintType, nodeFilterDataDefinition, requirementNodeFilterPropertyDataDefinition, capabilityName); + final PropertyFilterDataDefinition filterPropertyDataDefinition = new PropertyFilterDataDefinition(); + filterPropertyDataDefinition.setName(filterConstraint.getPropertyName()); + filterPropertyDataDefinition.setConstraints(List.of(new FilterConstraintMapper().mapTo(filterConstraint))); + final Either<CINodeFilterDataDefinition, StorageOperationStatus> result = addNodeFilter(componentId, componentInstanceId, + nodeFilterConstraintType, nodeFilterDataDefinition, filterPropertyDataDefinition, capabilityName); if (result.isRight()) { - janusGraphDao.rollback(); - throw new BusinessLogicException(componentsUtils - .getResponseFormatByResource(componentsUtils.convertFromStorageResponse(result.right().value()), component.getSystemName())); + throw new BusinessLogicException(componentsUtils.getResponseFormatByResource( + componentsUtils.convertFromStorageResponse(result.right().value()), component.getSystemName() + )); } else { nodeFilterDataDefinition = result.left().value(); } @@ -201,6 +184,9 @@ public class ComponentNodeFilterBusinessLogic extends BaseBusinessLogic { } catch (final Exception e) { janusGraphDao.rollback(); LOGGER.error(BUSINESS_PROCESS_ERROR, "Exception occurred during add component node filter property values: {}", e.getMessage(), e); + if (e instanceof BusinessLogicException) { + throw e; + } throw new BusinessLogicException(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR)); } finally { if (wasLocked) { @@ -210,14 +196,13 @@ public class ComponentNodeFilterBusinessLogic extends BaseBusinessLogic { return Optional.ofNullable(nodeFilterDataDefinition); } - public Optional<CINodeFilterDataDefinition> deleteNodeFilter(final String componentId, final String componentInstanceId, - final NodeFilterConstraintAction action, final String constraint, final int position, + public Optional<CINodeFilterDataDefinition> deleteNodeFilter(final String componentId, final String componentInstanceId, final int position, final boolean shouldLock, final ComponentTypeEnum componentTypeEnum, final NodeFilterConstraintType nodeFilterConstraintType) throws BusinessLogicException { + final Component component = getComponent(componentId); - CINodeFilterDataDefinition nodeFilterDataDefinition = validateAndReturnNodeFilterDefinition(componentInstanceId, action, constraint, - component, nodeFilterConstraintType, ""); + CINodeFilterDataDefinition nodeFilterDataDefinition = getComponentInstanceNodeFilterOrThrow(componentInstanceId, component); boolean wasLocked = false; try { if (shouldLock) { @@ -247,23 +232,23 @@ public class ComponentNodeFilterBusinessLogic extends BaseBusinessLogic { return Optional.ofNullable(nodeFilterDataDefinition); } - private Either<CINodeFilterDataDefinition, StorageOperationStatus> addNewNodeFilter(final String componentId, final String componentInstanceId, - final NodeFilterConstraintType nodeFilterConstraintType, - final CINodeFilterDataDefinition nodeFilterDataDefinition, - final RequirementNodeFilterPropertyDataDefinition requirementNodeFilterPropertyDataDefinition, - final String capabilityName) { + private Either<CINodeFilterDataDefinition, StorageOperationStatus> addNodeFilter(final String componentId, final String componentInstanceId, + final NodeFilterConstraintType nodeFilterConstraintType, + final CINodeFilterDataDefinition nodeFilterDataDefinition, + final PropertyFilterDataDefinition propertyFilterDataDefinition, + final String capabilityName) { if (NodeFilterConstraintType.PROPERTIES.equals(nodeFilterConstraintType)) { return nodeFilterOperation - .addNewProperty(componentId, componentInstanceId, nodeFilterDataDefinition, requirementNodeFilterPropertyDataDefinition); + .addPropertyFilter(componentId, componentInstanceId, nodeFilterDataDefinition, propertyFilterDataDefinition); } final RequirementNodeFilterCapabilityDataDefinition requirementNodeFilterCapabilityDataDefinition = new RequirementNodeFilterCapabilityDataDefinition(); requirementNodeFilterCapabilityDataDefinition.setName(capabilityName); - final ListDataDefinition<RequirementNodeFilterPropertyDataDefinition> propertyDataDefinitionListDataDefinition = new ListDataDefinition<>(); + final ListDataDefinition<PropertyFilterDataDefinition> propertyDataDefinitionListDataDefinition = new ListDataDefinition<>(); propertyDataDefinitionListDataDefinition.getListToscaDataDefinition() - .addAll(Collections.singleton(requirementNodeFilterPropertyDataDefinition)); + .add(propertyFilterDataDefinition); requirementNodeFilterCapabilityDataDefinition.setProperties(propertyDataDefinitionListDataDefinition); return nodeFilterOperation - .addNewCapabilities(componentId, componentInstanceId, nodeFilterDataDefinition, requirementNodeFilterCapabilityDataDefinition); + .addCapabilities(componentId, componentInstanceId, nodeFilterDataDefinition, requirementNodeFilterCapabilityDataDefinition); } private void unlockComponent(final String componentUniqueId, final ComponentTypeEnum componentType) { @@ -280,64 +265,42 @@ public class ComponentNodeFilterBusinessLogic extends BaseBusinessLogic { return component.getComponentInstanceById(componentInstanceId); } - private Optional<CINodeFilterDataDefinition> getCiNodeFilterDataDefinition(final Optional<ComponentInstance> componentInstance) { - if (componentInstance.isPresent()) { - return Optional.ofNullable(componentInstance.get().getNodeFilter()); - } - return Optional.empty(); - } - - private Optional<CINodeFilterDataDefinition> getCiNodeFilterDataDefinition(final String componentInstanceId, final Component component) + private Optional<CINodeFilterDataDefinition> getComponentInstanceNodeFilter(final String componentInstanceId, final Component component) throws BusinessLogicException { final Either<Boolean, ResponseFormat> response = nodeFilterValidator.validateComponentInstanceExist(component, componentInstanceId); if (response.isRight()) { throw new BusinessLogicException( componentsUtils.getResponseFormat(ActionStatus.NODE_FILTER_NOT_FOUND, response.right().value().getFormattedMessage())); } - final Optional<ComponentInstance> componentInstance = getComponentInstance(componentInstanceId, component); - if (componentInstance.isPresent()) { - return Optional.ofNullable(componentInstance.get().getNodeFilter()); - } - return Optional.empty(); + return getComponentInstance(componentInstanceId, component).map(ComponentInstance::getNodeFilter); } - private CINodeFilterDataDefinition validateAndReturnNodeFilterDefinition(final String componentInstanceId, - final NodeFilterConstraintAction action, final String constraint, - final Component component, - final NodeFilterConstraintType nodeFilterConstraintType, - final String capabilityName) - throws BusinessLogicException { - validateNodeFilter(component, componentInstanceId, action, constraint, nodeFilterConstraintType, capabilityName); - final Optional<CINodeFilterDataDefinition> cINodeFilterDataDefinition = getCiNodeFilterDataDefinition(componentInstanceId, component); - if (!cINodeFilterDataDefinition.isPresent()) { - throw new BusinessLogicException(componentsUtils.getResponseFormat(ActionStatus.NODE_FILTER_NOT_FOUND)); - } - return cINodeFilterDataDefinition.get(); + private CINodeFilterDataDefinition getComponentInstanceNodeFilterOrThrow(final String componentInstanceId, + final Component component) throws BusinessLogicException { + return getComponentInstanceNodeFilter(componentInstanceId, component).orElseThrow( + () -> new BusinessLogicException(componentsUtils.getResponseFormat(ActionStatus.NODE_FILTER_NOT_FOUND))); } - private void validateNodeFilter(final Component component, final String componentInstanceId, final NodeFilterConstraintAction action, - final String constraint, final NodeFilterConstraintType nodeFilterConstraintType, final String capabilityName) throws BusinessLogicException { - final Either<Boolean, ResponseFormat> response = nodeFilterValidator - .validateFilter(component, componentInstanceId, Collections.singletonList(constraint), action, nodeFilterConstraintType, capabilityName); + private void validateNodeFilter(final Component component, final String componentInstanceId, + final FilterConstraintDto constraint) throws BusinessLogicException { + final Either<Boolean, ResponseFormat> response = nodeFilterValidator.validateFilter(component, componentInstanceId, constraint); if (response.isRight()) { - throw new BusinessLogicException( - componentsUtils.getResponseFormat(ActionStatus.NODE_FILTER_NOT_FOUND, response.right().value().getFormattedMessage())); + throw new BusinessLogicException(response.right().value()); } } public Optional<CINodeFilterDataDefinition> updateNodeFilter(final String componentId, final String componentInstanceId, final UIConstraint uiConstraint, final ComponentTypeEnum componentTypeEnum, - final NodeFilterConstraintType nodeFilterConstraintType, final int index) - throws BusinessLogicException { - final Optional<CINodeFilterDataDefinition> deleteActionResponse = deleteNodeFilter(componentId, componentInstanceId, - NodeFilterConstraintAction.DELETE, null, index, true, componentTypeEnum, nodeFilterConstraintType); - if (!deleteActionResponse.isPresent()) { + final NodeFilterConstraintType nodeFilterConstraintType, + final int index) throws BusinessLogicException { + final Optional<CINodeFilterDataDefinition> deleteActionResponse = + deleteNodeFilter(componentId, componentInstanceId, index, true, componentTypeEnum, nodeFilterConstraintType); + if (deleteActionResponse.isEmpty()) { throw new BusinessLogicException( componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR, "Failed to delete node filter capabilities")); } - return addNodeFilter(componentId.toLowerCase(), componentInstanceId, NodeFilterConstraintAction.ADD, uiConstraint.getServicePropertyName(), - new ConstraintConvertor().convert(uiConstraint), true, componentTypeEnum, nodeFilterConstraintType, - uiConstraint.getCapabilityName()); + return addNodeFilter(componentId.toLowerCase(), componentInstanceId, new FilterConstraintMapper().mapFrom(uiConstraint), true, + componentTypeEnum, nodeFilterConstraintType, uiConstraint.getCapabilityName()); } public StorageOperationStatus associateNodeFilterToComponentInstance(final String componentId, @@ -355,22 +318,12 @@ public class ComponentNodeFilterBusinessLogic extends BaseBusinessLogic { } //associate node filter properties to component instance - List<RequirementNodeFilterPropertyDataDefinition> properties = ciNodeFilterDataDefinition.getProperties() + List<PropertyFilterDataDefinition> properties = ciNodeFilterDataDefinition.getProperties() .getListToscaDataDefinition(); if (!properties.isEmpty()) { - final Component component; - try { - component = getComponent(componentId); - } catch (BusinessLogicException e) { - throw new ComponentException(e.getResponseFormat()); - } properties.forEach(property -> { - String propertyType = getComponentInstancePropertyType(component, componentInstanceId, property.getName()); - RequirementNodeFilterPropertyDataDefinition requirementNodeFilterPropertyDataDefinition = - getRequirementNodeFilterPropertyDataDefinition(property); - requirementNodeFilterPropertyDataDefinition.setType(propertyType); Either<CINodeFilterDataDefinition, StorageOperationStatus> nodeFilterProperty = nodeFilterOperation - .addNewProperty(componentId, componentInstanceId, nodeFilter.left().value(), requirementNodeFilterPropertyDataDefinition); + .addPropertyFilter(componentId, componentInstanceId, nodeFilter.left().value(), property); if (nodeFilterProperty.isRight()) { throw new ComponentException( componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(nodeFilterProperty.right().value()), @@ -389,7 +342,7 @@ public class ComponentNodeFilterBusinessLogic extends BaseBusinessLogic { requirementNodeFilterCapabilityDataDefinition.setName(capability.getName()); requirementNodeFilterCapabilityDataDefinition.setProperties(getProperties(capability.getProperties())); Either<CINodeFilterDataDefinition, StorageOperationStatus> nodeFilterCapability = nodeFilterOperation - .addNewCapabilities(componentId, componentInstanceId, nodeFilter.left().value(), + .addCapabilities(componentId, componentInstanceId, nodeFilter.left().value(), requirementNodeFilterCapabilityDataDefinition); if (nodeFilterCapability.isRight()) { throw new ComponentException( @@ -402,27 +355,10 @@ public class ComponentNodeFilterBusinessLogic extends BaseBusinessLogic { return StorageOperationStatus.OK; } - private List<String> getNodeFilterConstraints(String name, List<String> value) { - List<String> constraints = new ArrayList<>(); - constraints.add(name + ":\n " + value.get(0)); - return constraints; - } - - private ListDataDefinition<RequirementNodeFilterPropertyDataDefinition> getProperties(ListDataDefinition<RequirementNodeFilterPropertyDataDefinition> properties) { - ListDataDefinition<RequirementNodeFilterPropertyDataDefinition> updatedProperties = new ListDataDefinition<>(); - properties.getListToscaDataDefinition().forEach(property -> { - RequirementNodeFilterPropertyDataDefinition requirementNodeFilterPropertyDataDefinition = getRequirementNodeFilterPropertyDataDefinition( - property); - updatedProperties.add(requirementNodeFilterPropertyDataDefinition); - }); + private ListDataDefinition<PropertyFilterDataDefinition> getProperties(ListDataDefinition<PropertyFilterDataDefinition> properties) { + ListDataDefinition<PropertyFilterDataDefinition> updatedProperties = new ListDataDefinition<>(); + properties.getListToscaDataDefinition().forEach(updatedProperties::add); return updatedProperties; } - private RequirementNodeFilterPropertyDataDefinition getRequirementNodeFilterPropertyDataDefinition( - RequirementNodeFilterPropertyDataDefinition property) { - RequirementNodeFilterPropertyDataDefinition requirementNodeFilterPropertyDataDefinition = new RequirementNodeFilterPropertyDataDefinition(); - requirementNodeFilterPropertyDataDefinition.setName(property.getName()); - requirementNodeFilterPropertyDataDefinition.setConstraints(getNodeFilterConstraints(property.getName(), property.getConstraints())); - return requirementNodeFilterPropertyDataDefinition; - } } diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ComponentSubstitutionFilterBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ComponentSubstitutionFilterBusinessLogic.java index 74b353ec85..2fed0e2483 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ComponentSubstitutionFilterBusinessLogic.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ComponentSubstitutionFilterBusinessLogic.java @@ -23,20 +23,19 @@ import static org.openecomp.sdc.common.log.enums.EcompLoggerErrorCode.BUSINESS_P import fj.data.Either; import java.util.Arrays; -import java.util.Collections; import java.util.List; import java.util.Optional; import java.util.stream.Collectors; import org.openecomp.sdc.be.components.impl.exceptions.BusinessLogicException; -import org.openecomp.sdc.be.components.impl.utils.NodeFilterConstraintAction; import org.openecomp.sdc.be.components.validation.NodeFilterValidator; import org.openecomp.sdc.be.dao.api.ActionStatus; import org.openecomp.sdc.be.datatypes.elements.ListDataDefinition; -import org.openecomp.sdc.be.datatypes.elements.RequirementSubstitutionFilterPropertyDataDefinition; +import org.openecomp.sdc.be.datatypes.elements.SubstitutionFilterPropertyDataDefinition; import org.openecomp.sdc.be.datatypes.elements.SubstitutionFilterDataDefinition; 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.be.model.dto.FilterConstraintDto; import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ArtifactsOperations; import org.openecomp.sdc.be.model.jsonjanusgraph.operations.InterfaceOperation; import org.openecomp.sdc.be.model.jsonjanusgraph.operations.SubstitutionFilterOperation; @@ -46,6 +45,7 @@ import org.openecomp.sdc.be.model.operations.api.IGroupOperation; import org.openecomp.sdc.be.model.operations.api.IGroupTypeOperation; import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus; import org.openecomp.sdc.be.model.operations.impl.InterfaceLifecycleOperation; +import org.openecomp.sdc.be.ui.mapper.FilterConstraintMapper; import org.openecomp.sdc.be.user.Role; import org.openecomp.sdc.common.log.wrappers.Logger; import org.openecomp.sdc.exception.ResponseFormat; @@ -111,12 +111,11 @@ public class ComponentSubstitutionFilterBusinessLogic extends BaseBusinessLogic return substitutionFilterDataDefinition; } - public Optional<SubstitutionFilterDataDefinition> addSubstitutionFilter(final String componentId, final String propertyName, - final String constraint, final boolean shouldLock, + public Optional<SubstitutionFilterDataDefinition> addSubstitutionFilter(final String componentId, + final FilterConstraintDto filterConstraint, final boolean shouldLock, final ComponentTypeEnum componentTypeEnum) throws BusinessLogicException { final Component component = getComponent(componentId); - final Either<Boolean, ResponseFormat> response = nodeFilterValidator - .validateComponentFilter(component, Collections.singletonList(constraint), NodeFilterConstraintAction.ADD); + final Either<Boolean, ResponseFormat> response = nodeFilterValidator.validateSubstitutionFilter(component, filterConstraint); if (response.isRight()) { throw new BusinessLogicException( componentsUtils.getResponseFormat(ActionStatus.SUBSTITUTION_FILTER_NOT_FOUND, response.right().value().getFormattedMessage())); @@ -127,9 +126,9 @@ public class ComponentSubstitutionFilterBusinessLogic extends BaseBusinessLogic lockComponent(component.getUniqueId(), component, "Add Substitution Filter on Component"); wasLocked = true; } - final RequirementSubstitutionFilterPropertyDataDefinition newProperty = new RequirementSubstitutionFilterPropertyDataDefinition(); - newProperty.setName(propertyName); - newProperty.setConstraints(Collections.singletonList(constraint)); + final SubstitutionFilterPropertyDataDefinition newProperty = new SubstitutionFilterPropertyDataDefinition(); + newProperty.setName(filterConstraint.getPropertyName()); + newProperty.setConstraints(List.of(new FilterConstraintMapper().mapTo(filterConstraint))); final Either<SubstitutionFilterDataDefinition, StorageOperationStatus> resultEither = substitutionFilterOperation .addPropertyFilter(componentId, component.getSubstitutionFilter(), newProperty); if (resultEither.isRight()) { @@ -153,12 +152,11 @@ public class ComponentSubstitutionFilterBusinessLogic extends BaseBusinessLogic } } - public Optional<SubstitutionFilterDataDefinition> updateSubstitutionFilter(final String componentId, final List<String> constraints, - final boolean shouldLock, final ComponentTypeEnum componentTypeEnum) - throws BusinessLogicException { + public Optional<SubstitutionFilterDataDefinition> updateSubstitutionFilter(final String componentId, final List<FilterConstraintDto> constraints, + final boolean shouldLock, + final ComponentTypeEnum componentTypeEnum) throws BusinessLogicException { final Component component = getComponent(componentId); - final Either<Boolean, ResponseFormat> response = nodeFilterValidator - .validateComponentFilter(component, constraints, NodeFilterConstraintAction.UPDATE); + final Either<Boolean, ResponseFormat> response = nodeFilterValidator.validateSubstitutionFilter(component, constraints); if (response.isRight()) { throw new BusinessLogicException( componentsUtils.getResponseFormat(ActionStatus.SUBSTITUTION_FILTER_NOT_FOUND, response.right().value().getFormattedMessage())); @@ -173,10 +171,10 @@ public class ComponentSubstitutionFilterBusinessLogic extends BaseBusinessLogic lockComponent(component.getUniqueId(), component, "Update Substitution Filter on Component"); wasLocked = true; } - final List<RequirementSubstitutionFilterPropertyDataDefinition> properties = constraints.stream() - .map(this::getRequirementSubstitutionFilterPropertyDataDefinition).collect(Collectors.toList()); + final List<SubstitutionFilterPropertyDataDefinition> properties = constraints.stream() + .map(this::buildSubstitutionFilterPropertyDataDefinition).collect(Collectors.toList()); final Either<SubstitutionFilterDataDefinition, StorageOperationStatus> result = substitutionFilterOperation - .updateProperties(componentId, substitutionFilterDataDefinition, properties); + .updatePropertyFilters(componentId, substitutionFilterDataDefinition, properties); if (result.isRight()) { janusGraphDao.rollback(); throw new BusinessLogicException(componentsUtils @@ -199,6 +197,51 @@ public class ComponentSubstitutionFilterBusinessLogic extends BaseBusinessLogic return Optional.ofNullable(substitutionFilterDataDefinition); } + public Optional<SubstitutionFilterDataDefinition> updateSubstitutionFilter(final String componentId, final FilterConstraintDto filterConstraint, + final int index, + final boolean shouldLock) throws BusinessLogicException { + final Component component = getComponent(componentId); + final Either<Boolean, ResponseFormat> validationResponse = nodeFilterValidator.validateSubstitutionFilter(component, filterConstraint); + if (validationResponse.isRight()) { + throw new BusinessLogicException(validationResponse.right().value()); + } + final SubstitutionFilterDataDefinition substitutionFilterDataDefinition = component.getSubstitutionFilter(); + if (substitutionFilterDataDefinition == null) { + throw new BusinessLogicException(componentsUtils.getResponseFormat(SUBSTITUTION_FILTER_NOT_FOUND, component.getName())); + } + boolean wasLocked = false; + try { + if (shouldLock) { + lockComponent(component.getUniqueId(), component, "Update Substitution Filter on Component"); + wasLocked = true; + } + final SubstitutionFilterPropertyDataDefinition substitutionFilterProperty = + buildSubstitutionFilterPropertyDataDefinition(filterConstraint); + final Either<SubstitutionFilterDataDefinition, StorageOperationStatus> result = + substitutionFilterOperation.updatePropertyFilter(componentId, substitutionFilterDataDefinition, substitutionFilterProperty, index); + if (result.isRight()) { + janusGraphDao.rollback(); + throw new BusinessLogicException( + componentsUtils.getResponseFormatByResource( + componentsUtils.convertFromStorageResponse(result.right().value()), component.getSystemName() + ) + ); + } + janusGraphDao.commit(); + LOGGER.debug("Substitution filter successfully updated in component {} . ", component.getSystemName()); + return Optional.ofNullable(result.left().value()); + } catch (final Exception e) { + janusGraphDao.rollback(); + LOGGER.error(BUSINESS_PROCESS_ERROR, this.getClass().getName(), + "Exception occurred during update component substitution filter property values: {}", e); + throw e; + } finally { + if (wasLocked) { + unlockComponent(component.getUniqueId(), component.getComponentType()); + } + } + } + public Optional<SubstitutionFilterDataDefinition> deleteSubstitutionFilter(final String componentId, final int position, final boolean shouldLock, final ComponentTypeEnum componentTypeEnum) throws BusinessLogicException { @@ -244,20 +287,21 @@ public class ComponentSubstitutionFilterBusinessLogic extends BaseBusinessLogic return user; } - private RequirementSubstitutionFilterPropertyDataDefinition getRequirementSubstitutionFilterPropertyDataDefinition(final String constraint) { - final RequirementSubstitutionFilterPropertyDataDefinition requirementSubstitutionFilterPropertyDataDefinition = new RequirementSubstitutionFilterPropertyDataDefinition(); - requirementSubstitutionFilterPropertyDataDefinition.setConstraints(Arrays.asList(constraint)); - return requirementSubstitutionFilterPropertyDataDefinition; + private SubstitutionFilterPropertyDataDefinition buildSubstitutionFilterPropertyDataDefinition(final FilterConstraintDto filterConstraint) { + final var substitutionFilterProperty = new SubstitutionFilterPropertyDataDefinition(); + substitutionFilterProperty.setName(filterConstraint.getPropertyName()); + substitutionFilterProperty.setConstraints(List.of(new FilterConstraintMapper().mapTo(filterConstraint))); + return substitutionFilterProperty; } public void addSubstitutionFilterInGraph(String componentId, - ListDataDefinition<RequirementSubstitutionFilterPropertyDataDefinition> substitutionFilterProperties) + ListDataDefinition<SubstitutionFilterPropertyDataDefinition> substitutionFilterProperties) throws BusinessLogicException { Either<SubstitutionFilterDataDefinition, StorageOperationStatus> updateSubstitutionFilter; Optional<SubstitutionFilterDataDefinition> substitutionFilter = createSubstitutionFilterIfNotExist(componentId, true, ComponentTypeEnum.SERVICE); if (substitutionFilter.isPresent()) { - for (RequirementSubstitutionFilterPropertyDataDefinition filter : substitutionFilterProperties.getListToscaDataDefinition()) { + for (SubstitutionFilterPropertyDataDefinition filter : substitutionFilterProperties.getListToscaDataDefinition()) { updateSubstitutionFilter = substitutionFilterOperation.addPropertyFilter(componentId, substitutionFilter.get(), filter); if (updateSubstitutionFilter.isRight()) { throw new BusinessLogicException(componentsUtils diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ImportUtils.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ImportUtils.java index b4f6ee3950..8ad86b3510 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ImportUtils.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ImportUtils.java @@ -63,7 +63,7 @@ import org.openecomp.sdc.be.model.heat.HeatParameterType; import org.openecomp.sdc.be.model.operations.impl.AnnotationTypeOperations; import org.openecomp.sdc.be.model.operations.impl.PropertyOperation.PropertyConstraintDeserialiser; import org.openecomp.sdc.be.model.tosca.ToscaPropertyType; -import org.openecomp.sdc.be.model.tosca.constraints.ConstraintType; +import org.openecomp.sdc.be.datatypes.enums.ConstraintType; import org.openecomp.sdc.be.model.tosca.constraints.ValidValuesConstraint; import org.openecomp.sdc.be.model.tosca.constraints.exception.ConstraintValueDoNotMatchPropertyTypeException; import org.openecomp.sdc.be.utils.TypeUtils; diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/NodeFilterUploadCreator.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/NodeFilterUploadCreator.java index 9d72eeca87..f34091de0f 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/NodeFilterUploadCreator.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/NodeFilterUploadCreator.java @@ -49,22 +49,26 @@ public class NodeFilterUploadCreator { return uploadNodeFilterInfo; } - private List<UploadNodeFilterPropertyInfo> createNodeFilterProperties(Object o) { - if (!(o instanceof List)) { + private List<UploadNodeFilterPropertyInfo> createNodeFilterProperties(Object propertyNodeFilterYamlObject) { + if (!(propertyNodeFilterYamlObject instanceof List)) { return null; } List<UploadNodeFilterPropertyInfo> retVal = new ArrayList<>(); - List<Map<String, Object>> propertiesList = (List<Map<String, Object>>) o; + List<Map<String, Object>> propertiesList = (List<Map<String, Object>>) propertyNodeFilterYamlObject; for (Map<String, Object> map : propertiesList) { final Map.Entry<String, Object> entry = map.entrySet().iterator().next(); - final Object value = entry.getValue(); - if (value instanceof Map) { - List<String> valueList = new ArrayList<>(); - valueList.add(valueToProperty(entry.getValue())); - retVal.add(new UploadNodeFilterPropertyInfo(entry.getKey(), valueList)); - } else if (value instanceof List) { - List<String> propertiesVals = (List<String>) ((List) value).stream().map(this::valueToProperty).collect(Collectors.toList()); - retVal.add(new UploadNodeFilterPropertyInfo(entry.getKey(), propertiesVals)); + final Object propertyConstraintClauses = entry.getValue(); + if (propertyConstraintClauses instanceof Map) { + final List<String> propertyFilterConstraintList = new ArrayList<>(); + propertyFilterConstraintList.add(valueToProperty(map)); + retVal.add(new UploadNodeFilterPropertyInfo(entry.getKey(), propertyFilterConstraintList)); + } else if (propertyConstraintClauses instanceof List) { + final List<String> propertyFilterConstraintList = ((List<Object>) propertyConstraintClauses).stream() + .map(propertyConstraintClause -> Map.of(entry.getKey(), propertyConstraintClause)) + .map(this::valueToProperty) + .collect(Collectors.toList()); + + retVal.add(new UploadNodeFilterPropertyInfo(entry.getKey(), propertyFilterConstraintList)); } } return retVal; diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceImportBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceImportBusinessLogic.java index ab43b4329e..8c46285240 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceImportBusinessLogic.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceImportBusinessLogic.java @@ -77,7 +77,7 @@ import org.openecomp.sdc.be.datatypes.elements.OperationDataDefinition; import org.openecomp.sdc.be.datatypes.elements.OperationInputDefinition; import org.openecomp.sdc.be.datatypes.elements.PolicyDataDefinition; import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition; -import org.openecomp.sdc.be.datatypes.elements.RequirementSubstitutionFilterPropertyDataDefinition; +import org.openecomp.sdc.be.datatypes.elements.SubstitutionFilterPropertyDataDefinition; import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum; import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum; import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum; @@ -448,7 +448,7 @@ public class ServiceImportBusinessLogic { Map<String, InputDefinition> inputs = parsedToscaYamlInfo.getInputs(); service = serviceImportParseLogic.createInputsOnService(service, inputs); log.trace("************* Finished to add inputs from yaml {}", yamlName); - ListDataDefinition<RequirementSubstitutionFilterPropertyDataDefinition> substitutionFilterProperties = parsedToscaYamlInfo.getSubstitutionFilterProperties(); + ListDataDefinition<SubstitutionFilterPropertyDataDefinition> substitutionFilterProperties = parsedToscaYamlInfo.getSubstitutionFilterProperties(); service = serviceImportParseLogic.createSubstitutionFilterOnService(service, substitutionFilterProperties); log.trace("************* Added Substitution filter from interface yaml {}", yamlName); Map<String, UploadComponentInstanceInfo> uploadComponentInstanceInfoMap = parsedToscaYamlInfo.getInstances(); diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceImportParseLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceImportParseLogic.java index 8cc5bd6fcb..b97645cc35 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceImportParseLogic.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceImportParseLogic.java @@ -40,7 +40,7 @@ import org.openecomp.sdc.be.datatypes.elements.ListRequirementDataDefinition; import org.openecomp.sdc.be.datatypes.elements.MapInterfaceDataDefinition; import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition; import org.openecomp.sdc.be.datatypes.elements.RequirementDataDefinition; -import org.openecomp.sdc.be.datatypes.elements.RequirementSubstitutionFilterPropertyDataDefinition; +import org.openecomp.sdc.be.datatypes.elements.SubstitutionFilterPropertyDataDefinition; import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum; import org.openecomp.sdc.be.datatypes.enums.CreatedFrom; import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum; @@ -1381,7 +1381,7 @@ public class ServiceImportParseLogic { } public Service createSubstitutionFilterOnService(Service service, - ListDataDefinition<RequirementSubstitutionFilterPropertyDataDefinition> substitutionFilterProperties) + ListDataDefinition<SubstitutionFilterPropertyDataDefinition> substitutionFilterProperties) throws BusinessLogicException { if (substitutionFilterProperties == null || substitutionFilterProperties.isEmpty()) { return service; diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/exceptions/FilterConstraintExceptionSupplier.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/exceptions/FilterConstraintExceptionSupplier.java new file mode 100644 index 0000000000..9f184aa2c2 --- /dev/null +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/exceptions/FilterConstraintExceptionSupplier.java @@ -0,0 +1,40 @@ +/* + * - + * ============LICENSE_START======================================================= + * Copyright (C) 2022 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdc.be.components.impl.exceptions; + +import java.util.function.Supplier; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; +import org.openecomp.sdc.be.dao.api.ActionStatus; + +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public class FilterConstraintExceptionSupplier { + + public static Supplier<ByActionStatusComponentException> filterConstraintNotProvided() { + return () -> new ByActionStatusComponentException(ActionStatus.FILTER_CONSTRAINT_MISSING); + } + + public static Supplier<ByActionStatusComponentException> missingField(final String fieldName) { + return () -> new ByActionStatusComponentException(ActionStatus.FILTER_CONSTRAINT_MISSING_FIELD, fieldName); + } + +} diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/utils/CINodeFilterUtils.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/utils/CINodeFilterUtils.java index a7dd5afc10..5ac9bcd2de 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/utils/CINodeFilterUtils.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/utils/CINodeFilterUtils.java @@ -15,37 +15,39 @@ */ package org.openecomp.sdc.be.components.impl.utils; +import java.util.Collection; import java.util.List; import java.util.Map; import java.util.stream.Collectors; +import org.apache.commons.collections4.CollectionUtils; import org.openecomp.sdc.be.datatypes.elements.CINodeFilterDataDefinition; import org.openecomp.sdc.be.datatypes.elements.ListDataDefinition; +import org.openecomp.sdc.be.datatypes.elements.PropertyFilterDataDefinition; import org.openecomp.sdc.be.datatypes.elements.RequirementNodeFilterCapabilityDataDefinition; -import org.openecomp.sdc.be.datatypes.elements.RequirementNodeFilterPropertyDataDefinition; import org.openecomp.sdc.be.model.UploadNodeFilterCapabilitiesInfo; import org.openecomp.sdc.be.model.UploadNodeFilterInfo; import org.openecomp.sdc.be.model.UploadNodeFilterPropertyInfo; -import org.openecomp.sdc.common.log.wrappers.Logger; +import org.openecomp.sdc.be.utils.PropertyFilterConstraintDataDefinitionHelper; public class CINodeFilterUtils { - Logger log = Logger.getLogger(CINodeFilterUtils.class); - - public CINodeFilterDataDefinition getNodeFilterDataDefinition(UploadNodeFilterInfo uploadNodeFilterInfo, String uniqueId) { - CINodeFilterDataDefinition nodeFilterDataDefinition = new CINodeFilterDataDefinition(); + public CINodeFilterDataDefinition getNodeFilterDataDefinition(final UploadNodeFilterInfo uploadNodeFilterInfo, final String uniqueId) { + final var nodeFilterDataDefinition = new CINodeFilterDataDefinition(); nodeFilterDataDefinition.setName(uploadNodeFilterInfo.getName()); - List<RequirementNodeFilterPropertyDataDefinition> collect = uploadNodeFilterInfo.getProperties().stream().map(this::buildProperty) + final List<PropertyFilterDataDefinition> propertyFilterList = uploadNodeFilterInfo.getProperties().stream() + .map(this::buildOnePropertyFilterForEachConstraint) + .flatMap(Collection::stream) .collect(Collectors.toList()); - ListDataDefinition<RequirementNodeFilterPropertyDataDefinition> listDataDefinition = new ListDataDefinition<>(); - listDataDefinition.getListToscaDataDefinition().addAll(collect); + final ListDataDefinition<PropertyFilterDataDefinition> listDataDefinition = new ListDataDefinition<>(); + listDataDefinition.getListToscaDataDefinition().addAll(propertyFilterList); nodeFilterDataDefinition.setProperties(listDataDefinition); - nodeFilterDataDefinition.setCapabilities(converCapabilties(uploadNodeFilterInfo.getCapabilities())); + nodeFilterDataDefinition.setCapabilities(convertCapabilities(uploadNodeFilterInfo.getCapabilities())); nodeFilterDataDefinition.setID(uniqueId); nodeFilterDataDefinition.setTosca_id(uploadNodeFilterInfo.getTosca_id()); return nodeFilterDataDefinition; } - private ListDataDefinition<RequirementNodeFilterCapabilityDataDefinition> converCapabilties( + private ListDataDefinition<RequirementNodeFilterCapabilityDataDefinition> convertCapabilities( Map<String, UploadNodeFilterCapabilitiesInfo> capabilities) { ListDataDefinition<RequirementNodeFilterCapabilityDataDefinition> listDataDefinition = new ListDataDefinition<>(); for (UploadNodeFilterCapabilitiesInfo capability : capabilities.values()) { @@ -58,19 +60,43 @@ public class CINodeFilterUtils { private RequirementNodeFilterCapabilityDataDefinition convertCapability(UploadNodeFilterCapabilitiesInfo capability) { RequirementNodeFilterCapabilityDataDefinition retVal = new RequirementNodeFilterCapabilityDataDefinition(); retVal.setName(capability.getName()); - List<RequirementNodeFilterPropertyDataDefinition> props = capability.getProperties().stream().map(this::buildProperty) + List<PropertyFilterDataDefinition> props = capability.getProperties().stream().map(this::buildProperty) .collect(Collectors.toList()); - ListDataDefinition<RequirementNodeFilterPropertyDataDefinition> propsList = new ListDataDefinition<>(); + ListDataDefinition<PropertyFilterDataDefinition> propsList = new ListDataDefinition<>(); propsList.getListToscaDataDefinition().addAll(props); retVal.setProperties(propsList); return retVal; } - private RequirementNodeFilterPropertyDataDefinition buildProperty(UploadNodeFilterPropertyInfo uploadNodeFilterPropertyInfo) { - RequirementNodeFilterPropertyDataDefinition retVal = new RequirementNodeFilterPropertyDataDefinition(); - retVal.setName(uploadNodeFilterPropertyInfo.getName()); - List<String> propertyConstraints = uploadNodeFilterPropertyInfo.getValues(); - retVal.setConstraints(propertyConstraints); - return retVal; + private PropertyFilterDataDefinition buildProperty(final UploadNodeFilterPropertyInfo uploadNodeFilterPropertyInfo) { + final var propertyFilter = new PropertyFilterDataDefinition(); + propertyFilter.setName(uploadNodeFilterPropertyInfo.getName()); + final List<String> propertyConstraints = uploadNodeFilterPropertyInfo.getValues(); + if (CollectionUtils.isNotEmpty(propertyConstraints)) { + propertyFilter.setConstraints( + propertyConstraints.stream() + .map(PropertyFilterConstraintDataDefinitionHelper::convertLegacyConstraint) + .collect(Collectors.toList()) + ); + } + return propertyFilter; + } + + private List<PropertyFilterDataDefinition> buildOnePropertyFilterForEachConstraint(final UploadNodeFilterPropertyInfo uploadNodeFilterProperty) { + final List<String> propertyConstraints = uploadNodeFilterProperty.getValues(); + if (CollectionUtils.isNotEmpty(propertyConstraints)) { + return propertyConstraints.stream() + .map(PropertyFilterConstraintDataDefinitionHelper::convertLegacyConstraint) + .map(propertyFilterConstraint -> { + final var propertyFilter = new PropertyFilterDataDefinition(); + propertyFilter.setName(uploadNodeFilterProperty.getName()); + propertyFilter.setConstraints(List.of(propertyFilterConstraint)); + return propertyFilter; + }).collect(Collectors.toList()); + } else { + final var propertyFilter = new PropertyFilterDataDefinition(); + propertyFilter.setName(uploadNodeFilterProperty.getName()); + return List.of(propertyFilter); + } } } diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/property/PropertyConstraintsUtils.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/property/PropertyConstraintsUtils.java index bd2187616c..4bd953fd3d 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/property/PropertyConstraintsUtils.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/property/PropertyConstraintsUtils.java @@ -28,7 +28,7 @@ import org.openecomp.sdc.be.components.impl.exceptions.ByActionStatusComponentEx import org.openecomp.sdc.be.model.PropertyConstraint; import org.openecomp.sdc.be.model.PropertyDefinition; import org.openecomp.sdc.be.model.Resource; -import org.openecomp.sdc.be.model.tosca.constraints.ConstraintType; +import org.openecomp.sdc.be.datatypes.enums.ConstraintType; import org.openecomp.sdc.be.model.tosca.constraints.exception.PropertyConstraintException; /** diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/validation/FilterConstraintValidatorImpl.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/validation/FilterConstraintValidatorImpl.java new file mode 100644 index 0000000000..862b839326 --- /dev/null +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/validation/FilterConstraintValidatorImpl.java @@ -0,0 +1,64 @@ +/* + * - + * ============LICENSE_START======================================================= + * Copyright (C) 2022 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdc.be.components.validation; + +import org.apache.commons.lang3.StringUtils; +import org.openecomp.sdc.be.components.impl.exceptions.FilterConstraintExceptionSupplier; +import org.openecomp.sdc.be.datatypes.enums.PropertyFilterTargetType; +import org.openecomp.sdc.be.model.dto.FilterConstraintDto; +import org.openecomp.sdc.be.model.validation.FilterConstraintValidator; + +@org.springframework.stereotype.Component +public class FilterConstraintValidatorImpl implements FilterConstraintValidator { + + @Override + public void validate(final FilterConstraintDto filterConstraint) { + if (filterConstraint == null) { + throw FilterConstraintExceptionSupplier.filterConstraintNotProvided().get(); + } + + if (StringUtils.isBlank(filterConstraint.getPropertyName())) { + throw FilterConstraintExceptionSupplier.missingField("propertyName").get(); + } + + if (filterConstraint.getValueType() == null) { + throw FilterConstraintExceptionSupplier.missingField("valueType").get(); + } + + if (filterConstraint.getTargetType() == null) { + throw FilterConstraintExceptionSupplier.missingField("targetType").get(); + } + + if (filterConstraint.getTargetType() == PropertyFilterTargetType.CAPABILITY && StringUtils.isBlank(filterConstraint.getCapabilityName())) { + throw FilterConstraintExceptionSupplier.missingField("capabilityName").get(); + } + + if (filterConstraint.getValue() == null) { + throw FilterConstraintExceptionSupplier.missingField("value").get(); + } + + if (filterConstraint.getOperator() == null) { + throw FilterConstraintExceptionSupplier.missingField("operator").get(); + } + + } +} diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/validation/NodeFilterValidator.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/validation/NodeFilterValidator.java index e62893a148..12b58ded4a 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/validation/NodeFilterValidator.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/validation/NodeFilterValidator.java @@ -19,33 +19,33 @@ */ package org.openecomp.sdc.be.components.validation; -import com.google.common.collect.ImmutableSet; +import com.google.gson.Gson; import fj.data.Either; -import java.util.ArrayList; -import java.util.Collections; import java.util.List; -import java.util.Objects; +import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; -import org.openecomp.sdc.be.components.impl.ResponseFormatManager; -import org.openecomp.sdc.be.components.impl.utils.NodeFilterConstraintAction; import org.openecomp.sdc.be.dao.api.ActionStatus; -import org.openecomp.sdc.be.datamodel.utils.ConstraintConvertor; -import org.openecomp.sdc.be.datatypes.elements.SchemaDefinition; -import org.openecomp.sdc.be.datatypes.enums.NodeFilterConstraintType; +import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus; +import org.openecomp.sdc.be.datatypes.elements.ToscaGetFunctionDataDefinition; +import org.openecomp.sdc.be.datatypes.enums.PropertySource; 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; +import org.openecomp.sdc.be.model.DataTypeDefinition; import org.openecomp.sdc.be.model.InputDefinition; import org.openecomp.sdc.be.model.PropertyDefinition; -import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ToscaOperationFacade; +import org.openecomp.sdc.be.model.ToscaPropertyData; +import org.openecomp.sdc.be.model.cache.ApplicationDataTypeCache; +import org.openecomp.sdc.be.model.dto.FilterConstraintDto; import org.openecomp.sdc.be.model.tosca.ToscaPropertyType; -import org.openecomp.sdc.be.ui.model.UIConstraint; +import org.openecomp.sdc.be.model.tosca.validators.DataTypeValidatorConverter; +import org.openecomp.sdc.be.model.validation.FilterConstraintValidator; import org.openecomp.sdc.exception.ResponseFormat; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -54,128 +54,192 @@ import org.springframework.beans.factory.annotation.Autowired; @org.springframework.stereotype.Component("NodeFilterValidator") public class NodeFilterValidator { + private static final Logger LOGGER = LoggerFactory.getLogger(NodeFilterValidator.class); private static final String SOURCE = "Source"; - public static final Set<String> comparableTypes = ImmutableSet + private static final String TARGET = "Target"; + private static final String INPUT_NOT_FOUND_LOG = "Input '{}' not found in parent component '{}', unique id '{}'"; + private static final Set<String> TYPES_WITH_SCHEMA = Set.of(ToscaPropertyType.MAP.getType(), ToscaPropertyType.LIST.getType()); + private static final Set<String> COMPARABLE_TYPES = Set .of(ToscaPropertyType.STRING.getType(), ToscaPropertyType.INTEGER.getType(), ToscaPropertyType.FLOAT.getType()); - public static final Set<String> schemableTypes = ImmutableSet.of(ToscaPropertyType.MAP.getType(), ToscaPropertyType.LIST.getType()); - public static final Set<String> comparableConstraintsOperators = ImmutableSet - .of(ConstraintConvertor.GREATER_THAN_OPERATOR, ConstraintConvertor.LESS_THAN_OPERATOR); - protected final ToscaOperationFacade toscaOperationFacade; - protected final ComponentsUtils componentsUtils; - private static final Logger LOGGER = LoggerFactory.getLogger(NodeFilterValidator.class); + private final ComponentsUtils componentsUtils; + private final ApplicationDataTypeCache applicationDataTypeCache; + private final FilterConstraintValidator filterConstraintValidator; @Autowired - public NodeFilterValidator(final ToscaOperationFacade toscaOperationFacade, final ComponentsUtils componentsUtils) { - this.toscaOperationFacade = toscaOperationFacade; + public NodeFilterValidator(final ComponentsUtils componentsUtils, final ApplicationDataTypeCache applicationDataTypeCache, + final FilterConstraintValidator filterConstraintValidator) { this.componentsUtils = componentsUtils; + this.applicationDataTypeCache = applicationDataTypeCache; + this.filterConstraintValidator = filterConstraintValidator; } public Either<Boolean, ResponseFormat> validateComponentInstanceExist(final Component component, final String componentInstanceId) { if (component == null || StringUtils.isEmpty(componentInstanceId)) { - LOGGER.error("Input data cannot be empty"); - return getErrorResponse(ActionStatus.FILTER_NOT_FOUND); + LOGGER.error("Expecting a component and a component instance id, given was '{}' and '{}'", component, componentInstanceId); + final String componentName = component == null ? "?" : component.getName(); + return Either.right(componentsUtils.getResponseFormat(ActionStatus.COMPONENT_INSTANCE_NOT_FOUND, componentName, componentInstanceId)); } if (CollectionUtils.isEmpty(component.getComponentInstances()) || component.getComponentInstances().stream() .noneMatch(ci -> ci.getUniqueId().equals(componentInstanceId))) { - LOGGER.error("Component Instance list is empty"); - return getErrorResponse(ActionStatus.FILTER_NOT_FOUND); + LOGGER.error("Component '{}' node instance list is empty or component instance '{}' not found", + component.getUniqueId(), componentInstanceId); + return Either.right(componentsUtils.getResponseFormat(ActionStatus.COMPONENT_INSTANCE_NOT_FOUND, + component.getName(), componentInstanceId)); } return Either.left(Boolean.TRUE); } - private Either<Boolean, ResponseFormat> getErrorResponse(ActionStatus actionStatus, String... variables) { - ResponseFormat errorResponse = ResponseFormatManager.getInstance().getResponseFormat(actionStatus, variables); - return Either.right(errorResponse); - } - public Either<Boolean, ResponseFormat> validateFilter(final Component parentComponent, final String componentInstanceId, - final List<String> uiConstraints, final NodeFilterConstraintAction action, - final NodeFilterConstraintType nodeFilterConstraintType, - final String capabilityName) { - try { - if (NodeFilterConstraintAction.ADD == action || NodeFilterConstraintAction.UPDATE == action) { - for (final String uiConstraint : uiConstraints) { - final UIConstraint constraint = new ConstraintConvertor().convert(uiConstraint); - if (ConstraintConvertor.PROPERTY_CONSTRAINT.equals(constraint.getSourceType())) { - final Either<Boolean, ResponseFormat> booleanResponseFormatEither = validatePropertyConstraint(parentComponent, - componentInstanceId, constraint, capabilityName); - if (booleanResponseFormatEither.isRight()) { - return booleanResponseFormatEither; - } - } - else if (ConstraintConvertor.SERVICE_INPUT_CONSTRAINT.equals(constraint.getSourceType())) { - final Either<Boolean, ResponseFormat> booleanResponseFormatEither = validateInputConstraint(parentComponent, - componentInstanceId, constraint); - if (booleanResponseFormatEither.isRight()) { - return booleanResponseFormatEither; - } - } - else if (ConstraintConvertor.STATIC_CONSTRAINT.equals(constraint.getSourceType())) { - Either<Boolean, ResponseFormat> booleanResponseFormatEither; - if (NodeFilterConstraintType.PROPERTIES.equals(nodeFilterConstraintType)) { - booleanResponseFormatEither = isComponentPropertyFilterValid(parentComponent, componentInstanceId, constraint); - } else { - booleanResponseFormatEither = isComponentCapabilityPropertyFilterValid(parentComponent, componentInstanceId, constraint); - } - if (booleanResponseFormatEither.isRight()) { - return booleanResponseFormatEither; - } - } - } + final List<FilterConstraintDto> filterConstraint) { + if (CollectionUtils.isEmpty(filterConstraint)) { + return Either.left(true); + } + for (final FilterConstraintDto filterConstraintDto : filterConstraint) { + final Either<Boolean, ResponseFormat> validationEither = + validateFilter(parentComponent, componentInstanceId, filterConstraintDto); + if (validationEither.isRight()) { + return validationEither; } - } catch (final Exception e) { - LOGGER.debug("Provided constraint" + uiConstraints, e); - return Either.right(componentsUtils.getResponseFormat(ActionStatus.CONSTRAINT_FORMAT_INCORRECT)); } return Either.left(true); } - - private Either<Boolean, ResponseFormat> isComponentCapabilityPropertyFilterValid(final Component parentComponent, - final String componentInstanceId, - final UIConstraint uiConstraint) { - return validateStaticValueAndOperatorOfCapabilityProperties(parentComponent, componentInstanceId, uiConstraint); + public Either<Boolean, ResponseFormat> validateFilter(final Component parentComponent, final String componentInstanceId, + final FilterConstraintDto filterConstraint) { + validateFilterConstraint(filterConstraint); + switch (filterConstraint.getValueType()) { + case STATIC: + if (filterConstraint.isCapabilityPropertyFilter()) { + return validateStaticValueAndOperatorOfCapabilityProperties(parentComponent, componentInstanceId, filterConstraint); + } else { + return validateStaticValueAndOperator(parentComponent, componentInstanceId, filterConstraint); + } + case GET_PROPERTY: + return validatePropertyConstraint(parentComponent, componentInstanceId, filterConstraint, filterConstraint.getCapabilityName()); + case GET_INPUT: + return validateInputConstraint(parentComponent, componentInstanceId, filterConstraint); + default: + return Either.left(true); + } } - private Either<Boolean, ResponseFormat> isComponentPropertyFilterValid(Component parentComponent, String componentInstanceId, - UIConstraint constraint) { - return validateStaticValueAndOperator(parentComponent, componentInstanceId, constraint); + private void validateFilterConstraint(final FilterConstraintDto filterConstraint) { + filterConstraintValidator.validate(filterConstraint); } private Either<Boolean, ResponseFormat> validatePropertyConstraint(final Component parentComponent, final String componentInstanceId, - final UIConstraint uiConstraint, final String capabilityName) { + final FilterConstraintDto filterConstraint, final String capabilityName) { String source = SOURCE; - final Optional<ComponentInstance> optionalComponentInstance; - final List<PropertyDefinition> propertyDefinitions = parentComponent.getProperties(); - final var SELF = "SELF"; - List<? extends PropertyDefinition> sourcePropertyDefinition = - SELF.equalsIgnoreCase(uiConstraint.getSourceName()) && propertyDefinitions != null ? propertyDefinitions - : Collections.emptyList(); - if (sourcePropertyDefinition.isEmpty() && !SELF.equalsIgnoreCase(uiConstraint.getSourceName())) { - optionalComponentInstance = parentComponent.getComponentInstances().stream() - .filter(componentInstance -> uiConstraint.getSourceName().equals(componentInstance.getName())).findFirst(); - if (optionalComponentInstance.isPresent()) { - final List<ComponentInstanceProperty> componentInstanceProperties = parentComponent.getComponentInstancesProperties() - .get(optionalComponentInstance.get().getUniqueId()); - sourcePropertyDefinition = componentInstanceProperties == null ? new ArrayList<>() : componentInstanceProperties; - } + final ToscaGetFunctionDataDefinition toscaGetFunction = filterConstraint.getAsToscaGetFunction().orElse(null); + if (toscaGetFunction == null || !(filterConstraint.getValue() instanceof ToscaGetFunctionDataDefinition)) { + return Either.right(componentsUtils.getResponseFormat(ActionStatus.TOSCA_FUNCTION_EXPECTED_ERROR)); } - if (CollectionUtils.isNotEmpty(sourcePropertyDefinition)) { - final Optional<? extends PropertyDefinition> sourceSelectedProperty = sourcePropertyDefinition.stream() - .filter(property -> uiConstraint.getValue().equals(property.getName())).findFirst(); - Optional<? extends PropertyDefinition> targetComponentInstanceProperty = getProperty(parentComponent, componentInstanceId, capabilityName, uiConstraint.getServicePropertyName()); - - source = !targetComponentInstanceProperty.isPresent() ? "Target" : SOURCE; - if (sourceSelectedProperty.isPresent() && targetComponentInstanceProperty.isPresent()) { - return validatePropertyData(uiConstraint, sourceSelectedProperty, targetComponentInstanceProperty); + final Optional<? extends ToscaPropertyData> sourceSelectedProperty = findPropertyFromGetFunction(parentComponent, toscaGetFunction); + if (sourceSelectedProperty.isPresent()) { + Optional<? extends PropertyDefinition> targetComponentInstanceProperty = + getInstanceProperties(parentComponent, componentInstanceId, capabilityName, filterConstraint.getPropertyName()); + + source = targetComponentInstanceProperty.isEmpty() ? TARGET : SOURCE; + if (targetComponentInstanceProperty.isPresent()) { + final ResponseFormat responseFormat = validatePropertyData(sourceSelectedProperty.get(), targetComponentInstanceProperty.get()); + if (responseFormat != null) { + return Either.right(responseFormat); + } + return Either.left(true); } } - final String missingProperty = source.equals(SOURCE) ? uiConstraint.getValue().toString() : uiConstraint.getServicePropertyName(); - return Either.right(componentsUtils.getResponseFormat(ActionStatus.MAPPED_PROPERTY_NOT_FOUND, source, missingProperty)); + final String missingProperty = SOURCE.equals(source) ? filterConstraint.getValue().toString() : filterConstraint.getPropertyName(); + return Either.right(componentsUtils.getResponseFormat(ActionStatus.FILTER_PROPERTY_NOT_FOUND, source, missingProperty)); + } + + private Optional<? extends ToscaPropertyData> findPropertyFromGetFunction(final Component parentComponent, + final ToscaGetFunctionDataDefinition toscaGetFunction) { + List<? extends ToscaPropertyData> sourcePropertyDefinitions; + if (PropertySource.SELF == toscaGetFunction.getPropertySource()) { + sourcePropertyDefinitions = getSelfPropertyFromGetFunction(parentComponent, toscaGetFunction); + } else { + sourcePropertyDefinitions = getInstancePropertiesBasedOnGetFunctionSource(parentComponent, toscaGetFunction); + } + final List<String> propertyPath = toscaGetFunction.getPropertyPathFromSource(); + final Optional<? extends ToscaPropertyData> sourceProperty = sourcePropertyDefinitions.stream() + .filter(propertyDefinition -> propertyDefinition.getName().equals(propertyPath.get(0))).findFirst(); + if (sourceProperty.isEmpty() || propertyPath.size() == 1) { + return sourceProperty; + } + final Either<Map<String, DataTypeDefinition>, JanusGraphOperationStatus> allDataTypesEither = + applicationDataTypeCache.getAll(parentComponent.getModel()); + if (allDataTypesEither.isRight()) { + return Optional.empty(); + } + return findSubProperty(propertyPath.subList(1, propertyPath.size()), sourceProperty.get().getType(), allDataTypesEither.left().value()); + } + + private List<? extends ToscaPropertyData> getInstancePropertiesBasedOnGetFunctionSource(final Component parentComponent, + final ToscaGetFunctionDataDefinition toscaGetFunction) { + final ComponentInstance componentInstance = parentComponent.getComponentInstances().stream() + .filter(componentInstance1 -> componentInstance1.getName().equals(toscaGetFunction.getSourceName())) + .findFirst() + .orElse(null); + if (componentInstance == null) { + return List.of(); + } + final List<? extends ToscaPropertyData> instanceProperties; + switch (toscaGetFunction.getFunctionType()) { + case GET_PROPERTY: + instanceProperties = parentComponent.getComponentInstancesProperties().get(componentInstance.getUniqueId()); + break; + case GET_ATTRIBUTE: + instanceProperties = parentComponent.getComponentInstancesAttributes().get(componentInstance.getUniqueId()); + break; + default: + instanceProperties = List.of(); + } + if (instanceProperties == null) { + return List.of(); + } + return instanceProperties; + } + + private static List<? extends ToscaPropertyData> getSelfPropertyFromGetFunction(final Component component, + final ToscaGetFunctionDataDefinition toscaGetFunction) { + switch (toscaGetFunction.getFunctionType()) { + case GET_INPUT: + if (component.getInputs() != null) { + return component.getInputs(); + } + break; + case GET_PROPERTY: + if (component.getProperties() != null) { + return component.getProperties(); + } + break; + case GET_ATTRIBUTE: + if (component.getAttributes() != null) { + return component.getAttributes(); + } + break; + } + return List.of(); } - - private Optional<ComponentInstanceProperty> getProperty(final Component parentComponent, final String componentInstanceId, - final String capabilityName, final String propertyName) { + private Optional<PropertyDefinition> findSubProperty(final List<String> propertyPath, final String parentPropertyType, + final Map<String, DataTypeDefinition> modelDataTypes) { + final DataTypeDefinition dataTypeDefinition = modelDataTypes.get(parentPropertyType); + if (CollectionUtils.isEmpty(dataTypeDefinition.getProperties())) { + return Optional.empty(); + } + final PropertyDefinition propertyDefinition = dataTypeDefinition.getProperties().stream() + .filter(propertyDefinition1 -> propertyDefinition1.getName().equals(propertyPath.get(0))).findFirst().orElse(null); + if (propertyDefinition == null) { + return Optional.empty(); + } + if (propertyPath.size() == 1) { + return Optional.of(propertyDefinition); + } + return findSubProperty(propertyPath.subList(1, propertyPath.size()), propertyDefinition.getType(), modelDataTypes); + } + + private Optional<ComponentInstanceProperty> getInstanceProperties(final Component parentComponent, final String componentInstanceId, + final String capabilityName, final String propertyName) { if (StringUtils.isEmpty(capabilityName)) { return parentComponent.getComponentInstancesProperties().get(componentInstanceId).stream() .filter(property -> propertyName.equals(property.getName())).findFirst(); @@ -195,80 +259,109 @@ public class NodeFilterValidator { } private Either<Boolean, ResponseFormat> validateInputConstraint(final Component parentComponent, final String componentInstanceId, - final UIConstraint uiConstraint) { + final FilterConstraintDto filterConstraint) { final List<InputDefinition> sourceInputDefinition = parentComponent.getInputs(); - if (CollectionUtils.isNotEmpty(sourceInputDefinition)) { - final Optional<? extends InputDefinition> sourceSelectedProperty = sourceInputDefinition.stream() - .filter(input -> uiConstraint.getValue().equals(input.getName())).findFirst(); - final Optional<? extends PropertyDefinition> targetComponentInstanceProperty = parentComponent.getComponentInstancesProperties() - .get(componentInstanceId).stream().filter(property -> uiConstraint.getServicePropertyName().equals(property.getName())).findFirst(); - if (sourceSelectedProperty.isPresent() && targetComponentInstanceProperty.isPresent()) { - return validatePropertyData(uiConstraint, sourceSelectedProperty, targetComponentInstanceProperty); + if (CollectionUtils.isEmpty(sourceInputDefinition)) { + LOGGER.debug("Parent component '{}', unique id '{}', does not have inputs", parentComponent.getName(), parentComponent.getUniqueId()); + return Either.right(componentsUtils.getResponseFormat(ActionStatus.COMPONENT_DOES_NOT_HAVE_INPUTS, parentComponent.getName())); + } + if (!(filterConstraint.getValue() instanceof ToscaGetFunctionDataDefinition)) { + return Either.right(componentsUtils.getResponseFormat(ActionStatus.TOSCA_FUNCTION_EXPECTED_ERROR)); + } + final ToscaGetFunctionDataDefinition getFunction = (ToscaGetFunctionDataDefinition) filterConstraint.getValue(); + final List<String> propertyPathFromSource = getFunction.getPropertyPathFromSource(); + Optional<? extends PropertyDefinition> sourceSelectedProperty = + sourceInputDefinition.stream().filter(input -> input.getName().equals(propertyPathFromSource.get(0))).findFirst(); + if (sourceSelectedProperty.isEmpty()) { + LOGGER.debug(INPUT_NOT_FOUND_LOG, + propertyPathFromSource.get(0), parentComponent.getName(), parentComponent.getUniqueId()); + return Either.right( + componentsUtils.getResponseFormat(ActionStatus.COMPONENT_INPUT_NOT_FOUND, propertyPathFromSource.get(0), parentComponent.getName()) + ); + } + if (propertyPathFromSource.size() > 1) { + final Either<Map<String, DataTypeDefinition>, JanusGraphOperationStatus> allDataTypesEither = + applicationDataTypeCache.getAll(parentComponent.getModel()); + if (allDataTypesEither.isRight()) { + LOGGER.error("Could not load data types for model {}", parentComponent.getModel()); + return Either.right(componentsUtils.getResponseFormat(ActionStatus.DATA_TYPES_NOT_LOADED, parentComponent.getModel())); + } + sourceSelectedProperty = + findSubProperty(propertyPathFromSource.subList(1, propertyPathFromSource.size()), sourceSelectedProperty.get().getType(), + allDataTypesEither.left().value()); + } + final Optional<? extends PropertyDefinition> targetComponentInstanceProperty = + parentComponent.getComponentInstancesProperties() + .get(componentInstanceId).stream() + .filter(property -> filterConstraint.getPropertyName().equals(property.getName())) + .findFirst(); + if (sourceSelectedProperty.isPresent() && targetComponentInstanceProperty.isPresent()) { + final ResponseFormat responseFormat = validatePropertyData(sourceSelectedProperty.get(), targetComponentInstanceProperty.get()); + if (responseFormat != null) { + return Either.right(responseFormat); } + return Either.left(true); } - LOGGER.debug("Parent component does not have inputs", parentComponent); + return Either.right(componentsUtils.getResponseFormat(ActionStatus.INPUTS_NOT_FOUND)); } - private Either<Boolean, ResponseFormat> validatePropertyData(UIConstraint uiConstraint, - Optional<? extends PropertyDefinition> sourceSelectedProperty, - Optional<? extends PropertyDefinition> targetComponentInstanceProperty) { - if (sourceSelectedProperty.isPresent() && targetComponentInstanceProperty.isPresent()) { - final PropertyDefinition sourcePropDefinition = sourceSelectedProperty.get(); - final String sourceType = sourcePropDefinition.getType(); - final PropertyDefinition targetPropDefinition = targetComponentInstanceProperty.get(); - final String targetType = targetPropDefinition.getType(); - if (sourceType.equals(targetType)) { - if (schemableTypes.contains(sourceType)) { - final SchemaDefinition sourceSchemaDefinition = sourcePropDefinition.getSchema(); - final SchemaDefinition targetSchemaDefinition = targetPropDefinition.getSchema(); - if (!sourceSchemaDefinition.equals(targetSchemaDefinition)) { - return Either.right(componentsUtils - .getResponseFormat(ActionStatus.SOURCE_TARGET_SCHEMA_MISMATCH, uiConstraint.getServicePropertyName(), - uiConstraint.getValue().toString())); - } + private <T extends ToscaPropertyData> ResponseFormat validatePropertyData(final T sourcePropDefinition, + final T targetPropDefinition) { + final String sourceType = sourcePropDefinition.getType(); + final String targetType = targetPropDefinition.getType(); + if (sourceType.equals(targetType)) { + if (TYPES_WITH_SCHEMA.contains(sourceType)) { + final String sourceSchemaType = sourcePropDefinition.getSchemaType(); + final String targetSchemaType = targetPropDefinition.getSchemaType(); + if (sourceSchemaType != null && !sourceSchemaType.equals(targetSchemaType)) { + return componentsUtils.getResponseFormat(ActionStatus.SOURCE_TARGET_SCHEMA_MISMATCH, + targetPropDefinition.getName(), targetSchemaType, sourcePropDefinition.getName(), sourceSchemaType); } - return Either.left(Boolean.TRUE); - } else { - return Either.right(componentsUtils - .getResponseFormat(ActionStatus.SOURCE_TARGET_PROPERTY_TYPE_MISMATCH, uiConstraint.getServicePropertyName(), - uiConstraint.getValue().toString())); } - } else { - LOGGER.debug("Null value passed to `validatePropertyData` - sourceSelectedProperty: '{}' - targetComponentInstanceProperty: '{}'", - sourceSelectedProperty, targetComponentInstanceProperty); - return Either.right(componentsUtils - .getResponseFormat(ActionStatus.GENERAL_ERROR, uiConstraint.getServicePropertyName(), uiConstraint.getValue().toString())); + return null; } + return componentsUtils.getResponseFormat(ActionStatus.SOURCE_TARGET_PROPERTY_TYPE_MISMATCH, + sourcePropDefinition.getName(), sourcePropDefinition.getType(), targetPropDefinition.getName(), targetPropDefinition.getType()); } private Either<Boolean, ResponseFormat> validateStaticValueAndOperator(final Component parentComponent, final String componentInstanceId, - final UIConstraint uiConstraint) { - if (!(Objects.nonNull(uiConstraint) && uiConstraint.getValue() instanceof String)) { - return Either.left(false); - } - //TODO: get capabilities properties when constraint type is capabilities - final Optional<ComponentInstanceProperty> componentInstanceProperty = parentComponent.getComponentInstancesProperties() - .get(componentInstanceId).stream().filter(property -> uiConstraint.getServicePropertyName().equals(property.getName())).findFirst(); - if (!componentInstanceProperty.isPresent()) { - return Either.right(componentsUtils.getResponseFormat(ActionStatus.SELECTED_PROPERTY_NOT_PRESENT, uiConstraint.getServicePropertyName())); - } - if (comparableConstraintsOperators.contains(uiConstraint.getConstraintOperator()) && !comparableTypes - .contains(componentInstanceProperty.get().getType())) { - return Either.right(componentsUtils.getResponseFormat(ActionStatus.UNSUPPORTED_OPERATOR_PROVIDED, uiConstraint.getServicePropertyName(), - uiConstraint.getConstraintOperator())); - } - return isValidValueCheck(componentInstanceProperty.get().getType(), String.valueOf(uiConstraint.getValue()), - uiConstraint.getServicePropertyName()); + final FilterConstraintDto filterConstraint) { + final ComponentInstanceProperty componentInstanceProperty = parentComponent.getComponentInstancesProperties() + .get(componentInstanceId).stream().filter(property -> filterConstraint.getPropertyName().equals(property.getName())) + .findFirst() + .orElse(null); + if (componentInstanceProperty == null) { + return Either.right(componentsUtils.getResponseFormat(ActionStatus.SELECTED_PROPERTY_NOT_PRESENT, filterConstraint.getPropertyName())); + } + if (filterConstraint.getOperator().isComparable() && !COMPARABLE_TYPES.contains(componentInstanceProperty.getType())) { + return Either.right(componentsUtils.getResponseFormat(ActionStatus.UNSUPPORTED_OPERATOR_PROVIDED, filterConstraint.getPropertyName(), + filterConstraint.getOperator().getType())); + } + return isValidValueCheck(componentInstanceProperty.getType(), componentInstanceProperty.getSchemaType(), parentComponent.getModel(), + filterConstraint.getValue(), filterConstraint.getPropertyName()); + } + + private Either<Boolean, ResponseFormat> validateStaticSubstitutionFilter(final Component component, + final FilterConstraintDto filterConstraint) { + + final PropertyDefinition componentProperty = component.getProperties().stream() + .filter(property -> property.getName().equals(filterConstraint.getPropertyName())).findFirst().orElse(null); + if (componentProperty == null) { + return Either.right(componentsUtils.getResponseFormat(ActionStatus.SELECTED_PROPERTY_NOT_PRESENT, filterConstraint.getPropertyName())); + } + if (filterConstraint.getOperator().isComparable() && !COMPARABLE_TYPES.contains(componentProperty.getType())) { + return Either.right(componentsUtils.getResponseFormat(ActionStatus.UNSUPPORTED_OPERATOR_PROVIDED, filterConstraint.getPropertyName(), + filterConstraint.getOperator().getType())); + } + return isValidValueCheck(componentProperty.getType(), componentProperty.getSchemaType(), component.getModel(), + filterConstraint.getValue(), filterConstraint.getPropertyName()); } private Either<Boolean, ResponseFormat> validateStaticValueAndOperatorOfCapabilityProperties(final Component parentComponent, final String componentInstanceId, - final UIConstraint uiConstraint) { - if (!(Objects.nonNull(uiConstraint) && uiConstraint.getValue() instanceof String)) { - return Either.left(false); - } - Optional<ComponentInstanceProperty> optionalComponentInstanceProperty = Optional.empty(); + final FilterConstraintDto filterConstraint) { + ComponentInstanceProperty componentInstanceProperty = null; final Optional<ComponentInstance> optionalComponentInstances = parentComponent.getComponentInstances().stream() .filter(componentInstance -> componentInstanceId.equalsIgnoreCase(componentInstance.getUniqueId())).findFirst(); if (optionalComponentInstances.isPresent()) { @@ -277,99 +370,136 @@ public class NodeFilterValidator { .allMatch(capabilityDefinition -> capabilityDefinition.getProperties() != null)).collect(Collectors.toList()).stream().filter( capabilityDefinitions -> capabilityDefinitions.stream().allMatch( capabilityDefinition -> capabilityDefinition.getProperties().stream().anyMatch( - componentInstanceProperty -> uiConstraint.getServicePropertyName() - .equalsIgnoreCase(componentInstanceProperty.getName())))).findFirst(); + componentInstanceProperty1 -> filterConstraint.getPropertyName() + .equalsIgnoreCase(componentInstanceProperty1.getName())))).findFirst(); if (optionalCapabilityDefinitionList.isPresent() && !optionalCapabilityDefinitionList.get().isEmpty()) { - optionalComponentInstanceProperty = getComponentInstanceProperty(optionalCapabilityDefinitionList.get().get(0), uiConstraint.getServicePropertyName()); + componentInstanceProperty = + getComponentInstanceProperty(optionalCapabilityDefinitionList.get().get(0), filterConstraint.getPropertyName()).orElse(null); } } - if (optionalComponentInstanceProperty.isEmpty()) { - return Either.right(componentsUtils.getResponseFormat(ActionStatus.SELECTED_PROPERTY_NOT_PRESENT, uiConstraint.getServicePropertyName())); + if (componentInstanceProperty == null) { + return Either.right(componentsUtils.getResponseFormat(ActionStatus.SELECTED_PROPERTY_NOT_PRESENT, filterConstraint.getPropertyName())); } - if (comparableConstraintsOperators.contains(uiConstraint.getConstraintOperator()) && !comparableTypes - .contains(optionalComponentInstanceProperty.get().getType())) { - return Either.right(componentsUtils.getResponseFormat(ActionStatus.UNSUPPORTED_OPERATOR_PROVIDED, uiConstraint.getServicePropertyName(), - uiConstraint.getConstraintOperator())); + if (filterConstraint.getOperator().isComparable() && !COMPARABLE_TYPES.contains(componentInstanceProperty.getType())) { + return Either.right(componentsUtils.getResponseFormat(ActionStatus.UNSUPPORTED_OPERATOR_PROVIDED, filterConstraint.getPropertyName(), + filterConstraint.getOperator().getType())); } - return isValidValueCheck(optionalComponentInstanceProperty.get().getType(), String.valueOf(uiConstraint.getValue()), - uiConstraint.getServicePropertyName()); + return isValidValueCheck(componentInstanceProperty.getType(), componentInstanceProperty.getSchemaType(), parentComponent.getModel(), + filterConstraint.getValue(), filterConstraint.getPropertyName()); } private Optional<ComponentInstanceProperty> getComponentInstanceProperty(CapabilityDefinition capabilityDefinition, final String propertyName){ return capabilityDefinition.getProperties().stream().filter(property -> property.getName().equals(propertyName)).findAny(); } - private Either<Boolean, ResponseFormat> isValidValueCheck(String type, String value, String propertyName) { - ToscaPropertyType toscaPropertyType = ToscaPropertyType.isValidType(type); - if (Objects.isNull(toscaPropertyType)) { + private Either<Boolean, ResponseFormat> isValidValueCheck(final String type, final String schemaType, final String model, + final Object value, final String propertyName) { + final Either<Map<String, DataTypeDefinition>, JanusGraphOperationStatus> allDataTypesEither = + applicationDataTypeCache.getAll(model); + if (allDataTypesEither.isRight()) { + LOGGER.error("Could not validate filter value. Could not load data types for model {}", model); + return Either.right(componentsUtils.getResponseFormat(ActionStatus.DATA_TYPES_NOT_LOADED, model)); + } + final Map<String, DataTypeDefinition> modelDataTypesMap = allDataTypesEither.left().value(); + final ToscaPropertyType toscaPropertyType = ToscaPropertyType.isValidType(type); + if (toscaPropertyType == null && !modelDataTypesMap.containsKey(type)) { return Either.right(componentsUtils.getResponseFormat(ActionStatus.UNSUPPORTED_PROPERTY_TYPE, type, propertyName)); } - if (toscaPropertyType.getValidator().isValid(value, null)) { - return Either.left(Boolean.TRUE); + final String valueAsJsonString; + try { + valueAsJsonString = new Gson().toJson(value); + } catch (final Exception e) { + LOGGER.debug("Unsupported property filter value", e); + return Either.right(componentsUtils.getResponseFormat(ActionStatus.UNSUPPORTED_VALUE_PROVIDED, type, propertyName, String.valueOf(value))); + } + if (toscaPropertyType != null) { + if (toscaPropertyType.getValidator().isValid(valueAsJsonString, schemaType, modelDataTypesMap)) { + return Either.left(true); + } + } else { + if (DataTypeValidatorConverter.getInstance().isValid(valueAsJsonString, modelDataTypesMap.get(type), modelDataTypesMap)) { + return Either.left(true); + } } - return Either.right(componentsUtils.getResponseFormat(ActionStatus.UNSUPPORTED_VALUE_PROVIDED, type, propertyName, value)); + + return Either.right(componentsUtils.getResponseFormat(ActionStatus.UNSUPPORTED_VALUE_PROVIDED, type, propertyName, valueAsJsonString)); } - public Either<Boolean, ResponseFormat> validateComponentFilter(final Component component, final List<String> uiConstraints, - final NodeFilterConstraintAction action) { - try { - if (NodeFilterConstraintAction.ADD == action || NodeFilterConstraintAction.UPDATE == action) { - for (final String uiConstraint : uiConstraints) { - final UIConstraint constraint = new ConstraintConvertor().convert(uiConstraint); - if (ConstraintConvertor.PROPERTY_CONSTRAINT.equals(constraint.getSourceType())) { - final Either<Boolean, ResponseFormat> booleanResponseFormatEither = validateComponentPropertyConstraint(component, - constraint); - if (booleanResponseFormatEither.isRight()) { - return booleanResponseFormatEither; - } - } else if (ConstraintConvertor.STATIC_CONSTRAINT.equals(constraint.getSourceType())) { - final Either<Boolean, ResponseFormat> booleanResponseFormatEither = validateComponentStaticValueAndOperator(component, - constraint); - if (booleanResponseFormatEither.isRight()) { - return booleanResponseFormatEither; - } - } - } - } - } catch (final Exception e) { - LOGGER.debug("Provided constraint" + uiConstraints, e); + public Either<Boolean, ResponseFormat> validateSubstitutionFilter(final Component component, final List<FilterConstraintDto> filterConstraintList) { + if (CollectionUtils.isEmpty(filterConstraintList)) { return Either.right(componentsUtils.getResponseFormat(ActionStatus.CONSTRAINT_FORMAT_INCORRECT)); } + for (final FilterConstraintDto filterConstraintDto : filterConstraintList) { + final Either<Boolean, ResponseFormat> validationEither = validateSubstitutionFilter(component, filterConstraintDto); + if (validationEither.isRight()) { + return validationEither; + } + } return Either.left(true); } - private Either<Boolean, ResponseFormat> validateComponentPropertyConstraint(final Component component, final UIConstraint uiConstraint) { - String source = SOURCE; - final List<PropertyDefinition> propertyDefinitions = component.getProperties(); - if (CollectionUtils.isNotEmpty(propertyDefinitions)) { - final Optional<? extends PropertyDefinition> sourceSelectedProperty = propertyDefinitions.stream() - .filter(property -> uiConstraint.getValue().equals(property.getName())).findFirst(); - final Optional<? extends PropertyDefinition> targetComponentProperty = component.getProperties().stream() - .filter(property -> uiConstraint.getServicePropertyName().equals(property.getName())).findFirst(); - source = !targetComponentProperty.isPresent() ? "Target" : SOURCE; - if (sourceSelectedProperty.isPresent() && targetComponentProperty.isPresent()) { - return validatePropertyData(uiConstraint, sourceSelectedProperty, targetComponentProperty); - } + public Either<Boolean, ResponseFormat> validateSubstitutionFilter(final Component component, final FilterConstraintDto filterConstraint) { + validateFilterConstraint(filterConstraint); + switch (filterConstraint.getValueType()) { + case STATIC: + return validateStaticSubstitutionFilter(component, filterConstraint); + case GET_PROPERTY: + case GET_ATTRIBUTE: + case GET_INPUT: + return validateSubstitutionFilterGetFunctionConstraint(component, filterConstraint); + default: + return Either.left(true); } - final String missingProperty = source.equals(SOURCE) ? uiConstraint.getValue().toString() : uiConstraint.getServicePropertyName(); - return Either.right(componentsUtils.getResponseFormat(ActionStatus.MAPPED_PROPERTY_NOT_FOUND, source, missingProperty)); } - private Either<Boolean, ResponseFormat> validateComponentStaticValueAndOperator(final Component component, final UIConstraint uiConstraint) { - if (!(Objects.nonNull(uiConstraint) && uiConstraint.getValue() instanceof String)) { - return Either.left(false); + private Either<Boolean, ResponseFormat> validateSubstitutionFilterGetFunctionConstraint(final Component component, + final FilterConstraintDto filterConstraint) { + final ToscaGetFunctionDataDefinition toscaGetFunction = filterConstraint.getAsToscaGetFunction().orElse(null); + if (toscaGetFunction == null) { + return Either.right(componentsUtils.getResponseFormat(ActionStatus.TOSCA_FUNCTION_EXPECTED_ERROR)); } - final Optional<PropertyDefinition> componentProperty = component.getProperties().stream() - .filter(property -> uiConstraint.getServicePropertyName().equals(property.getName())).findFirst(); - if (componentProperty.isEmpty()) { - return Either.right(componentsUtils.getResponseFormat(ActionStatus.SELECTED_PROPERTY_NOT_PRESENT, uiConstraint.getServicePropertyName())); + + if (CollectionUtils.isEmpty(component.getProperties())) { + return Either.right( + componentsUtils.getResponseFormat(ActionStatus.FILTER_PROPERTY_NOT_FOUND, TARGET, getPropertyType(toscaGetFunction), + filterConstraint.getPropertyName()) + ); + } + + final Optional<? extends PropertyDefinition> targetComponentProperty = component.getProperties().stream() + .filter(property -> property.getName().equals(filterConstraint.getPropertyName())).findFirst(); + if (targetComponentProperty.isEmpty()) { + return Either.right( + componentsUtils.getResponseFormat(ActionStatus.FILTER_PROPERTY_NOT_FOUND, TARGET, getPropertyType(toscaGetFunction), + filterConstraint.getPropertyName()) + ); } - if (comparableConstraintsOperators.contains(uiConstraint.getConstraintOperator()) && !comparableTypes - .contains(componentProperty.get().getType())) { - return Either.right(componentsUtils.getResponseFormat(ActionStatus.UNSUPPORTED_OPERATOR_PROVIDED, uiConstraint.getServicePropertyName(), - uiConstraint.getConstraintOperator())); + + final Optional<? extends ToscaPropertyData> sourceSelectedProperty = findPropertyFromGetFunction(component, toscaGetFunction); + if (sourceSelectedProperty.isEmpty()) { + return Either.right(componentsUtils.getResponseFormat(ActionStatus.FILTER_PROPERTY_NOT_FOUND, SOURCE, getPropertyType(toscaGetFunction), + String.join("->", toscaGetFunction.getPropertyPathFromSource()))); + } + + final ResponseFormat responseFormat = validatePropertyData(sourceSelectedProperty.get(), targetComponentProperty.get()); + if (responseFormat != null) { + return Either.right(responseFormat); } - return isValidValueCheck(componentProperty.get().getType(), String.valueOf(uiConstraint.getValue()), uiConstraint.getServicePropertyName()); + return Either.left(true); } + + private String getPropertyType(final ToscaGetFunctionDataDefinition toscaGetFunction) { + switch (toscaGetFunction.getType()) { + case GET_INPUT: + return "input"; + case GET_PROPERTY: + return "property"; + case GET_ATTRIBUTE: + return "attribute"; + default: + return ""; + } + } + } diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/datamodel/utils/ConstraintConvertor.java b/catalog-be/src/main/java/org/openecomp/sdc/be/datamodel/utils/ConstraintConvertor.java index a2c7aa2502..8e823bbe9f 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/datamodel/utils/ConstraintConvertor.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/datamodel/utils/ConstraintConvertor.java @@ -19,15 +19,15 @@ */ package org.openecomp.sdc.be.datamodel.utils; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSet; import java.util.ArrayList; -import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.Set; -import org.openecomp.sdc.be.model.tosca.constraints.ConstraintType; +import org.openecomp.sdc.be.datatypes.elements.ToscaFunctionType; +import org.openecomp.sdc.be.datatypes.enums.PropertySource; +import org.openecomp.sdc.be.datatypes.enums.ConstraintType; import org.openecomp.sdc.be.ui.model.UIConstraint; import org.openecomp.sdc.tosca.datatypes.ToscaFunctions; import org.slf4j.Logger; @@ -37,91 +37,92 @@ import org.yaml.snakeyaml.Yaml; public class ConstraintConvertor { - public static final String EQUAL_OPERATOR = ConstraintType.EQUAL.getTypes().get(1); - public static final String GREATER_THAN_OPERATOR = ConstraintType.GREATER_THAN.getTypes().get(1); - public static final String LESS_THAN_OPERATOR = ConstraintType.LESS_THAN.getTypes().get(1); - public static final String GREATER_OR_EQUAL_OPERATOR = ConstraintType.GREATER_OR_EQUAL.getTypes().get(1); - public static final String LESS_OR_EQUAL_OPERATOR = ConstraintType.LESS_OR_EQUAL.getTypes().get(1); public static final String STATIC_CONSTRAINT = "static"; public static final String PROPERTY_CONSTRAINT = "property"; public static final String SERVICE_INPUT_CONSTRAINT = "service_input"; public static final String SELF = "SELF"; private static final Logger logger = LoggerFactory.getLogger(ConstraintConvertor.class); - private static Set<String> SUPPORTED_CONSTRAINT_LIST = ImmutableSet.of(EQUAL_OPERATOR, GREATER_THAN_OPERATOR, LESS_THAN_OPERATOR, GREATER_OR_EQUAL_OPERATOR, LESS_OR_EQUAL_OPERATOR); - private static Set<String> SUPPORTED_FUNCTIONS = ImmutableSet - .of(ToscaFunctions.GET_INPUT.getFunctionName(), ToscaFunctions.GET_PROPERTY.getFunctionName()); + private static final Set<ConstraintType> SUPPORTED_CONSTRAINT_LIST = + Set.of(ConstraintType.EQUAL, ConstraintType.GREATER_THAN, ConstraintType.LESS_THAN, + ConstraintType.GREATER_OR_EQUAL, ConstraintType.LESS_OR_EQUAL); - public UIConstraint convert(String inConstraint) { - return convert(inConstraint, ""); + public UIConstraint convert(final String constraintValue) { + return convert(constraintValue, null); } - public UIConstraint convert(String inConstraint, String valueType) { + public UIConstraint convert(final String inConstraint, final String valueType) { Yaml yamlSource = new Yaml(); UIConstraint uiConstraint = new UIConstraint(); Object content1 = yamlSource.load(inConstraint); if (!(content1 instanceof Map)) { return null; } - Map map1 = (Map) content1; - Object key = map1.keySet().iterator().next(); - uiConstraint.setServicePropertyName(key.toString()); - Object content2 = map1.get(key); - if (!(content2 instanceof Map)) { + Map propertyAndConstraintMap = (Map) content1; + Object propertyNameKey = propertyAndConstraintMap.keySet().iterator().next(); + uiConstraint.setServicePropertyName(propertyNameKey.toString()); + Object operatorMapObj = propertyAndConstraintMap.get(propertyNameKey); + if (!(operatorMapObj instanceof Map)) { return null; } - Map map2 = (Map) content2; - Object key2 = map2.keySet().iterator().next(); - final String operator = key2.toString(); - if (SUPPORTED_CONSTRAINT_LIST.contains(operator)) { + Map operatorMap = (Map) operatorMapObj; + Object operatorKey = operatorMap.keySet().iterator().next(); + final String operator = (String) operatorKey; + final Optional<ConstraintType> constraintType = ConstraintType.findByType(operator); + if (constraintType.isPresent() && SUPPORTED_CONSTRAINT_LIST.contains(constraintType.get())) { uiConstraint.setConstraintOperator(operator); } - Object content3 = map2.get(key2); - if (content3 instanceof String || content3 instanceof Number || content3 instanceof Boolean) { - uiConstraint.setValue(content3); + Object constraintValueObj = operatorMap.get(operatorKey); + if (constraintValueObj instanceof String || constraintValueObj instanceof Number || constraintValueObj instanceof Boolean) { + uiConstraint.setValue(constraintValueObj); uiConstraint.setSourceType(STATIC_CONSTRAINT); uiConstraint.setSourceName(STATIC_CONSTRAINT); return uiConstraint; - } else if (content3 instanceof List) { - List list1 = (List) content3; + } else if (constraintValueObj instanceof List) { uiConstraint.setSourceType(STATIC_CONSTRAINT); uiConstraint.setSourceName(STATIC_CONSTRAINT); - uiConstraint.setValue(list1); + uiConstraint.setValue(constraintValueObj); return uiConstraint; - } else if (valueType != null && valueType.equals("string")) { + } else if ("string".equals(valueType)) { uiConstraint.setSourceType(STATIC_CONSTRAINT); uiConstraint.setSourceName(STATIC_CONSTRAINT); - DumperOptions options = new DumperOptions(); - options.setDefaultFlowStyle(DumperOptions.FlowStyle.FLOW); - Yaml yaml = new Yaml(options); - String yamlString = yaml.dump(content3); - uiConstraint.setValue(yamlString); + uiConstraint.setValue(dumpYamlString(constraintValueObj)); return uiConstraint; - } else if (content3 instanceof Map) { - return handleMap(uiConstraint, content3); + } else if (constraintValueObj instanceof Map) { + return handleMap(uiConstraint, (Map<Object, Object>) constraintValueObj); } return null; } - private UIConstraint handleMap(UIConstraint uiConstraint, Object content3) { - Map map3 = (Map) content3; - Map.Entry entry = (Map.Entry) map3.entrySet().iterator().next(); + private String dumpYamlString(final Object constraintValueObj) { + final var dumperOptions = new DumperOptions(); + dumperOptions.setDefaultFlowStyle(DumperOptions.FlowStyle.FLOW); + return new Yaml(dumperOptions).dump(constraintValueObj); + } + + private UIConstraint handleMap(final UIConstraint uiConstraint, final Map<Object, Object> constraintValueAsMap) { + final Map.Entry<Object, Object> entry = constraintValueAsMap.entrySet().iterator().next(); final String firstKey = entry.getKey().toString().trim(); - if (!SUPPORTED_FUNCTIONS.contains(firstKey)) { - uiConstraint.setValue(content3); + final ToscaFunctionType toscaFunctionType = ToscaFunctionType.findType(firstKey).orElse(null); + if (toscaFunctionType == null) { + uiConstraint.setValue(constraintValueAsMap); return uiConstraint; } - if (ToscaFunctions.GET_INPUT.getFunctionName().equals(firstKey)) { - uiConstraint.setSourceType(SERVICE_INPUT_CONSTRAINT); - uiConstraint.setValue(entry.getValue()); - return uiConstraint; - } else if (ToscaFunctions.GET_PROPERTY.getFunctionName().equals(firstKey)) { - uiConstraint.setSourceType(PROPERTY_CONSTRAINT); - final List<String> value = (List<String>) entry.getValue(); - uiConstraint.setSourceName(value.get(0)); - uiConstraint.setValue(value.get(1)); - return uiConstraint; + uiConstraint.setValue(constraintValueAsMap); + uiConstraint.setSourceType(toscaFunctionType.getName()); + switch (toscaFunctionType) { + case GET_INPUT: + uiConstraint.setSourceName(PropertySource.SELF.getName()); + break; + case GET_PROPERTY: + case GET_ATTRIBUTE: + final List<String> value = (List<String>) entry.getValue(); + uiConstraint.setSourceName(value.get(0)); + break; + default: + break; } - return null; + + return uiConstraint; } public List<String> convertToList(List<UIConstraint> uiConstraints) { @@ -135,29 +136,39 @@ public class ConstraintConvertor { return retVal; } - public String convert(UIConstraint uiConstraint) { + public String convert(final UIConstraint uiConstraint) { try { - Map map1 = new HashMap(); - Map map2 = new HashMap(); - map1.put(uiConstraint.getServicePropertyName(), map2); - if (uiConstraint.getSourceType().equals(STATIC_CONSTRAINT)) { - Object value = uiConstraint.getValue(); - if (value instanceof String) { - value = new Yaml().load(value.toString()); + final Map<String, Object> constraintAsMap = new HashMap<>(); + switch (uiConstraint.getSourceType()) { + case STATIC_CONSTRAINT: { + Object value = uiConstraint.getValue(); + if (value instanceof String) { + value = new Yaml().load(value.toString()); + } + constraintAsMap.put(uiConstraint.getConstraintOperator(), value); + break; + } + case PROPERTY_CONSTRAINT: + constraintAsMap.put(uiConstraint.getConstraintOperator(), + Map.of(ToscaFunctions.GET_PROPERTY.getFunctionName(), List.of(uiConstraint.getSourceName(), uiConstraint.getValue())) + ); + break; + case SERVICE_INPUT_CONSTRAINT: + constraintAsMap.put(uiConstraint.getConstraintOperator(), Map.of(ToscaFunctions.GET_INPUT.getFunctionName(), uiConstraint.getValue())); + break; + default: { + if (ToscaFunctionType.findType(uiConstraint.getSourceType()).isPresent()) { + Object value = uiConstraint.getValue(); + if (value instanceof String) { + value = new Yaml().load((String) value); + } + constraintAsMap.put(uiConstraint.getConstraintOperator(), value); + } } - map2.put(uiConstraint.getConstraintOperator(), value); - } else if (uiConstraint.getSourceType().equals(PROPERTY_CONSTRAINT)) { - List list1 = Arrays.asList(uiConstraint.getSourceName(), uiConstraint.getValue()); - Map map3 = ImmutableMap.of(ToscaFunctions.GET_PROPERTY.getFunctionName(), list1); - map2.put(uiConstraint.getConstraintOperator(), map3); - } else if (uiConstraint.getSourceType().equals(SERVICE_INPUT_CONSTRAINT)) { - Map map3 = ImmutableMap.of(ToscaFunctions.GET_INPUT.getFunctionName(), uiConstraint.getValue()); - map2.put(uiConstraint.getConstraintOperator(), map3); } - Yaml yamlSource = new Yaml(); - return yamlSource.dump(map1); - } catch (NullPointerException ex) { - logger.error(ex.getMessage(), ex); + return new Yaml().dump(Map.of(uiConstraint.getServicePropertyName(), constraintAsMap)); + } catch (final Exception ex) { + logger.error("Could not convert constraint", ex); } return null; } @@ -187,13 +198,12 @@ public class ConstraintConvertor { uiConstraint.setSourceName(STATIC_CONSTRAINT); return uiConstraint; } else if (constraintValue instanceof List) { - final List constraintValueList = (List) constraintValue; uiConstraint.setSourceType(STATIC_CONSTRAINT); uiConstraint.setSourceName(STATIC_CONSTRAINT); - uiConstraint.setValue(constraintValueList); + uiConstraint.setValue(constraintValue); return uiConstraint; } else if (constraintValue instanceof Map) { - return handleMap(uiConstraint, constraintValue); + return handleMap(uiConstraint, (Map<Object, Object>) constraintValue); } return null; } diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/impl/ComponentsUtils.java b/catalog-be/src/main/java/org/openecomp/sdc/be/impl/ComponentsUtils.java index 7d58687bfd..313a303b61 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/impl/ComponentsUtils.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/impl/ComponentsUtils.java @@ -80,9 +80,7 @@ import org.openecomp.sdc.be.dao.api.ActionStatus; import org.openecomp.sdc.be.dao.cassandra.CassandraOperationStatus; import org.openecomp.sdc.be.dao.graph.datatype.AdditionalInformationEnum; import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus; -import org.openecomp.sdc.be.datamodel.utils.ConstraintConvertor; import org.openecomp.sdc.be.datatypes.elements.AdditionalInfoParameterInfo; -import org.openecomp.sdc.be.datatypes.elements.RequirementNodeFilterPropertyDataDefinition; import org.openecomp.sdc.be.datatypes.elements.ToscaFunction; import org.openecomp.sdc.be.datatypes.elements.ToscaFunctionJsonDeserializer; import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum; @@ -138,7 +136,7 @@ public class ComponentsUtils { private static final String CONVERT_JSON_TO_OBJECT = "convertJsonToObject"; private static final Logger log = Logger.getLogger(ComponentsUtils.class); private static final String PARTNER_NAME = "UNKNOWN"; - private static LoggerSdcAudit audit = new LoggerSdcAudit(DmaapConsumer.class); + private static final LoggerSdcAudit audit = new LoggerSdcAudit(DmaapConsumer.class); private final AuditingManager auditingManager; private final ResponseFormatManager responseFormatManager; @@ -174,27 +172,7 @@ public class ComponentsUtils { return false; } return componentInstance.getNodeFilter().getProperties().getListToscaDataDefinition().stream() - .anyMatch(property -> isPropertyConstraintChangedByCi(property, componentInstanceName)); - } - - private static boolean isPropertyConstraintChangedByCi( - final RequirementNodeFilterPropertyDataDefinition requirementNodeFilterPropertyDataDefinition, final String componentInstanceName) { - final List<String> constraints = requirementNodeFilterPropertyDataDefinition.getConstraints(); - if (constraints == null) { - return false; - } - return constraints.stream().anyMatch(constraint -> isConstraintChangedByCi(constraint, componentInstanceName)); - } - - private static boolean isConstraintChangedByCi(final String constraint, final String componentInstanceName) { - final UIConstraint uiConstraint = new ConstraintConvertor().convert(constraint); - if (uiConstraint == null || uiConstraint.getSourceType() == null) { - return false; - } - if (!uiConstraint.getSourceType().equals(ConstraintConvertor.PROPERTY_CONSTRAINT)) { - return false; - } - return uiConstraint.getSourceName().equals(componentInstanceName); + .anyMatch(property -> ServiceFilterUtils.isPropertyConstraintChangedByCi(property, componentInstanceName)); } public AuditingManager getAuditingManager() { @@ -1554,7 +1532,7 @@ public class ComponentsUtils { log.error(EcompLoggerErrorCode.DATA_ERROR, FAILED_TO_PARSE_CONSTRAINT_DATA, constraintData); return Collections.emptyList(); } - return uiConstraintsMaps.stream().map(dataMap -> new com.fasterxml.jackson.databind.ObjectMapper().convertValue(dataMap, UIConstraint.class)) + return uiConstraintsMaps.stream().map(dataMap -> new ObjectMapper().convertValue(dataMap, UIConstraint.class)) .collect(Collectors.toList()); } diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/impl/ServiceFilterUtils.java b/catalog-be/src/main/java/org/openecomp/sdc/be/impl/ServiceFilterUtils.java index 866affc509..c3fdaa6bed 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/impl/ServiceFilterUtils.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/impl/ServiceFilterUtils.java @@ -24,11 +24,18 @@ import org.apache.commons.collections.CollectionUtils; import org.javatuples.Pair; import org.openecomp.sdc.be.datamodel.utils.ConstraintConvertor; import org.openecomp.sdc.be.datatypes.elements.CINodeFilterDataDefinition; -import org.openecomp.sdc.be.datatypes.elements.RequirementNodeFilterPropertyDataDefinition; +import org.openecomp.sdc.be.datatypes.elements.PropertyFilterConstraintDataDefinition; +import org.openecomp.sdc.be.datatypes.elements.PropertyFilterDataDefinition; +import org.openecomp.sdc.be.datatypes.elements.ToscaConcatFunction; +import org.openecomp.sdc.be.datatypes.elements.ToscaFunction; +import org.openecomp.sdc.be.datatypes.elements.ToscaFunctionParameter; +import org.openecomp.sdc.be.datatypes.elements.ToscaFunctionType; +import org.openecomp.sdc.be.datatypes.elements.ToscaGetFunctionDataDefinition; +import org.openecomp.sdc.be.datatypes.enums.FilterValueType; import org.openecomp.sdc.be.model.ComponentInstance; import org.openecomp.sdc.be.model.InputDefinition; import org.openecomp.sdc.be.model.Service; -import org.openecomp.sdc.be.ui.model.UIConstraint; +import org.openecomp.sdc.be.ui.mapper.FilterConstraintMapper; public class ServiceFilterUtils { @@ -48,12 +55,19 @@ public class ServiceFilterUtils { || ci.getNodeFilter().getProperties().getListToscaDataDefinition() == null) { return false; } - return ci.getNodeFilter().getProperties().getListToscaDataDefinition().stream().flatMap(prop -> prop.getConstraints().stream()) - .map(String::new) - .filter(constraint -> new ConstraintConvertor().convert(constraint).getSourceType().equals(ConstraintConvertor.PROPERTY_CONSTRAINT)) - .anyMatch(constraintStr -> { - UIConstraint uiConstraint = new ConstraintConvertor().convert(constraintStr); - return uiConstraint.getSourceName().equals(ciName) && uiConstraint.getValue().equals(propertyName); + return ci.getNodeFilter().getProperties().getListToscaDataDefinition().stream() + .flatMap(prop -> prop.getConstraints().stream()) + .filter(constraint -> + List.of(ConstraintConvertor.PROPERTY_CONSTRAINT, ToscaFunctionType.GET_PROPERTY.getName()) + .contains(constraint.getValueType().getName()) + ) + .map(new FilterConstraintMapper()::mapFrom) + .anyMatch(constraint -> { + final ToscaGetFunctionDataDefinition toscaGetFunction = constraint.getAsToscaGetFunction().orElse(null); + if (toscaGetFunction == null) { + return false; + } + return toscaGetFunction.getSourceName().equals(ciName) && toscaGetFunction.getPropertyPathFromSource().contains(propertyName); }); } @@ -69,22 +83,59 @@ public class ServiceFilterUtils { return new Pair<>(ci.getUniqueId(), ci.getNodeFilter()); } - private static void renamePropertyCiNames(RequirementNodeFilterPropertyDataDefinition property, String oldName, String newName) { - final List<String> constraints = property.getConstraints().stream().map(getConstraintString(oldName, newName)).collect(Collectors.toList()); - property.setConstraints(constraints); + private static void renamePropertyCiNames(final PropertyFilterDataDefinition propertyFilter, final String oldInstanceName, + final String newInstanceName) { + final List<FilterValueType> instanceValueTypes = + List.of(FilterValueType.GET_PROPERTY, FilterValueType.GET_ATTRIBUTE, FilterValueType.CONCAT); + final List<PropertyFilterConstraintDataDefinition> constraints = propertyFilter.getConstraints().stream() + .filter(propertyFilter1 -> instanceValueTypes.contains(propertyFilter1.getValueType())) + .map(replaceConstraintsInstanceSource(oldInstanceName, newInstanceName)) + .collect(Collectors.toList()); + propertyFilter.setConstraints(constraints); } - private static Function<String, String> getConstraintString(String oldName, String newName) { + private static Function<PropertyFilterConstraintDataDefinition, PropertyFilterConstraintDataDefinition> replaceConstraintsInstanceSource( + final String oldInstanceName, final String newInstanceName) { + return constraint -> { - final ConstraintConvertor constraintConvertor = new ConstraintConvertor(); - UIConstraint uiConstraint = constraintConvertor.convert(constraint); - if (uiConstraint.getSourceName().equals(oldName)) { - uiConstraint.setSourceName(newName); + final ToscaFunction toscaFunction = new FilterConstraintMapper().parseValueToToscaFunction(constraint.getValue()).orElse(null); + if (toscaFunction == null) { + return constraint; } - return constraintConvertor.convert(uiConstraint); + renameToscaFunctionComponentInstance(toscaFunction, oldInstanceName, newInstanceName); + return constraint; }; } + private static void renameToscaFunctionComponentInstance(final ToscaFunction toscaFunction, final String oldInstanceName, + final String newInstanceName) { + switch (toscaFunction.getType()) { + case GET_PROPERTY: + case GET_ATTRIBUTE: { + final ToscaGetFunctionDataDefinition toscaGetFunctionDataDefinition = (ToscaGetFunctionDataDefinition) toscaFunction; + if (toscaGetFunctionDataDefinition.getSourceName().equals(oldInstanceName)) { + toscaGetFunctionDataDefinition.setSourceName(newInstanceName); + } + break; + } + case CONCAT: { + final ToscaConcatFunction toscaConcatFunction = (ToscaConcatFunction) toscaFunction; + for (final ToscaFunctionParameter parameter : toscaConcatFunction.getParameters()) { + switch (parameter.getType()) { + case GET_PROPERTY: + case GET_ATTRIBUTE: + case CONCAT: + renameToscaFunctionComponentInstance((ToscaFunction) parameter, oldInstanceName, newInstanceName); + break; + default: + } + } + break; + } + default: + } + } + public static Set<String> getNodesFiltersToBeDeleted(Service service, String ciName) { return service.getComponentInstances().stream().filter(ci -> isNodeFilterUsingChangedCi(ci, ciName)).map(ComponentInstance::getName) .collect(Collectors.toSet()); @@ -106,24 +157,24 @@ public class ServiceFilterUtils { .anyMatch(property -> isPropertyConstraintChangedByCi(property, name)); } - private static boolean isPropertyConstraintChangedByCi(RequirementNodeFilterPropertyDataDefinition requirementNodeFilterPropertyDataDefinition, + public static boolean isPropertyConstraintChangedByCi(PropertyFilterDataDefinition propertyFilterDataDefinition, String name) { - List<String> constraints = requirementNodeFilterPropertyDataDefinition.getConstraints(); - if (constraints == null) { + List<PropertyFilterConstraintDataDefinition> constraints = propertyFilterDataDefinition.getConstraints(); + if (CollectionUtils.isEmpty(constraints)) { return false; } return constraints.stream().anyMatch(constraint -> isConstraintChangedByCi(constraint, name)); } - private static boolean isConstraintChangedByCi(String constraint, String name) { - UIConstraint uiConstraint = new ConstraintConvertor().convert(constraint); - if (uiConstraint == null || uiConstraint.getSourceType() == null) { - return false; - } - if (!uiConstraint.getSourceType().equals(ConstraintConvertor.PROPERTY_CONSTRAINT)) { - return false; + private static boolean isConstraintChangedByCi(final PropertyFilterConstraintDataDefinition constraint, final String name) { + if (constraint.getValueType() == FilterValueType.GET_PROPERTY || constraint.getValueType() == FilterValueType.GET_ATTRIBUTE) { + final ToscaFunction toscaFunction = new FilterConstraintMapper().parseValueToToscaFunction(constraint.getValue()).orElse(null); + if (toscaFunction != null) { + final ToscaGetFunctionDataDefinition toscaGetFunction = (ToscaGetFunctionDataDefinition) toscaFunction; + return toscaGetFunction.getSourceName().equals(name); + } } - return uiConstraint.getSourceName().equals(name); + return false; } public static Set<String> getNodesFiltersToBeDeleted(Service service, InputDefinition changedInput) { @@ -139,17 +190,20 @@ public class ServiceFilterUtils { .anyMatch(property -> isPropertyConstraintChangedByInput(property, changedInput)); } - private static boolean isPropertyConstraintChangedByInput(RequirementNodeFilterPropertyDataDefinition requirementNodeFilterPropertyDataDefinition, - InputDefinition changedInput) { - List<String> constraints = requirementNodeFilterPropertyDataDefinition.getConstraints(); + private static boolean isPropertyConstraintChangedByInput(final PropertyFilterDataDefinition propertyFilterDataDefinition, + final InputDefinition changedInput) { + final List<PropertyFilterConstraintDataDefinition> constraints = propertyFilterDataDefinition.getConstraints(); return constraints.stream().anyMatch(constraint -> isConstraintChangedByInput(constraint, changedInput)); } - private static boolean isConstraintChangedByInput(String constraint, InputDefinition changedInput) { - UIConstraint uiConstraint = new ConstraintConvertor().convert(constraint); - if (!uiConstraint.getSourceType().equals(ConstraintConvertor.SERVICE_INPUT_CONSTRAINT)) { - return false; + private static boolean isConstraintChangedByInput(final PropertyFilterConstraintDataDefinition constraint, final InputDefinition changedInput) { + if (constraint.getValueType() == FilterValueType.GET_INPUT) { + final ToscaFunction toscaFunction = new FilterConstraintMapper().parseValueToToscaFunction(constraint.getValue()).orElse(null); + if (toscaFunction != null) { + final ToscaGetFunctionDataDefinition toscaGetFunction = (ToscaGetFunctionDataDefinition) toscaFunction; + return toscaGetFunction.getPropertyPathFromSource().contains(changedInput.getName()); + } } - return uiConstraint.getValue().equals(changedInput.getName()); + return false; } } diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ComponentNodeFilterServlet.java b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ComponentNodeFilterServlet.java index c66bb8a8ec..87de704750 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ComponentNodeFilterServlet.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ComponentNodeFilterServlet.java @@ -25,7 +25,6 @@ import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.tags.Tag; -import io.swagger.v3.oas.annotations.tags.Tags; import java.util.Optional; import javax.inject.Inject; import javax.inject.Singleton; @@ -47,17 +46,19 @@ import org.openecomp.sdc.be.components.impl.ComponentNodeFilterBusinessLogic; import org.openecomp.sdc.be.components.impl.ResourceImportManager; import org.openecomp.sdc.be.components.impl.aaf.AafPermission; import org.openecomp.sdc.be.components.impl.aaf.PermissionAllowed; -import org.openecomp.sdc.be.components.impl.utils.NodeFilterConstraintAction; +import org.openecomp.sdc.be.components.impl.exceptions.BusinessLogicException; +import org.openecomp.sdc.be.components.impl.exceptions.ComponentException; import org.openecomp.sdc.be.config.BeEcompErrorManager; import org.openecomp.sdc.be.dao.api.ActionStatus; -import org.openecomp.sdc.be.datamodel.utils.ConstraintConvertor; import org.openecomp.sdc.be.datatypes.elements.CINodeFilterDataDefinition; import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum; import org.openecomp.sdc.be.datatypes.enums.NodeFilterConstraintType; import org.openecomp.sdc.be.impl.ComponentsUtils; import org.openecomp.sdc.be.impl.ServletUtils; import org.openecomp.sdc.be.model.User; +import org.openecomp.sdc.be.model.dto.FilterConstraintDto; import org.openecomp.sdc.be.tosca.utils.NodeFilterConverter; +import org.openecomp.sdc.be.ui.mapper.FilterConstraintMapper; import org.openecomp.sdc.be.ui.model.UIConstraint; import org.openecomp.sdc.be.user.UserBusinessLogic; import org.openecomp.sdc.common.api.Constants; @@ -65,7 +66,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; @Path("/v1/catalog") -@Tags({@Tag(name = "SDCE-2 APIs")}) +@Tag(name = "SDCE-2 APIs") @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) @Singleton @@ -122,21 +123,20 @@ public class ComponentNodeFilterServlet extends AbstractValidationsServlet { final User userModifier = componentNodeFilterBusinessLogic.validateUser(userId); final ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(componentType); try { - final Optional<UIConstraint> convertResponse = componentsUtils.parseToConstraint(constraintData, userModifier, componentTypeEnum); - if (convertResponse.isEmpty()) { - LOGGER.error(FAILED_TO_PARSE_COMPONENT); - return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR)); - } final Optional<NodeFilterConstraintType> nodeFilterConstraintType = NodeFilterConstraintType.parse(constraintType); if (nodeFilterConstraintType.isEmpty()) { return buildErrorResponse( getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT_PARAM, INVALID_NODE_FILTER_CONSTRAINT_TYPE, constraintType)); } - final UIConstraint uiConstraint = convertResponse.get(); - final String constraint = new ConstraintConvertor().convert(uiConstraint); + final UIConstraint uiConstraint = componentsUtils.parseToConstraint(constraintData, userModifier, componentTypeEnum).orElse(null); + if (uiConstraint == null) { + LOGGER.error(FAILED_TO_PARSE_COMPONENT); + return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR)); + } + final FilterConstraintDto filterConstraintDto = new FilterConstraintMapper().mapFrom(uiConstraint); final Optional<CINodeFilterDataDefinition> actionResponse = componentNodeFilterBusinessLogic - .addNodeFilter(componentId.toLowerCase(), componentInstanceId, NodeFilterConstraintAction.ADD, uiConstraint.getServicePropertyName(), - constraint, true, componentTypeEnum, nodeFilterConstraintType.get(), + .addNodeFilter(componentId.toLowerCase(), componentInstanceId, + filterConstraintDto, true, componentTypeEnum, nodeFilterConstraintType.get(), StringUtils.isEmpty(uiConstraint.getCapabilityName()) ? "" : uiConstraint.getCapabilityName()); if (actionResponse.isEmpty()) { LOGGER.error(FAILED_TO_CREATE_NODE_FILTER); @@ -144,6 +144,10 @@ public class ComponentNodeFilterServlet extends AbstractValidationsServlet { } return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), new NodeFilterConverter().convertToUi(actionResponse.get())); + } catch (final ComponentException e) { + throw e; + } catch (final BusinessLogicException e) { + return buildErrorResponse(e.getResponseFormat()); } catch (final Exception e) { BeEcompErrorManager.getInstance().logBeRestApiGeneralError(NODE_FILTER_CREATION); LOGGER.error(CREATE_NODE_FILTER_WITH_AN_ERROR, e); @@ -236,7 +240,7 @@ public class ComponentNodeFilterServlet extends AbstractValidationsServlet { getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT_PARAM, INVALID_NODE_FILTER_CONSTRAINT_TYPE, constraintType)); } final Optional<CINodeFilterDataDefinition> actionResponse = componentNodeFilterBusinessLogic - .deleteNodeFilter(componentId.toLowerCase(), componentInstanceId, NodeFilterConstraintAction.DELETE, null, index, true, + .deleteNodeFilter(componentId.toLowerCase(), componentInstanceId, index, true, ComponentTypeEnum.findByParamName(componentType), nodeFilterConstraintType.get()); if (actionResponse.isEmpty()) { LOGGER.debug(FAILED_TO_DELETE_NODE_FILTER); diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ComponentSubstitutionFilterServlet.java b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ComponentSubstitutionFilterServlet.java index 067e68bcb8..596237065f 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ComponentSubstitutionFilterServlet.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ComponentSubstitutionFilterServlet.java @@ -25,9 +25,9 @@ import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.tags.Tag; -import io.swagger.v3.oas.annotations.tags.Tags; import java.util.List; import java.util.Optional; +import java.util.stream.Collectors; import javax.inject.Inject; import javax.inject.Singleton; import javax.servlet.http.HttpServletRequest; @@ -48,16 +48,18 @@ import org.openecomp.sdc.be.components.impl.ComponentSubstitutionFilterBusinessL import org.openecomp.sdc.be.components.impl.ResourceImportManager; import org.openecomp.sdc.be.components.impl.aaf.AafPermission; import org.openecomp.sdc.be.components.impl.aaf.PermissionAllowed; +import org.openecomp.sdc.be.components.impl.exceptions.BusinessLogicException; import org.openecomp.sdc.be.config.BeEcompErrorManager; import org.openecomp.sdc.be.dao.api.ActionStatus; -import org.openecomp.sdc.be.datamodel.utils.ConstraintConvertor; import org.openecomp.sdc.be.datatypes.elements.SubstitutionFilterDataDefinition; import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum; import org.openecomp.sdc.be.datatypes.enums.NodeFilterConstraintType; import org.openecomp.sdc.be.impl.ComponentsUtils; import org.openecomp.sdc.be.impl.ServletUtils; import org.openecomp.sdc.be.model.User; +import org.openecomp.sdc.be.model.dto.FilterConstraintDto; import org.openecomp.sdc.be.tosca.utils.SubstitutionFilterConverter; +import org.openecomp.sdc.be.ui.mapper.FilterConstraintMapper; import org.openecomp.sdc.be.ui.model.UIConstraint; import org.openecomp.sdc.be.ui.model.UINodeFilter; import org.openecomp.sdc.be.user.UserBusinessLogic; @@ -66,7 +68,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; @Path("/v1/catalog/{componentType}/{componentId}/substitutionFilter/{constraintType}") -@Tags({@Tag(name = "SDCE-2 APIs")}) +@Tag(name = "SDCE-2 APIs") @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) @Singleton @@ -79,13 +81,17 @@ public class ComponentSubstitutionFilterServlet extends AbstractValidationsServl private static final String INVALID_CONSTRAINTYPE_ENUM = "Invalid value for NodeFilterConstraintType enum %s"; private static final String FAILED_TO_ADD_SUBSTITUTION_FILTER = "Failed to add substitution filter"; private static final String ADD_SUBSTITUTION_FILTER = "Add Substitution Filter"; - private static final String ADD_SUBSTITUTION_FILTER_WITH_AN_ERROR = "Add substitution filter with an error"; + private static final String ADD_SUBSTITUTION_FILTER_WITH_AN_ERROR = "An unexpected error has occurred while adding a substitution filter"; private static final String FAILED_TO_UPDATE_SUBSTITUTION_FILTER = "Failed to update substitution filter"; private static final String SUBSTITUTION_FILTER_UPDATE = "Substitution Filter Update"; private static final String UPDATE_SUBSTITUTION_FILTER_WITH_AN_ERROR = "Update substitution filter with an error {}"; private static final String FAILED_TO_DELETE_SUBSTITUTION_FILTER = "Failed to delete substitution filter"; private static final String SUBSTITUTION_FILTER_DELETE = "Substitution Filter Delete"; private static final String DELETE_SUBSTITUTION_FILTER_WITH_AN_ERROR = "Delete substitution filter with an error"; + private static final List<ComponentTypeEnum> EXPECTED_COMPONENT_TYPES = List.of(ComponentTypeEnum.SERVICE, ComponentTypeEnum.RESOURCE); + private static final String EXPECTED_COMPONENT_TYPES_AS_STRING = EXPECTED_COMPONENT_TYPES.stream() + .map(ComponentTypeEnum::findParamByType) + .collect(Collectors.joining(", ")); private final ComponentSubstitutionFilterBusinessLogic componentSubstitutionFilterBusinessLogic; @Inject @@ -125,21 +131,22 @@ public class ComponentSubstitutionFilterServlet extends AbstractValidationsServl LOGGER.error(FAILED_TO_PARSE_COMPONENT); return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR)); } - final UIConstraint uiConstraint = convertResponse.get(); - final String constraint = new ConstraintConvertor().convert(uiConstraint); + final FilterConstraintDto filterConstraintDto = new FilterConstraintMapper().mapFrom(convertResponse.get()); final Optional<NodeFilterConstraintType> nodeFilterConstraintType = NodeFilterConstraintType.parse(constraintType); if (nodeFilterConstraintType.isEmpty()) { return buildErrorResponse( getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT_PARAM, INVALID_CONSTRAINTYPE_ENUM, constraintType)); } final Optional<SubstitutionFilterDataDefinition> actionResponse = componentSubstitutionFilterBusinessLogic - .addSubstitutionFilter(componentId.toLowerCase(), uiConstraint.getServicePropertyName(), constraint, true, componentTypeEnum); + .addSubstitutionFilter(componentId.toLowerCase(), filterConstraintDto, true, componentTypeEnum); if (actionResponse.isEmpty()) { LOGGER.error(FAILED_TO_ADD_SUBSTITUTION_FILTER); return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR)); } final UINodeFilter uiFilter = new SubstitutionFilterConverter().convertToUi(actionResponse.get()); return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), uiFilter); + } catch (final BusinessLogicException e) { + return buildErrorResponse(e.getResponseFormat()); } catch (final Exception e) { BeEcompErrorManager.getInstance().logBeRestApiGeneralError(ADD_SUBSTITUTION_FILTER); LOGGER.error(ADD_SUBSTITUTION_FILTER_WITH_AN_ERROR, e); @@ -156,11 +163,67 @@ public class ComponentSubstitutionFilterServlet extends AbstractValidationsServl @ApiResponse(responseCode = "403", description = "Restricted operation"), @ApiResponse(responseCode = "400", description = "Invalid content / Missing content")}) @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE) - public Response updateSubstitutionFilter(@Parameter(description = "UIConstraint data", required = true) String constraintData, + public Response updateSubstitutionFilters(@Parameter(description = "UIConstraint data", required = true) String constraintData, + @Parameter(description = "Component Id") @PathParam("componentId") String componentId, + @Parameter(description = "valid value: resources / services", schema = @Schema(allowableValues = { + ComponentTypeEnum.SERVICE_PARAM_NAME, + ComponentTypeEnum.SERVICE_PARAM_NAME})) @PathParam("componentType") final String componentType, + @Parameter(description = "Constraint type. Valid values: properties / capabilities", schema = @Schema(allowableValues = { + NodeFilterConstraintType.PROPERTIES_PARAM_NAME, + NodeFilterConstraintType.CAPABILITIES_PARAM_NAME})) @PathParam("constraintType") final String constraintType, + @Context final HttpServletRequest request, + @HeaderParam(value = Constants.USER_ID_HEADER) String userId) { + LOGGER.debug(START_HANDLE_REQUEST_OF, request.getMethod(), request.getRequestURI()); + LOGGER.debug(MODIFIER_ID_IS, userId); + final User userModifier = componentSubstitutionFilterBusinessLogic.validateUser(userId); + try { + final ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(componentType); + final List<UIConstraint> uiConstraints = componentsUtils.validateAndParseConstraint(componentTypeEnum, constraintData, userModifier); + if (CollectionUtils.isEmpty(uiConstraints)) { + LOGGER.error("Failed to Parse Constraint data {} when executing {} ", constraintData, SUBSTITUTION_FILTER_UPDATE); + return buildErrorResponse(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR, "Failed to parse constraint data")); + } + final List<FilterConstraintDto> filterConstraintList = uiConstraints.stream() + .map(uiConstraint -> new FilterConstraintMapper().mapFrom(uiConstraint)) + .collect(Collectors.toList()); + final Optional<NodeFilterConstraintType> nodeFilterConstraintType = NodeFilterConstraintType.parse(constraintType); + if (nodeFilterConstraintType.isEmpty()) { + return buildErrorResponse( + getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT_PARAM, INVALID_CONSTRAINTYPE_ENUM, constraintType)); + } + final Optional<SubstitutionFilterDataDefinition> actionResponse = componentSubstitutionFilterBusinessLogic + .updateSubstitutionFilter(componentId.toLowerCase(), filterConstraintList, true, componentTypeEnum); + if (actionResponse.isEmpty()) { + LOGGER.error(FAILED_TO_UPDATE_SUBSTITUTION_FILTER); + return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR)); + } + return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), + new SubstitutionFilterConverter().convertToUi(actionResponse.get())); + } catch (final BusinessLogicException e) { + return buildErrorResponse(e.getResponseFormat()); + } catch (final Exception e) { + BeEcompErrorManager.getInstance().logBeRestApiGeneralError(SUBSTITUTION_FILTER_UPDATE); + LOGGER.error(UPDATE_SUBSTITUTION_FILTER_WITH_AN_ERROR, e.getMessage(), e); + return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR)); + } + } + + @PUT + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @Path("/{constraintIndex}") + @Operation(description = "Update Component Substitution Filter Constraint", method = "PUT", summary = "Update Component Substitution Filter Constraint", responses = { + @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))), + @ApiResponse(responseCode = "201", description = "Update Substitution Filter Constraint"), + @ApiResponse(responseCode = "403", description = "Restricted operation"), + @ApiResponse(responseCode = "400", description = "Invalid content / Missing content")}) + @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE) + public Response updateSubstitutionFilter(@Parameter(description = "Filter constraint information", required = true) UIConstraint uiConstraint, + @Parameter(description = "Constraint Index") @PathParam("constraintIndex") int index, @Parameter(description = "Component Id") @PathParam("componentId") String componentId, - @Parameter(description = "valid value: resources / services", schema = @Schema(allowableValues = { + @Parameter(description = "The component type", schema = @Schema(allowableValues = { ComponentTypeEnum.SERVICE_PARAM_NAME, - ComponentTypeEnum.SERVICE_PARAM_NAME})) @PathParam("componentType") final String componentType, + ComponentTypeEnum.RESOURCE_PARAM_NAME})) @PathParam("componentType") final String componentType, @Parameter(description = "Constraint type. Valid values: properties / capabilities", schema = @Schema(allowableValues = { NodeFilterConstraintType.PROPERTIES_PARAM_NAME, NodeFilterConstraintType.CAPABILITIES_PARAM_NAME})) @PathParam("constraintType") final String constraintType, @@ -168,28 +231,32 @@ public class ComponentSubstitutionFilterServlet extends AbstractValidationsServl @HeaderParam(value = Constants.USER_ID_HEADER) String userId) { LOGGER.debug(START_HANDLE_REQUEST_OF, request.getMethod(), request.getRequestURI()); LOGGER.debug(MODIFIER_ID_IS, userId); - final User userModifier = componentSubstitutionFilterBusinessLogic.validateUser(userId); + componentSubstitutionFilterBusinessLogic.validateUser(userId); try { final ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(componentType); - final List<UIConstraint> uiConstraints = componentsUtils.validateAndParseConstraint(componentTypeEnum, constraintData, userModifier); - if (CollectionUtils.isEmpty(uiConstraints)) { - LOGGER.error("Failed to Parse Constraint data {} when executing {} ", constraintData, SUBSTITUTION_FILTER_UPDATE); - return buildErrorResponse(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR, "Failed to parse constraint data")); + if (componentTypeEnum == null || !EXPECTED_COMPONENT_TYPES.contains(componentTypeEnum)) { + return buildErrorResponse( + getComponentsUtils().getResponseFormat(ActionStatus.INVALID_COMPONENT_TYPE, componentType, EXPECTED_COMPONENT_TYPES_AS_STRING)); } - final List<String> constraints = new ConstraintConvertor().convertToList(uiConstraints); final Optional<NodeFilterConstraintType> nodeFilterConstraintType = NodeFilterConstraintType.parse(constraintType); - if (!nodeFilterConstraintType.isPresent()) { + if (nodeFilterConstraintType.isEmpty()) { return buildErrorResponse( getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT_PARAM, INVALID_CONSTRAINTYPE_ENUM, constraintType)); } + final FilterConstraintDto filterConstraintDto = new FilterConstraintMapper().mapFrom(uiConstraint); + final Optional<SubstitutionFilterDataDefinition> actionResponse = componentSubstitutionFilterBusinessLogic - .updateSubstitutionFilter(componentId.toLowerCase(), constraints, true, componentTypeEnum); - if (!actionResponse.isPresent()) { + .updateSubstitutionFilter(componentId.toLowerCase(), filterConstraintDto, index , true); + if (actionResponse.isEmpty()) { LOGGER.error(FAILED_TO_UPDATE_SUBSTITUTION_FILTER); return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR)); } return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), new SubstitutionFilterConverter().convertToUi(actionResponse.get())); + } catch (final BusinessLogicException e) { + BeEcompErrorManager.getInstance().logBeRestApiGeneralError(SUBSTITUTION_FILTER_UPDATE); + LOGGER.error(UPDATE_SUBSTITUTION_FILTER_WITH_AN_ERROR, e.getMessage(), e); + return buildErrorResponse(e.getResponseFormat()); } catch (final Exception e) { BeEcompErrorManager.getInstance().logBeRestApiGeneralError(SUBSTITUTION_FILTER_UPDATE); LOGGER.error(UPDATE_SUBSTITUTION_FILTER_WITH_AN_ERROR, e.getMessage(), e); 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 25d0287d54..f3327d7206 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 @@ -71,11 +71,13 @@ import org.openecomp.sdc.be.datatypes.elements.CINodeFilterDataDefinition; import org.openecomp.sdc.be.datatypes.elements.InterfaceDataDefinition; import org.openecomp.sdc.be.datatypes.elements.ListDataDefinition; import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition; +import org.openecomp.sdc.be.datatypes.elements.PropertyFilterConstraintDataDefinition; +import org.openecomp.sdc.be.datatypes.elements.PropertyFilterDataDefinition; import org.openecomp.sdc.be.datatypes.elements.RequirementNodeFilterCapabilityDataDefinition; -import org.openecomp.sdc.be.datatypes.elements.RequirementNodeFilterPropertyDataDefinition; -import org.openecomp.sdc.be.datatypes.elements.RequirementSubstitutionFilterPropertyDataDefinition; import org.openecomp.sdc.be.datatypes.elements.SubstitutionFilterDataDefinition; +import org.openecomp.sdc.be.datatypes.elements.SubstitutionFilterPropertyDataDefinition; import org.openecomp.sdc.be.datatypes.elements.ToscaArtifactDataDefinition; +import org.openecomp.sdc.be.datatypes.elements.ToscaFunction; import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum; import org.openecomp.sdc.be.datatypes.enums.JsonPresentationFields; import org.openecomp.sdc.be.datatypes.enums.OriginTypeEnum; @@ -1044,11 +1046,10 @@ public class ToscaExportHandler { private Object convertToToscaObject(String value) { try { ToscaMapValueConverter mapConverterInst = ToscaMapValueConverter.getInstance(); - JsonParser jsonParser = new JsonParser(); StringReader reader = new StringReader(value); JsonReader jsonReader = new JsonReader(reader); jsonReader.setLenient(true); - JsonElement jsonElement = jsonParser.parse(jsonReader); + JsonElement jsonElement = JsonParser.parseReader(jsonReader); if (jsonElement.isJsonObject()) { JsonObject jsonObj = jsonElement.getAsJsonObject(); if (jsonObj.entrySet().size() == 1 && jsonObj.has(ToscaFunctions.GET_INPUT.getFunctionName())) { @@ -1613,14 +1614,13 @@ public class ToscaExportHandler { } NodeFilter nodeFilter = new NodeFilter(); ListDataDefinition<RequirementNodeFilterCapabilityDataDefinition> origCapabilities = inNodeFilter.getCapabilities(); - ListDataDefinition<RequirementNodeFilterPropertyDataDefinition> origProperties = inNodeFilter.getProperties(); + ListDataDefinition<PropertyFilterDataDefinition> origProperties = inNodeFilter.getProperties(); List<Map<String, CapabilityFilter>> capabilitiesCopy = new ArrayList<>(); - List<Map<String, List<Object>>> propertiesCopy = new ArrayList<>(); copyNodeFilterCapabilitiesTemplate(origCapabilities, capabilitiesCopy); - copyNodeFilterProperties(origProperties, propertiesCopy); if (CollectionUtils.isNotEmpty(capabilitiesCopy)) { nodeFilter.setCapabilities(capabilitiesCopy); } + final List<Map<String, List<Object>>> propertiesCopy = copyNodeFilterProperties(origProperties); if (CollectionUtils.isNotEmpty(propertiesCopy)) { nodeFilter.setProperties(propertiesCopy); } @@ -1634,10 +1634,8 @@ public class ToscaExportHandler { return null; } NodeFilter nodeFilter = new NodeFilter(); - ListDataDefinition<RequirementSubstitutionFilterPropertyDataDefinition> origProperties = substitutionFilterDataDefinition.getProperties(); - List<Map<String, List<Object>>> propertiesCopy = new ArrayList<>(); - copySubstitutionFilterProperties(origProperties, propertiesCopy); - if (CollectionUtils.isNotEmpty(propertiesCopy)) { + final List<Map<String, List<Object>>> propertiesCopy = copySubstitutionPropertiesFilter(substitutionFilterDataDefinition.getProperties()); + if (!propertiesCopy.isEmpty()) { nodeFilter.setProperties(propertiesCopy); } nodeFilter.setTosca_id(cloneToscaId(substitutionFilterDataDefinition.getTosca_id())); @@ -1661,81 +1659,71 @@ public class ToscaExportHandler { } for (RequirementNodeFilterCapabilityDataDefinition capability : origCapabilities.getListToscaDataDefinition()) { Map<String, CapabilityFilter> capabilityFilterCopyMap = new HashMap<>(); - CapabilityFilter capabilityFilter = new CapabilityFilter(); - List<Map<String, List<Object>>> propertiesCopy = new ArrayList<>(); - copyNodeFilterProperties(capability.getProperties(), propertiesCopy); - capabilityFilter.setProperties(propertiesCopy); + final var capabilityFilter = new CapabilityFilter(); + capabilityFilter.setProperties(copyNodeFilterProperties(capability.getProperties())); capabilityFilterCopyMap.put(capability.getName(), capabilityFilter); capabilitiesCopy.add(capabilityFilterCopyMap); } } - private void copyNodeFilterProperties(ListDataDefinition<RequirementNodeFilterPropertyDataDefinition> origProperties, - List<Map<String, List<Object>>> propertiesCopy) { + private List<Map<String, List<Object>>> copyNodeFilterProperties(final ListDataDefinition<PropertyFilterDataDefinition> origProperties) { if (origProperties == null || origProperties.getListToscaDataDefinition() == null || origProperties.isEmpty()) { - return; + return Collections.emptyList(); } - Map<String, List<Object>> propertyMapCopy = new HashMap<>(); - for (RequirementNodeFilterPropertyDataDefinition propertyDataDefinition : origProperties.getListToscaDataDefinition()) { - for (String propertyInfoEntry : propertyDataDefinition.getConstraints()) { - Map<String, List<Object>> propertyValObj = new YamlUtil().yamlToObject(propertyInfoEntry, Map.class); - String propertyName = propertyDataDefinition.getName(); - if (propertyMapCopy.containsKey(propertyName)) { - addPropertyConstraintValueToList(propertyName, propertyValObj, propertyMapCopy.get(propertyName)); - } else { - if (propertyName != null) { - List<Object> propsList = new ArrayList<>(); - addPropertyConstraintValueToList(propertyName, propertyValObj, propsList); - propertyMapCopy.put(propertyName, propsList); - } else { - propertyMapCopy.putAll(propertyValObj); + List<Map<String, List<Object>>> propertiesCopy = new ArrayList<>(); + Map<String, List<Object>> propertyFilterDefinitionMap = new HashMap<>(); + for (final PropertyFilterDataDefinition propertyFilter : origProperties.getListToscaDataDefinition()) { + final String propertyName = propertyFilter.getName(); + for (final PropertyFilterConstraintDataDefinition filterConstraint : propertyFilter.getConstraints()) { + propertyFilterDefinitionMap.compute(propertyName, (propertyName1, constraints) -> { + if (constraints == null) { + constraints = new ArrayList<>(); } - } + constraints.add(buildNodeFilterValue(filterConstraint)); + return constraints; + }); } } - propertyMapCopy.entrySet().stream().forEach(entry -> addCalculatedConstraintsIntoPropertiesList(propertiesCopy, entry)); + propertyFilterDefinitionMap.entrySet().stream() + .map(entry -> Map.of(entry.getKey(), entry.getValue())) + .forEach(propertiesCopy::add); + return propertiesCopy; } - private void copySubstitutionFilterProperties(final ListDataDefinition<RequirementSubstitutionFilterPropertyDataDefinition> origProperties, - final List<Map<String, List<Object>>> propertiesCopy) { + private List<Map<String, List<Object>>> copySubstitutionPropertiesFilter( + final ListDataDefinition<SubstitutionFilterPropertyDataDefinition> origProperties) { + if (origProperties == null || origProperties.getListToscaDataDefinition() == null || origProperties.isEmpty()) { - return; + return Collections.emptyList(); } - final Map<String, List<Object>> propertyMapCopy = new HashMap<>(); - for (final RequirementSubstitutionFilterPropertyDataDefinition propertyDataDefinition : origProperties.getListToscaDataDefinition()) { - for (final String propertyInfoEntry : propertyDataDefinition.getConstraints()) { - final Map<String, List<Object>> propertyValObj = new YamlUtil().yamlToObject(propertyInfoEntry, Map.class); - final String propertyName = propertyDataDefinition.getName(); - if (propertyMapCopy.containsKey(propertyName)) { - addPropertyConstraintValueToList(propertyName, propertyValObj, propertyMapCopy.get(propertyName)); - } else { - if (propertyName != null) { - final List<Object> propsList = new ArrayList<>(); - addPropertyConstraintValueToList(propertyName, propertyValObj, propsList); - propertyMapCopy.put(propertyName, propsList); - } else { - propertyMapCopy.putAll(propertyValObj); + List<Map<String, List<Object>>> propertiesCopy = new ArrayList<>(); + Map<String, List<Object>> propertyFilterDefinitionMap = new HashMap<>(); + for (final SubstitutionFilterPropertyDataDefinition propertyFilter : origProperties.getListToscaDataDefinition()) { + final String propertyName = propertyFilter.getName(); + for (final PropertyFilterConstraintDataDefinition filterConstraint : propertyFilter.getConstraints()) { + propertyFilterDefinitionMap.compute(propertyName, (propertyName1, constraints) -> { + if (constraints == null) { + constraints = new ArrayList<>(); } - } + constraints.add(buildNodeFilterValue(filterConstraint)); + return constraints; + }); } } - propertyMapCopy.entrySet().forEach(entry -> addCalculatedConstraintsIntoPropertiesList(propertiesCopy, entry)); + propertyFilterDefinitionMap.entrySet().stream() + .map(entry -> Map.of(entry.getKey(), entry.getValue())) + .forEach(propertiesCopy::add); + return propertiesCopy; } - private void addPropertyConstraintValueToList(String propertyName, Map<String, List<Object>> propertyValObj, List<Object> propsList) { - if (propertyValObj.containsKey(propertyName)) { - propsList.add(propertyValObj.get(propertyName)); + private static Object buildNodeFilterValue(final PropertyFilterConstraintDataDefinition filterConstraint) { + if (filterConstraint.getValue() instanceof ToscaFunction) { + return Map.of(filterConstraint.getOperator().getType(), ((ToscaFunction) filterConstraint.getValue()).getJsonObjectValue()); } else { - propsList.add(propertyValObj); + return Map.of(filterConstraint.getOperator().getType(), filterConstraint.getValue()); } } - private void addCalculatedConstraintsIntoPropertiesList(List<Map<String, List<Object>>> propertiesCopy, Entry<String, List<Object>> entry) { - Map<String, List<Object>> tempMap = new HashMap<>(); - tempMap.put(entry.getKey(), entry.getValue()); - propertiesCopy.add(tempMap); - } - private Map<String, String[]> buildSubstitutionMappingPropertyMapping(final Component component) { if (component == null || CollectionUtils.isEmpty(component.getInputs())) { return Collections.emptyMap(); diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/ToscaPropertyConstraint.java b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/ToscaPropertyConstraint.java index ab1137342d..6049be2fd6 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/ToscaPropertyConstraint.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/ToscaPropertyConstraint.java @@ -18,7 +18,7 @@ */ package org.openecomp.sdc.be.tosca.model; -import org.openecomp.sdc.be.model.tosca.constraints.ConstraintType; +import org.openecomp.sdc.be.datatypes.enums.ConstraintType; /** * Represents a Tosca Property Constraint diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/ToscaPropertyConstraintValidValues.java b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/ToscaPropertyConstraintValidValues.java index e7bade9421..8e73f6985b 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/ToscaPropertyConstraintValidValues.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/ToscaPropertyConstraintValidValues.java @@ -22,7 +22,7 @@ import java.util.List; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.Setter; -import org.openecomp.sdc.be.model.tosca.constraints.ConstraintType; +import org.openecomp.sdc.be.datatypes.enums.ConstraintType; /** * Represents a tosca valid_values constraint diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/utils/NodeFilterConverter.java b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/utils/NodeFilterConverter.java index 48932fefd7..6ef6c0dc3c 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/utils/NodeFilterConverter.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/utils/NodeFilterConverter.java @@ -19,11 +19,12 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.stream.Collectors; -import org.openecomp.sdc.be.datamodel.utils.ConstraintConvertor; import org.openecomp.sdc.be.datatypes.elements.CINodeFilterDataDefinition; import org.openecomp.sdc.be.datatypes.elements.ListDataDefinition; +import org.openecomp.sdc.be.datatypes.elements.PropertyFilterDataDefinition; import org.openecomp.sdc.be.datatypes.elements.RequirementNodeFilterCapabilityDataDefinition; -import org.openecomp.sdc.be.datatypes.elements.RequirementNodeFilterPropertyDataDefinition; +import org.openecomp.sdc.be.model.dto.FilterConstraintDto; +import org.openecomp.sdc.be.ui.mapper.FilterConstraintMapper; import org.openecomp.sdc.be.ui.model.UIConstraint; import org.openecomp.sdc.be.ui.model.UINodeFilter; @@ -35,36 +36,38 @@ public class NodeFilterConverter { public UINodeFilter convertToUi(final CINodeFilterDataDefinition inNodeFilter) { final UINodeFilter uiNodeFilter = new UINodeFilter(); - final ConstraintConvertor constraintConvertor = new ConstraintConvertor(); - final ListDataDefinition<RequirementNodeFilterPropertyDataDefinition> nodeFilterProperties = inNodeFilter.getProperties(); + + final ListDataDefinition<PropertyFilterDataDefinition> nodeFilterProperties = inNodeFilter.getProperties(); if (nodeFilterProperties != null && !nodeFilterProperties.isEmpty()) { - final List<UIConstraint> propertiesConstraint = nodeFilterProperties.getListToscaDataDefinition().stream().map(property -> { - if(property.getType() != null) { - return constraintConvertor.convert(property.getConstraints().iterator().next(), property.getType()); - } else { - return constraintConvertor.convert(property.getConstraints().iterator().next()); - }}).collect(Collectors.toList()); + final var filterConstraintMapper = new FilterConstraintMapper(); + final List<UIConstraint> propertiesConstraint = nodeFilterProperties.getListToscaDataDefinition().stream() + .map(property -> property.getConstraints().iterator().next()) + .map(filterConstraintMapper::mapFrom) + .map(filterConstraintMapper::mapToUiConstraint) + .collect(Collectors.toList()); uiNodeFilter.setProperties(propertiesConstraint); } final ListDataDefinition<RequirementNodeFilterCapabilityDataDefinition> nodeFilterCapabilities = inNodeFilter.getCapabilities(); if (nodeFilterCapabilities != null && !nodeFilterCapabilities.isEmpty()) { final List<UIConstraint> capabilitiesConstraint = new ArrayList<>(); - nodeFilterCapabilities.getListToscaDataDefinition().forEach( - requirementNodeFilterCapabilityDataDefinition -> convertCapabilityConstraint(requirementNodeFilterCapabilityDataDefinition, - capabilitiesConstraint)); + nodeFilterCapabilities.getListToscaDataDefinition() + .forEach(requirementNodeFilterCapabilityDataDefinition -> + capabilitiesConstraint.addAll(convertCapabilityConstraint(requirementNodeFilterCapabilityDataDefinition)) + ); uiNodeFilter.setCapabilities(capabilitiesConstraint); } return uiNodeFilter; } - private void convertCapabilityConstraint(final RequirementNodeFilterCapabilityDataDefinition requirementNodeFilterCapabilityDataDefinition, - final List<UIConstraint> capabilitiesConstraint) { - final ConstraintConvertor constraintConvertor = new ConstraintConvertor(); - requirementNodeFilterCapabilityDataDefinition.getProperties().getListToscaDataDefinition().forEach(property -> { + private List<UIConstraint> convertCapabilityConstraint(final RequirementNodeFilterCapabilityDataDefinition nodeFilterCapability) { + final var filterConstraintMapper = new FilterConstraintMapper(); + final List<UIConstraint> uiConstraints = new ArrayList<>(); + nodeFilterCapability.getProperties().getListToscaDataDefinition().forEach(property -> { final UIConstraint uiConstraint = new UIConstraint(); - uiConstraint.setCapabilityName(requirementNodeFilterCapabilityDataDefinition.getName()); - capabilitiesConstraint.add( - constraintConvertor.getUiConstraint(property.getConstraints().iterator().next(), uiConstraint)); + uiConstraint.setCapabilityName(nodeFilterCapability.getName()); + final FilterConstraintDto filterConstraintDto = filterConstraintMapper.mapFrom(property.getConstraints().iterator().next()); + uiConstraints.add(filterConstraintMapper.mapToUiConstraint(filterConstraintDto)); }); + return uiConstraints; } } diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/utils/SubstitutionFilterConverter.java b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/utils/SubstitutionFilterConverter.java index c083099629..562e4ea8fd 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/utils/SubstitutionFilterConverter.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/utils/SubstitutionFilterConverter.java @@ -22,11 +22,11 @@ import java.util.Collections; import java.util.List; import java.util.stream.Collectors; import org.apache.commons.collections.CollectionUtils; -import org.openecomp.sdc.be.datamodel.utils.ConstraintConvertor; import org.openecomp.sdc.be.datatypes.elements.ListDataDefinition; import org.openecomp.sdc.be.datatypes.elements.RequirementSubstitutionFilterCapabilityDataDefinition; -import org.openecomp.sdc.be.datatypes.elements.RequirementSubstitutionFilterPropertyDataDefinition; import org.openecomp.sdc.be.datatypes.elements.SubstitutionFilterDataDefinition; +import org.openecomp.sdc.be.datatypes.elements.SubstitutionFilterPropertyDataDefinition; +import org.openecomp.sdc.be.ui.mapper.FilterConstraintMapper; import org.openecomp.sdc.be.ui.model.UIConstraint; import org.openecomp.sdc.be.ui.model.UINodeFilter; @@ -34,39 +34,45 @@ public class SubstitutionFilterConverter { public UINodeFilter convertToUi(final SubstitutionFilterDataDefinition inSubstitutionFilter) { final UINodeFilter uiNodeFilter = new UINodeFilter(); - final ConstraintConvertor constraintConvertor = new ConstraintConvertor(); - final List<UIConstraint> uiPropertyFilters = extractPropertyFilter(inSubstitutionFilter, constraintConvertor); + + final List<UIConstraint> uiPropertyFilters = extractPropertyFilter(inSubstitutionFilter); if (!uiPropertyFilters.isEmpty()) { uiNodeFilter.setProperties(uiPropertyFilters); } - final List<UIConstraint> uiCapabilityFilters = extractCapabilitiesFilter(inSubstitutionFilter, constraintConvertor); + final List<UIConstraint> uiCapabilityFilters = extractCapabilitiesFilter(inSubstitutionFilter); if (!uiCapabilityFilters.isEmpty()) { uiNodeFilter.setCapabilities(uiCapabilityFilters); } return uiNodeFilter; } - private List<UIConstraint> extractPropertyFilter(final SubstitutionFilterDataDefinition substitutionFilter, - final ConstraintConvertor constraintConvertor) { - final ListDataDefinition<RequirementSubstitutionFilterPropertyDataDefinition> substitutionFilterProperties = substitutionFilter + private List<UIConstraint> extractPropertyFilter(final SubstitutionFilterDataDefinition substitutionFilter) { + final ListDataDefinition<SubstitutionFilterPropertyDataDefinition> substitutionFilterProperties = substitutionFilter .getProperties(); if (substitutionFilterProperties != null && !substitutionFilterProperties.isEmpty() && CollectionUtils .isNotEmpty(substitutionFilterProperties.getListToscaDataDefinition())) { - return substitutionFilterProperties.getListToscaDataDefinition().stream().map(property -> property.getConstraints().iterator().next()) - .map(constraintConvertor::convert).collect(Collectors.toList()); + final var filterConstraintMapper = new FilterConstraintMapper(); + return substitutionFilterProperties.getListToscaDataDefinition().stream() + .map(property -> property.getConstraints().iterator().next()) + .map(filterConstraintMapper::mapFrom) + .map(filterConstraintMapper::mapToUiConstraint) + .collect(Collectors.toList()); } return Collections.emptyList(); } - private List<UIConstraint> extractCapabilitiesFilter(final SubstitutionFilterDataDefinition substitutionFilter, - final ConstraintConvertor constraintConvertor) { + private List<UIConstraint> extractCapabilitiesFilter(final SubstitutionFilterDataDefinition substitutionFilter) { final ListDataDefinition<RequirementSubstitutionFilterCapabilityDataDefinition> substitutionFilterCapabilities = substitutionFilter .getCapabilities(); if (substitutionFilterCapabilities != null && !substitutionFilterCapabilities.isEmpty() && CollectionUtils .isNotEmpty(substitutionFilterCapabilities.getListToscaDataDefinition())) { + final var filterConstraintMapper = new FilterConstraintMapper(); return substitutionFilterCapabilities.getListToscaDataDefinition().stream() .map(capabilities -> capabilities.getProperties().getListToscaDataDefinition().iterator().next()) - .map(property -> property.getConstraints().iterator().next()).map(constraintConvertor::convert).collect(Collectors.toList()); + .map(property -> property.getConstraints().iterator().next()) + .map(filterConstraintMapper::mapFrom) + .map(filterConstraintMapper::mapToUiConstraint) + .collect(Collectors.toList()); } return Collections.emptyList(); } |