diff options
29 files changed, 2503 insertions, 2 deletions
diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceBusinessLogic.java index 8d4f896d47..9bf442990b 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceBusinessLogic.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceBusinessLogic.java @@ -33,8 +33,10 @@ import org.openecomp.sdc.be.components.distribution.engine.INotificationData; import org.openecomp.sdc.be.components.distribution.engine.VfModuleArtifactPayload; import org.openecomp.sdc.be.components.health.HealthCheckBusinessLogic; import org.openecomp.sdc.be.components.impl.exceptions.ComponentException; +import org.openecomp.sdc.be.components.impl.utils.NodeFilterConstraintAction; import org.openecomp.sdc.be.components.lifecycle.LifecycleChangeInfoWithAction; import org.openecomp.sdc.be.components.path.ForwardingPathValidator; +import org.openecomp.sdc.be.components.validation.NodeFilterValidator; import org.openecomp.sdc.be.components.validation.ServiceDistributionValidation; import org.openecomp.sdc.be.config.BeEcompErrorManager; import org.openecomp.sdc.be.config.ConfigurationManager; @@ -43,7 +45,9 @@ import org.openecomp.sdc.be.dao.cassandra.AuditCassandraDao; import org.openecomp.sdc.be.dao.jsongraph.types.JsonParseFlagEnum; import org.openecomp.sdc.be.datamodel.ServiceRelations; import org.openecomp.sdc.be.datamodel.utils.UiComponentDataConverter; +import org.openecomp.sdc.be.datatypes.elements.CINodeFilterDataDefinition; import org.openecomp.sdc.be.datatypes.elements.ForwardingPathDataDefinition; +import org.openecomp.sdc.be.datatypes.elements.RequirementNodeFilterPropertyDataDefinition; import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum; import org.openecomp.sdc.be.datatypes.enums.InstantiationTypes; import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum; @@ -54,6 +58,7 @@ import org.openecomp.sdc.be.impl.WebAppContextWrapper; import org.openecomp.sdc.be.model.*; import org.openecomp.sdc.be.model.category.CategoryDefinition; import org.openecomp.sdc.be.model.jsontitan.operations.ForwardingPathOperation; +import org.openecomp.sdc.be.model.jsontitan.operations.NodeFilterOperation; import org.openecomp.sdc.be.model.jsontitan.operations.ToscaOperationFacade; import org.openecomp.sdc.be.model.operations.api.ICacheMangerOperation; import org.openecomp.sdc.be.model.operations.api.IElementOperation; @@ -120,6 +125,10 @@ public class ServiceBusinessLogic extends ComponentBusinessLogic { private ForwardingPathValidator forwardingPathValidator; @Autowired private UiComponentDataConverter uiComponentDataConverter; + @Autowired + private NodeFilterOperation serviceFilterOperation; + @Autowired + private NodeFilterValidator serviceFilterValidator; public Either<Service, ResponseFormat> changeServiceDistributionState(String serviceId, String state, LifecycleChangeInfoWithAction commentObj, User user) { @@ -2107,4 +2116,303 @@ public class ServiceBusinessLogic extends ComponentBusinessLogic { UiComponentDataTransfer dataTransfer = uiComponentDataConverter.getUiDataTransferFromServiceByParams(service, dataParamsToReturn); return Either.left(dataTransfer); } + + public Either<String, ResponseFormat> deleteIfNotAlreadyDeletedServiceFilter(String serviceId, String resourceId, String userId, boolean lock) { + Service serviceToDelete = initServiceToDeleteServiceFilter(serviceId); + User user = validateUserExists(userId, "Create service Filter", false); + + user = + validateUser(user, "deleteIfNotAlreadyDeletedServiceFilter", serviceToDelete, null, false); + + Either<Service, StorageOperationStatus> storageStatus = toscaOperationFacade.getToscaElement(serviceId); + if (storageStatus.isRight()) { + return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(storageStatus.right().value(), ComponentTypeEnum.SERVICE), "")); + } + Service service = storageStatus.left().value(); + + Either<Boolean, ResponseFormat> response = serviceFilterValidator.validateComponentInstanceExist(service, resourceId); + if (storageStatus.isRight()) { + return Either.right(response.right().value()); + } + final Optional<ComponentInstance> optionalComponentInstance = service.getComponentInstanceById(resourceId); + if (!optionalComponentInstance.isPresent() ){ + return Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR)); + } + CINodeFilterDataDefinition nodeFilter = optionalComponentInstance.get().getNodeFilter(); + if (nodeFilter == null){ + return Either.left(resourceId); + } + + Either<String, StorageOperationStatus> result; + if (lock) { + Either<Boolean, ResponseFormat> lockResult = lockComponent(service.getUniqueId(), service, "Delete Service Filter from service"); + if (lockResult.isRight()) { + titanDao.rollback(); + return Either.right(componentsUtils.getResponseFormat(componentsUtils + .convertFromStorageResponse(storageStatus.right().value(), ComponentTypeEnum.SERVICE), "")); + } + } + try{ + result = serviceFilterOperation.deleteNodeFilter(service , resourceId); + if (result.isRight()) { + log.debug("Failed to delete node filter in service {}. Response is {}. ", service.getName(), result.right().value()); + titanDao.rollback(); + return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(storageStatus.right().value(), ComponentTypeEnum.SERVICE))); + } + titanDao.commit(); + log.debug("Node filter successfully changed in service {} . ", service.getSystemName()); + + } catch (Exception e){ + log.error("Exception occurred during delete forwarding path : {}", e.getMessage(), e); + titanDao.rollback(); + return Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR)); + } finally { + graphLockOperation.unlockComponent(service.getUniqueId(), NodeTypeEnum.Service); + } + return Either.left(result.left().value()); + } + + + private Service initServiceToDeleteServiceFilter(String serviceId) { + Service serviceToDelete = new Service(); + serviceToDelete.setUniqueId(serviceId); + return serviceToDelete; + } + + + public Either<CINodeFilterDataDefinition, ResponseFormat> createIfNotAlreadyExistServiceFilter(String serviceId, String componentInstanceId, String userId, boolean lock) { + String errorContext = "createIfNotAlreadyExistServiceFilter"; + User user = validateUserExists(userId, "Create service Filter", false); + + Either<Service, StorageOperationStatus> serviceEither = toscaOperationFacade.getToscaElement(serviceId); + if (serviceEither.isRight()) { + return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(serviceEither.right().value(), ComponentTypeEnum.SERVICE), "")); + } + final Service service = serviceEither.left().value(); + validateUserAndRole(service, user, errorContext); + + Optional<ComponentInstance> optionalComponentInstance = service.getComponentInstanceById(componentInstanceId); + if (!optionalComponentInstance.isPresent()){ + return Either.right(ResponseFormatManager.getInstance().getResponseFormat(ActionStatus.NODE_FILTER_NOT_FOUND)); + } + ComponentInstance componentInstance = optionalComponentInstance.get(); + CINodeFilterDataDefinition serviceFilter = componentInstance.getNodeFilter(); + if (serviceFilter != null){ + return Either.left(serviceFilter); + } + + Either<CINodeFilterDataDefinition, StorageOperationStatus> result; + + Either<Boolean, ResponseFormat> lockResult = null; + if (lock) { + lockResult = + lockComponent(service.getUniqueId(), service, "Create Service Filter"); + if (lockResult.isRight()) { + log.debug("Failed to lock service {}. Response is {}. ", service.getName(), + lockResult.right().value().getFormattedMessage()); + return Either.right(lockResult.right().value()); + } else { + log.debug("The service with system name {} locked. ", service.getSystemName()); + } + } + CINodeFilterDataDefinition serviceFilterResult; + try { + result = serviceFilterOperation.createNodeFilter(serviceId, componentInstanceId); + if (result.isRight()) { + titanDao.rollback(); + return Either.right(componentsUtils.getResponseFormat( + componentsUtils.convertFromStorageResponse(result.right().value(), ComponentTypeEnum.SERVICE), + "")); + } else { + serviceFilterResult = result.left().value(); + } + titanDao.commit(); + + } catch (Exception e) { + titanDao.rollback(); + log.error("Exception occurred during add or update service filter property values: {}", e.getMessage(), + e); + return Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR)); + + } finally { + if (lockResult != null && lockResult.isLeft() && lockResult.left().value()) { + graphLockOperation.unlockComponent(service.getUniqueId(), NodeTypeEnum.Service); + } + } + return Either.left(serviceFilterResult); + } + + + public Either<CINodeFilterDataDefinition, ResponseFormat> updateServiceFilter(String serviceId, String componentInstanceId, + List<String> constraints, User inUser, boolean lock) { + String errorContext = "createIfNotAlreadyExistServiceFilter"; + Either<?, ResponseFormat> eitherCreator1 = null; + User user = validateUserExists(inUser, errorContext, true); + validateUserRole(user, Arrays.asList(Role.DESIGNER, Role.ADMIN)); + if (eitherCreator1 != null && eitherCreator1.isRight()) { + return Either.right(eitherCreator1.right().value()); + } + + Either<Service, StorageOperationStatus> serviceStorageOperationStatusEither = toscaOperationFacade.getToscaElement(serviceId); + + if(serviceStorageOperationStatusEither.isRight()){ + StorageOperationStatus errorStatus = serviceStorageOperationStatusEither.right().value(); + log.debug("Failed to fetch service information by service id, error {}", errorStatus); + return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(errorStatus))); + } + Service storedService = serviceStorageOperationStatusEither.left().value(); + + Either<Boolean, ResponseFormat> booleanResponseFormatEither = + serviceFilterValidator.validateNodeFilter(storedService, componentInstanceId, constraints, + NodeFilterConstraintAction.UPDATE); + if(booleanResponseFormatEither.isRight()){ + return Either.right(booleanResponseFormatEither.right().value()); + } + + + Either<Boolean, ResponseFormat> lockResult = null; + if (lock) { + lockResult = + lockComponent(storedService.getUniqueId(), storedService, "Add or Update Service Filter on Service"); + if (lockResult.isRight()) { + log.debug("Failed to lock service {}. Response is {}. ", storedService.getName(), + lockResult.right().value().getFormattedMessage()); + return Either.right(lockResult.right().value()); + } else { + log.debug("The service with system name {} locked. ", storedService.getSystemName()); + } + } + Optional<ComponentInstance> componentInstanceOptional = storedService.getComponentInstanceById(componentInstanceId); + if (!componentInstanceOptional.isPresent()){ + return Either.right(ResponseFormatManager.getInstance().getResponseFormat(ActionStatus.NODE_FILTER_NOT_FOUND)); + } + CINodeFilterDataDefinition serviceFilter = componentInstanceOptional.get().getNodeFilter(); + if(serviceFilter == null){ + return Either.right(ResponseFormatManager.getInstance().getResponseFormat(ActionStatus.NODE_FILTER_NOT_FOUND)); + } + CINodeFilterDataDefinition serviceFilterResult; + try { + List<RequirementNodeFilterPropertyDataDefinition> properties = (List<RequirementNodeFilterPropertyDataDefinition>) constraints. + stream().map(this::getRequirementNodeFilterPropertyDataDefinition).collect(Collectors.toList()); + Either<CINodeFilterDataDefinition, StorageOperationStatus> result = serviceFilterOperation.updateProperties(serviceId, componentInstanceId, serviceFilter ,properties); + + if (result.isRight()) { + titanDao.rollback(); + return Either.right(componentsUtils.getResponseFormat( + componentsUtils.convertFromStorageResponse(result.right().value(), ComponentTypeEnum.SERVICE), + "")); + } else { + serviceFilterResult = result.left().value(); + } + titanDao.commit(); + + } catch (Exception e) { + titanDao.rollback(); + log.error("Exception occurred during add or update service filter property values: {}", e.getMessage(), + e); + return Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR)); + + } finally { + if (lockResult != null && lockResult.isLeft() && lockResult.left().value()) { + graphLockOperation.unlockComponent(storedService.getUniqueId(), NodeTypeEnum.Service); + } + } + return Either.left(serviceFilterResult); + } + + private RequirementNodeFilterPropertyDataDefinition getRequirementNodeFilterPropertyDataDefinition(String constraint){ + RequirementNodeFilterPropertyDataDefinition pdd = new RequirementNodeFilterPropertyDataDefinition(); + pdd.setConstraints(Arrays.asList(constraint)); + return pdd; + } + + public Either<CINodeFilterDataDefinition, ResponseFormat> addOrDeleteServiceFilter(String serviceId, String componentInstanceId, + NodeFilterConstraintAction action, String constraint, int position, User inUser, boolean lock) { + String errorContext = "createIfNotAlreadyExistServiceFilter"; + Either<?, ResponseFormat> eitherCreator1 = null; + User user = validateUserExists(inUser, errorContext, true); + validateUserRole(user, Arrays.asList(Role.DESIGNER, Role.ADMIN)); + if (eitherCreator1 != null && eitherCreator1.isRight()) { + return Either.right(eitherCreator1.right().value()); + } + + Either<Service, StorageOperationStatus> serviceStorageOperationStatusEither = toscaOperationFacade.getToscaElement(serviceId); + + if(serviceStorageOperationStatusEither.isRight()){ + StorageOperationStatus errorStatus = serviceStorageOperationStatusEither.right().value(); + log.debug("Failed to fetch service information by service id, error {}", errorStatus); + return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(errorStatus))); + } + Service storedService = serviceStorageOperationStatusEither.left().value(); + + Either<Boolean, ResponseFormat> booleanResponseFormatEither = + serviceFilterValidator.validateNodeFilter(storedService, componentInstanceId, + Collections.singletonList(constraint), action); + if(booleanResponseFormatEither.isRight()){ + return Either.right(booleanResponseFormatEither.right().value()); + } + + Either<CINodeFilterDataDefinition, StorageOperationStatus> result; + + Either<Boolean, ResponseFormat> lockResult = null; + if (lock) { + lockResult = + lockComponent(storedService.getUniqueId(), storedService, "Add or Update Service Filter on Service"); + if (lockResult.isRight()) { + log.debug("Failed to lock service {}. Response is {}. ", storedService.getName(), + lockResult.right().value().getFormattedMessage()); + return Either.right(lockResult.right().value()); + } else { + log.debug("The service with system name {} locked. ", storedService.getSystemName()); + } + } + + Optional<ComponentInstance> componentInstanceOptional = storedService.getComponentInstanceById(componentInstanceId); + if (!componentInstanceOptional.isPresent()){ + return Either.right(ResponseFormatManager.getInstance().getResponseFormat(ActionStatus.NODE_FILTER_NOT_FOUND)); + } + CINodeFilterDataDefinition serviceFilter = componentInstanceOptional.get().getNodeFilter(); + if(serviceFilter == null){ + return Either.right(ResponseFormatManager.getInstance().getResponseFormat(ActionStatus.NODE_FILTER_NOT_FOUND)); + } + CINodeFilterDataDefinition serviceFilterResult; + try { + switch (action) { + case ADD: + RequirementNodeFilterPropertyDataDefinition newProperty = new RequirementNodeFilterPropertyDataDefinition(); + newProperty.setConstraints(Collections.singletonList(constraint)); + result = serviceFilterOperation.addNewProperty(serviceId, componentInstanceId,serviceFilter,newProperty); + break; + case DELETE: + result = serviceFilterOperation.deleteConstraint(serviceId, componentInstanceId, serviceFilter, position); + break; + default: + log.error("Unsupported operation "+action); + return Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR)); + + } + + if (result.isRight()) { + titanDao.rollback(); + return Either.right(componentsUtils.getResponseFormat( + componentsUtils.convertFromStorageResponse(result.right().value(), ComponentTypeEnum.SERVICE), + "")); + } else { + serviceFilterResult = result.left().value(); + } + titanDao.commit(); + + } catch (Exception e) { + titanDao.rollback(); + log.error("Exception occurred during add or update node filter property values: {}", e.getMessage(), + e); + return Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR)); + + } finally { + if (lockResult != null && lockResult.isLeft() && lockResult.left().value()) { + graphLockOperation.unlockComponent(storedService.getUniqueId(), NodeTypeEnum.Service); + } + } + return Either.left(serviceFilterResult); + } } 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 new file mode 100644 index 0000000000..73ec3352b3 --- /dev/null +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/utils/CINodeFilterUtils.java @@ -0,0 +1,87 @@ +/* + * Copyright © 2016-2018 European Support Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.openecomp.sdc.be.components.impl.utils; + +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import org.openecomp.sdc.be.datatypes.elements.CINodeFilterDataDefinition; +import org.openecomp.sdc.be.datatypes.elements.ListDataDefinition; +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; + +public class CINodeFilterUtils { + + Logger log = Logger.getLogger(CINodeFilterUtils.class); + + + public CINodeFilterDataDefinition getNodeFilterDataDefinition( + UploadNodeFilterInfo uploadNodeFilterInfo, String uniqueId) { + CINodeFilterDataDefinition nodeFilterDataDefinition = + new CINodeFilterDataDefinition(); + nodeFilterDataDefinition.setName(uploadNodeFilterInfo.getName()); + List<RequirementNodeFilterPropertyDataDefinition> collect = + uploadNodeFilterInfo.getProperties().stream().map(this::buildProperty).collect(Collectors.toList()); + ListDataDefinition<RequirementNodeFilterPropertyDataDefinition> listDataDefinition = new ListDataDefinition<>(); + listDataDefinition.getListToscaDataDefinition().addAll(collect); + nodeFilterDataDefinition.setProperties(listDataDefinition); + nodeFilterDataDefinition.setCapabilities(converCapabilties(uploadNodeFilterInfo.getCapabilities())); + nodeFilterDataDefinition.setID(uniqueId); + nodeFilterDataDefinition.setTosca_id(uploadNodeFilterInfo.getTosca_id()); + return nodeFilterDataDefinition; + } + + private ListDataDefinition<RequirementNodeFilterCapabilityDataDefinition> converCapabilties( + Map<String, UploadNodeFilterCapabilitiesInfo> capabilities) { + ListDataDefinition<RequirementNodeFilterCapabilityDataDefinition> listDataDefinition = + new ListDataDefinition<>(); + for (UploadNodeFilterCapabilitiesInfo capability : capabilities.values()) { + RequirementNodeFilterCapabilityDataDefinition requirementNodeFilterCapabilityDataDefinition = + convertCapability(capability); + listDataDefinition.add(requirementNodeFilterCapabilityDataDefinition); + } + return listDataDefinition; + } + + private RequirementNodeFilterCapabilityDataDefinition convertCapability( + UploadNodeFilterCapabilitiesInfo capability) { + RequirementNodeFilterCapabilityDataDefinition retVal = new RequirementNodeFilterCapabilityDataDefinition(); + retVal.setName(capability.getName()); + List<RequirementNodeFilterPropertyDataDefinition> props = + capability.getProperties().stream().map(this::buildProperty).collect(Collectors.toList()); + ListDataDefinition<RequirementNodeFilterPropertyDataDefinition> 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; + } + + +} diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/utils/NodeFilterConstraintAction.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/utils/NodeFilterConstraintAction.java new file mode 100644 index 0000000000..32f49b3849 --- /dev/null +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/utils/NodeFilterConstraintAction.java @@ -0,0 +1,20 @@ +/* + * Copyright © 2016-2018 European Support Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openecomp.sdc.be.components.impl.utils; + +public enum NodeFilterConstraintAction { + ADD, DELETE, UPDATE +} 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 new file mode 100644 index 0000000000..8d2808851b --- /dev/null +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/validation/NodeFilterValidator.java @@ -0,0 +1,226 @@ +package org.openecomp.sdc.be.components.validation; + +import com.google.common.collect.ImmutableSet; +import fj.data.Either; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.Set; +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.CINodeFilterDataDefinition; +import org.openecomp.sdc.be.datatypes.elements.SchemaDefinition; +import org.openecomp.sdc.be.impl.ComponentsUtils; +import org.openecomp.sdc.be.model.ComponentInstance; +import org.openecomp.sdc.be.model.ComponentInstanceProperty; +import org.openecomp.sdc.be.model.PropertyDefinition; +import org.openecomp.sdc.be.model.Service; +import org.openecomp.sdc.be.model.jsontitan.operations.ToscaOperationFacade; +import org.openecomp.sdc.be.model.tosca.ToscaPropertyType; +import org.openecomp.sdc.be.ui.model.UIConstraint; +import org.openecomp.sdc.exception.ResponseFormat; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; + +@Component("NodeFilterValidator") +public class NodeFilterValidator { + + private static final String SOURCE = "Source"; + public static final Set<String> comparableTypes = ImmutableSet.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); + + @Autowired + protected ToscaOperationFacade toscaOperationFacade; + + @Autowired + protected ComponentsUtils componentsUtils; + + private static final Logger LOGGER = LoggerFactory.getLogger(NodeFilterValidator.class); + + public Either<Boolean, ResponseFormat> validateComponentInstanceExist(Service service, String componentInstanceId) { + if (service == null || StringUtils.isEmpty(componentInstanceId)) { + LOGGER.debug("Input data cannot be empty"); + return getErrorResponse(ActionStatus.NODE_FILTER_NOT_FOUND); + } + if (CollectionUtils.isEmpty(service.getComponentInstances())) { + LOGGER.debug("Component Instance list is empty"); + return getErrorResponse(ActionStatus.NODE_FILTER_NOT_FOUND); + } + boolean found = + service.getComponentInstances().stream().anyMatch(ci -> ci.getUniqueId().equals(componentInstanceId)); + if (!found) { + LOGGER.debug("Component Instance list is empty"); + return getErrorResponse(ActionStatus.NODE_FILTER_NOT_FOUND); + } + 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> validateNodeFilter(CINodeFilterDataDefinition nodeFilter, String serviceId, + String complonentInstanceId) { + return Either.left(Boolean.TRUE); + } + + + public Either<Boolean, ResponseFormat> validateNodeFilter(Service parentComponent, String componentInstanceId, + List<String> uiConstraints, NodeFilterConstraintAction action) { + try { + for (String uiConstraint : uiConstraints) { + if (NodeFilterConstraintAction.ADD != action && NodeFilterConstraintAction.UPDATE != action) { + break; + } + UIConstraint constraint = new ConstraintConvertor().convert(uiConstraint); + if (ConstraintConvertor.PROPERTY_CONSTRAINT.equals(constraint.getSourceType())) { + final Either<Boolean, ResponseFormat> booleanResponseFormatEither = + validatePropertyConstraint(parentComponent, componentInstanceId, constraint); + if (booleanResponseFormatEither.isRight()) { + return booleanResponseFormatEither; + } + } else if (ConstraintConvertor.STATIC_CONSTRAINT.equals(constraint.getSourceType())) { + final Either<Boolean, ResponseFormat> booleanResponseFormatEither = + validateStaticValueAndOperator(parentComponent, componentInstanceId, constraint); + if (booleanResponseFormatEither.isRight()) { + return booleanResponseFormatEither; + } + } + } + } catch (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> validatePropertyConstraint(Service parentComponent, + String componentInstanceId, UIConstraint uiConstraint) { + String source = SOURCE; + Optional<ComponentInstance> brotherComponentInstance; + + List<? extends PropertyDefinition> sourcePropertyDefinition = + parentComponent.getName().equals(uiConstraint.getSourceName()) ? parentComponent.getProperties() : + Collections.emptyList(); + + + if (sourcePropertyDefinition.isEmpty() && !parentComponent.getName().equals(uiConstraint.getSourceName())) { + brotherComponentInstance = parentComponent.getComponentInstances().stream() + .filter(componentInstance -> uiConstraint.getSourceName() + .equals(componentInstance + .getName())) + .findFirst(); + + if (brotherComponentInstance.isPresent()) { + final List<ComponentInstanceProperty> componentInstanceProperties = + parentComponent.getComponentInstancesProperties() + .get(brotherComponentInstance.get().getUniqueId()); + sourcePropertyDefinition = + componentInstanceProperties == null ? new ArrayList<>() : componentInstanceProperties; + } + } + + if (!CollectionUtils.isEmpty(sourcePropertyDefinition)) { + Optional<? extends PropertyDefinition> sourceSelectedProperty = sourcePropertyDefinition.stream() + .filter(property -> uiConstraint + .getValue() + .equals(property.getName())) + .findFirst(); + + Optional<? extends PropertyDefinition> targetComponentInstanceProperty = + parentComponent.getComponentInstancesProperties().get(componentInstanceId).stream() + .filter(property -> uiConstraint.getServicePropertyName().equals(property.getName())) + .findFirst(); + + source = !targetComponentInstanceProperty.isPresent() ? "Target" : SOURCE; + if (sourceSelectedProperty.isPresent() && targetComponentInstanceProperty.isPresent()) { + return validatePropertyData(uiConstraint, sourceSelectedProperty, targetComponentInstanceProperty); + } + } + + 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> validatePropertyData(UIConstraint uiConstraint, + Optional<? extends PropertyDefinition> sourceSelectedProperty, + Optional<? extends PropertyDefinition> targetComponentInstanceProperty) { + 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())); + } + } + return Either.left(Boolean.TRUE); + } else { + return Either.right(componentsUtils.getResponseFormat(ActionStatus.SOURCE_TARGET_PROPERTY_TYPE_MISMATCH, + uiConstraint.getServicePropertyName(), uiConstraint.getValue().toString())); + } + } + + private Either<Boolean, ResponseFormat> validateStaticValueAndOperator(Service parentComponent, + String componentInstanceId, UIConstraint uiConstraint) { + if (!(Objects.nonNull(uiConstraint) && uiConstraint.getValue() instanceof String)) { + return Either.left(false); + } + 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()); + } + + private Either<Boolean, ResponseFormat> isValidValueCheck(String type, String value, String propertyName) { + + ToscaPropertyType toscaPropertyType = ToscaPropertyType.isValidType(type); + if (Objects.isNull(toscaPropertyType)) { + return Either.right( + componentsUtils.getResponseFormat(ActionStatus.UNSUPPORTED_PROPERTY_TYPE, type, propertyName)); + } + if (toscaPropertyType.getValidator().isValid(value, null)) { + return Either.left(Boolean.TRUE); + } + return Either.right( + componentsUtils.getResponseFormat(ActionStatus.UNSUPPORTED_VALUE_PROVIDED, type, propertyName, value)); + } + + +} + + 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 new file mode 100644 index 0000000000..e05ef92431 --- /dev/null +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/datamodel/utils/ConstraintConvertor.java @@ -0,0 +1,138 @@ +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.Set; +import org.openecomp.sdc.be.model.tosca.constraints.ConstraintType; +import org.openecomp.sdc.be.ui.model.UIConstraint; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.yaml.snakeyaml.Yaml; + +public class ConstraintConvertor { + + private static final Logger logger = LoggerFactory.getLogger(ConstraintConvertor.class); + + 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 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 Set<String> SUPPORTED_CONSTRAINT_LIST = + ImmutableSet.of(EQUAL_OPERATOR, GREATER_THAN_OPERATOR, LESS_THAN_OPERATOR); + private static final String GET_INPUT = "get_input"; + private static final String GET_PROPERTY = "get_property"; + private static final Set<String> SUPPORTED_FUNCTIONS = ImmutableSet.of(GET_INPUT, GET_PROPERTY); + + + public UIConstraint convert(String inConstraint) { + Yaml yamlSource = new Yaml(); + UIConstraint uiConstraint = new UIConstraint(); + Object content1 = yamlSource.load(inConstraint); + if (content1 instanceof Map) { + Map map1 = (Map) content1; + Object key = map1.keySet().iterator().next(); + uiConstraint.setServicePropertyName(key.toString()); + Object content2 = map1.get(key); + if (content2 instanceof Map && handleServiceConstraint(uiConstraint, (Map) content2)) { + return uiConstraint; + } + } + return null; + } + + private boolean handleServiceConstraint(UIConstraint uiConstraint, Map content2) { + Map map2 = content2; + Object key2 = map2.keySet().iterator().next(); + final String operator = key2.toString(); + if (SUPPORTED_CONSTRAINT_LIST.contains(operator)) { + uiConstraint.setConstraintOperator(operator); + } + Object content3 = map2.get(key2); + if (content3 instanceof String || content3 instanceof Number || content3 instanceof Boolean) { + uiConstraint.setValue(content3); + uiConstraint.setSourceType(STATIC_CONSTRAINT); + return true; + } else if (content3 instanceof List) { + List list1 = (List) content3; + uiConstraint.setSourceType(STATIC_CONSTRAINT); + uiConstraint.setValue(list1); + return true; + } else if (content3 instanceof Map) { + Map map3 = (Map) content3; + Map.Entry entry = (Map.Entry) map3.entrySet().iterator().next(); + final String firstKey = entry.getKey().toString().trim(); + if (handleSupportedFunctions(uiConstraint, entry, firstKey)) { + return true; + } + uiConstraint.setValue(content3); + return true; + } + return false; + } + + private boolean handleSupportedFunctions(UIConstraint uiConstraint, Map.Entry entry, String firstKey) { + if (SUPPORTED_FUNCTIONS.contains(firstKey)) { + if (GET_INPUT.equals(firstKey)) { + uiConstraint.setSourceType(SERVICE_INPUT_CONSTRAINT); + uiConstraint.setValue(entry.getValue()); + return true; + } else if (GET_PROPERTY.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 true; + } + } + return false; + } + + public List<String> convertToList(List<UIConstraint> uiConstraints) { + List<String> retVal = new ArrayList<>(); + for (UIConstraint uiConstraint : uiConstraints) { + String constraint = convert(uiConstraint); + if (constraint != null) { + retVal.add(constraint); + } + } + return retVal; + } + + public String convert(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()); + } + map2.put(uiConstraint.getConstraintOperator(), value); + } else if (uiConstraint.getSourceType().equals(PROPERTY_CONSTRAINT)) { + List list1 = Arrays.asList(uiConstraint.getSourceName(), uiConstraint.getValue()); + Map map3 = ImmutableMap.of(GET_PROPERTY, list1); + map2.put(uiConstraint.getConstraintOperator(), map3); + } else if (uiConstraint.getSourceType().equals(SERVICE_INPUT_CONSTRAINT)) { + Map map3 = ImmutableMap.of(GET_INPUT, uiConstraint.getValue()); + map2.put(uiConstraint.getConstraintOperator(), map3); + } + + + Yaml yamlSource = new Yaml(); + return yamlSource.dump(map1); + } catch (NullPointerException ex) { + logger.error(ex.getMessage(), ex); + } + return null; + } +} diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ServiceFilterServlet.java b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ServiceFilterServlet.java new file mode 100644 index 0000000000..3daca3f28c --- /dev/null +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ServiceFilterServlet.java @@ -0,0 +1,258 @@ +package org.openecomp.sdc.be.servlets; + +import fj.data.Either; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import javax.inject.Singleton; +import javax.servlet.ServletContext; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpSession; +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.HeaderParam; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import org.codehaus.jackson.map.ObjectMapper; +import org.openecomp.sdc.be.components.impl.ServiceBusinessLogic; +import org.openecomp.sdc.be.components.impl.utils.NodeFilterConstraintAction; +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.model.User; +import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum; +import org.openecomp.sdc.be.tosca.utils.NodeFilterConverter; +import org.openecomp.sdc.be.ui.model.UIConstraint; +import org.openecomp.sdc.be.ui.model.UINodeFilter; +import org.openecomp.sdc.common.api.Constants; +import org.openecomp.sdc.exception.ResponseFormat; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@Path("/v1/catalog/services/{serviceId}/resourceInstances/{resourceInstanceId}/nodeFilter") +@Consumes(MediaType.APPLICATION_JSON) +@Produces(MediaType.APPLICATION_JSON) +@Api(value = "Service Filter", description = "Service Filter Servlet") +@Singleton +public class ServiceFilterServlet extends AbstractValidationsServlet { + + private static final Logger log = LoggerFactory.getLogger(ServiceFilterServlet.class); + private static final String START_HANDLE_REQUEST_OF = "Start handle request of {}"; + private static final String MODIFIER_ID_IS = "modifier id is {}"; + private static final String FAILED_TO_UPDATE_OR_CREATE_NODE_FILTER = "failed to update or create node filter"; + private static final String FAILED_TO_PARSE_SERVICE = "failed to parse service"; + private static final String NODE_FILTER_CREATION_OR_UPDATE = "Node Filter Creation or update"; + private static final String CREATE_OR_UPDATE_NODE_FILTER_WITH_AN_ERROR = + "create or update node filter with an error"; + + @POST + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @Path("/") + @ApiOperation(value = "Add Service Filter Constraint", httpMethod = "POST", notes = "Add Service Filter Constraint", + response = Response.class) + @ApiResponses(value = {@ApiResponse(code = 201, message = "Create Service Filter"), + @ApiResponse(code = 403, message = "Restricted operation"), + @ApiResponse(code = 400, message = "Invalid content / Missing content")}) + public Response addServiceFilterConstraint(@ApiParam(value = "Service data", required = true) String data, + @ApiParam(value = "Service Id") @PathParam("serviceId") String serviceId, + @ApiParam(value = "Resource Instance Id") @PathParam("resourceInstanceId") String ciId, + @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) { + + String url = request.getMethod() + " " + request.getRequestURI(); + log.debug(START_HANDLE_REQUEST_OF, url); + final HttpSession session = request.getSession(); + ServletContext context = session.getServletContext(); + User modifier = new User(); + modifier.setUserId(userId); + log.debug(MODIFIER_ID_IS, userId); + + Response response; + + try { + String serviceIdLower = serviceId.toLowerCase(); + ServiceBusinessLogic businessLogic = getServiceBL(context); + + Either<UIConstraint, ResponseFormat> convertResponse = parseToConstraint(data, modifier); + if (convertResponse.isRight()) { + log.debug(FAILED_TO_PARSE_SERVICE); + response = buildErrorResponse(convertResponse.right().value()); + return response; + } + UIConstraint uiConstraint = convertResponse.left().value(); + if (uiConstraint == null) { + log.debug(FAILED_TO_PARSE_SERVICE); + response = buildErrorResponse(convertResponse.right().value()); + return response; + } + Either<CINodeFilterDataDefinition, ResponseFormat> actionResponse; + String constraint = new ConstraintConvertor().convert(uiConstraint); + actionResponse = businessLogic + .addOrDeleteServiceFilter(serviceIdLower, ciId, NodeFilterConstraintAction.ADD, + constraint, -1, modifier, true); + + if (actionResponse.isRight()) { + log.debug(FAILED_TO_UPDATE_OR_CREATE_NODE_FILTER); + response = buildErrorResponse(actionResponse.right().value()); + return response; + } + + CINodeFilterDataDefinition value = actionResponse.left().value(); + UINodeFilter nodeFilter = new NodeFilterConverter().convertToUi(value); + return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), nodeFilter); + + } catch (Exception e) { + BeEcompErrorManager.getInstance().logBeRestApiGeneralError(NODE_FILTER_CREATION_OR_UPDATE); + log.debug(CREATE_OR_UPDATE_NODE_FILTER_WITH_AN_ERROR, e); + response = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR)); + return response; + + } + } + + @PUT + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @Path("/") + @ApiOperation(value = "Update Service Filter Constraint", httpMethod = "PUT", + notes = "Update Service Filter Constraint", response = Response.class) + @ApiResponses(value = {@ApiResponse(code = 201, message = "Create Service Filter"), + @ApiResponse(code = 403, message = "Restricted operation"), + @ApiResponse(code = 400, message = "Invalid content / Missing content")}) + public Response updateServiceFilterConstraint(@ApiParam(value = "Service data", required = true) String data, + @ApiParam(value = "Service Id") @PathParam("serviceId") String serviceId, + @ApiParam(value = "Resource Instance Id") @PathParam("resourceInstanceId") String ciId, + @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) { + ServletContext context = request.getSession().getServletContext(); + String url = request.getMethod() + " " + request.getRequestURI(); + log.debug(START_HANDLE_REQUEST_OF, url); + + User modifier = new User(); + modifier.setUserId(userId); + log.debug(MODIFIER_ID_IS, userId); + + Response response; + + try { + String serviceIdLower = serviceId.toLowerCase(); + ServiceBusinessLogic businessLogic = getServiceBL(context); + + Either<List, ResponseFormat> convertResponse = parseToConstraints(data, modifier); + if (convertResponse.isRight()) { + log.debug(FAILED_TO_PARSE_SERVICE); + response = buildErrorResponse(convertResponse.right().value()); + return response; + } + List<Map<String,String>> uiConstraintsMaps = (List<Map<String,String>>) convertResponse.left().value(); + if (uiConstraintsMaps == null) { + log.debug("failed to parse data"); + response = buildErrorResponse(convertResponse.right().value()); + return response; + } + final ObjectMapper objectMapper = new ObjectMapper(); + List<UIConstraint> uiConstraints = uiConstraintsMaps.stream().map(dataMap -> objectMapper.convertValue(dataMap, UIConstraint.class)).collect( + Collectors.toList()); + if (uiConstraints == null) { + log.debug("failed to parse data"); + response = buildErrorResponse(convertResponse.right().value()); + return response; + } + Either<CINodeFilterDataDefinition, ResponseFormat> actionResponse; + List<String> constraints = new ConstraintConvertor().convertToList(uiConstraints); + actionResponse = businessLogic.updateServiceFilter(serviceIdLower, ciId, constraints, modifier, true); + + if (actionResponse.isRight()) { + log.debug(FAILED_TO_UPDATE_OR_CREATE_NODE_FILTER); + response = buildErrorResponse(actionResponse.right().value()); + return response; + } + + CINodeFilterDataDefinition value = actionResponse.left().value(); + return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), + new NodeFilterConverter().convertToUi(value)); + + } catch (Exception e) { + BeEcompErrorManager.getInstance().logBeRestApiGeneralError(NODE_FILTER_CREATION_OR_UPDATE); + log.debug(CREATE_OR_UPDATE_NODE_FILTER_WITH_AN_ERROR, e); + response = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR)); + return response; + + } + } + + @DELETE + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @Path("/{constraintIndex}") + @ApiOperation(value = "Delete Service Filter Constraint", httpMethod = "Delete", + notes = "Delete Service Filter Constraint", response = Response.class) + @ApiResponses(value = {@ApiResponse(code = 201, message = "Delete Service Filter Constraint"), + @ApiResponse(code = 403, message = "Restricted operation"), + @ApiResponse(code = 400, message = "Invalid content / Missing content")}) + public Response deleteServiceFilterConstraint( + @ApiParam(value = "Service Id") @PathParam("serviceId") String serviceId, + @ApiParam(value = "Resource Instance Id") @PathParam("resourceInstanceId") String ciId, + @ApiParam(value = "Constraint Index") @PathParam("constraintIndex") int index, + @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) { + ServletContext context = request.getSession().getServletContext(); + String url = request.getMethod() + " " + request.getRequestURI(); + log.debug(START_HANDLE_REQUEST_OF, url); + + User modifier = new User(); + modifier.setUserId(userId); + log.debug(MODIFIER_ID_IS, userId); + + Response response; + + try { + String serviceIdLower = serviceId.toLowerCase(); + ServiceBusinessLogic businessLogic = getServiceBL(context); + + Either<CINodeFilterDataDefinition, ResponseFormat> actionResponse; + actionResponse = businessLogic + .addOrDeleteServiceFilter(serviceIdLower, ciId, NodeFilterConstraintAction.DELETE, + null, index, modifier, true); + + if (actionResponse.isRight()) { + + log.debug(FAILED_TO_UPDATE_OR_CREATE_NODE_FILTER); + response = buildErrorResponse(actionResponse.right().value()); + return response; + } + + final CINodeFilterDataDefinition value = actionResponse.left().value(); + return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), + new NodeFilterConverter().convertToUi(value)); + + } catch (Exception e) { + BeEcompErrorManager.getInstance().logBeRestApiGeneralError(NODE_FILTER_CREATION_OR_UPDATE); + log.debug(CREATE_OR_UPDATE_NODE_FILTER_WITH_AN_ERROR, e); + response = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR)); + return response; + + } + } + + private Either<UIConstraint, ResponseFormat> parseToConstraint(String serviceJson, User user) { + return getComponentsUtils().convertJsonToObjectUsingObjectMapper(serviceJson, user, UIConstraint.class, + AuditingActionEnum.CREATE_RESOURCE, ComponentTypeEnum.SERVICE); + } + + private Either<List, ResponseFormat> parseToConstraints(String serviceJson, User user) { + return getComponentsUtils().convertJsonToObjectUsingObjectMapper(serviceJson, user, List.class, + AuditingActionEnum.CREATE_RESOURCE, ComponentTypeEnum.SERVICE); + } +} diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/CapabilityFilter.java b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/CapabilityFilter.java new file mode 100644 index 0000000000..58a9a759bf --- /dev/null +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/CapabilityFilter.java @@ -0,0 +1,54 @@ +/* + * Copyright © 2016-2018 European Support Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.openecomp.sdc.be.tosca.model; + + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import org.apache.commons.collections.CollectionUtils; + + + +public class CapabilityFilter { + + List<Map<String, List<Object>>> properties; + + public List<Map<String, List<Object>>> getProperties() { + return properties; + } + + public void setProperties(List<Map<String, List<Object>>> properties) { + this.properties = properties; + } + + public void addProperty(Map<String, List<Object>> property) { + if(CollectionUtils.isEmpty(properties)) { + this.properties = new ArrayList<>(); + } + + this.properties.add(property); + } + + @Override + public String toString() { + final StringBuilder sb = new StringBuilder("CapabilityFilter{"); + sb.append("properties=").append(properties); + sb.append('}'); + return sb.toString(); + } +} diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/NodeFilter.java b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/NodeFilter.java new file mode 100644 index 0000000000..79e9f57209 --- /dev/null +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/NodeFilter.java @@ -0,0 +1,50 @@ +/* + * Copyright © 2016-2018 European Support Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openecomp.sdc.be.tosca.model; + +import java.util.List; +import java.util.Map; + +public class NodeFilter { + + Object tosca_id; + List<Map<String, List<Object>>> properties; + List<Map<String, CapabilityFilter>> capabilities; + + public Object getTosca_id() { + return tosca_id; + } + + public void setTosca_id(Object tosca_id) { + this.tosca_id = tosca_id; + } + + public List<Map<String, CapabilityFilter>> getCapabilities() { + return capabilities; + } + + public void setCapabilities(List<Map<String, CapabilityFilter>> capabilities) { + this.capabilities = capabilities; + } + + public List<Map<String, List<Object>>> getProperties() { + return properties; + } + + public void setProperties(List<Map<String, List<Object>>> properties) { + this.properties = properties; + } +}
\ No newline at end of file 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 new file mode 100644 index 0000000000..af0837fdcf --- /dev/null +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/utils/NodeFilterConverter.java @@ -0,0 +1,139 @@ +/* + * Copyright © 2016-2018 European Support Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.openecomp.sdc.be.tosca.utils; + +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +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.CINodeFilterDataDefinition; +import org.openecomp.sdc.be.datatypes.elements.RequirementNodeFilterCapabilityDataDefinition; +import org.openecomp.sdc.be.datatypes.elements.RequirementNodeFilterPropertyDataDefinition; +import org.openecomp.sdc.be.tosca.model.CapabilityFilter; +import org.openecomp.sdc.be.tosca.model.NodeFilter; +import org.openecomp.sdc.be.ui.model.UIConstraint; +import org.openecomp.sdc.be.ui.model.UINodeFilter; + +public class NodeFilterConverter { + + + public NodeFilter convertNodeFilter(CINodeFilterDataDefinition nodeFilterData) { + NodeFilter retVal = new NodeFilter(); + if (nodeFilterData.getCapabilities() != null) { + retVal.setCapabilities(convertCapabilities(nodeFilterData.getCapabilities().getListToscaDataDefinition())); + } + if (nodeFilterData.getProperties() != null) { + retVal.setProperties(convertProperties(nodeFilterData.getProperties().getListToscaDataDefinition())); + } + return retVal; + } + + private List<Map<String, CapabilityFilter>> convertCapabilities( + List<RequirementNodeFilterCapabilityDataDefinition> capabilities) { + if (CollectionUtils.isEmpty(capabilities)) { + return Collections.emptyList(); + } + return capabilities.stream().map(this::transformCapability).collect(Collectors.toList()); + } + + private Map<String, CapabilityFilter> transformCapability( + RequirementNodeFilterCapabilityDataDefinition capability) { + Map<String, CapabilityFilter> retVal = new HashMap<>(); + if (capability.getProperties() == null) { + return retVal; + } + List<RequirementNodeFilterPropertyDataDefinition> propertyDataDefinitionList = + capability.getProperties().getListToscaDataDefinition(); + for (RequirementNodeFilterPropertyDataDefinition propertyDataDefinition : propertyDataDefinitionList) { + retVal.put(capability.getName(), convertCapabilityProperty(propertyDataDefinition)); + } + return retVal; + } + + private List<Map<String, List<Object>>> convertProperties( + List<RequirementNodeFilterPropertyDataDefinition> properties) { + if (CollectionUtils.isEmpty(properties)) { + return Collections.emptyList(); + } + return properties.stream().map(this::transformProperty).collect(Collectors.toList()); + } + + private CapabilityFilter convertCapabilityProperty(RequirementNodeFilterPropertyDataDefinition property) { + TransformCapabilityData transformCapabilityData = new TransformCapabilityData(property).invoke(); + Map<String, List<Object>> tranformedMap = transformCapabilityData.getRetVal(); + List<Object> constraints = transformCapabilityData.getConstraints(); + tranformedMap.put(property.getName(), constraints); + CapabilityFilter capabilityFilter = new CapabilityFilter(); + capabilityFilter.setProperties(Collections.singletonList(tranformedMap)); + return capabilityFilter; + } + + + private Map<String, List<Object>> transformProperty(RequirementNodeFilterPropertyDataDefinition property) { + TransformCapabilityData transformCapabilityData = new TransformCapabilityData(property).invoke(); + Map<String, List<Object>> retVal = transformCapabilityData.getRetVal(); + List<Object> constraints = transformCapabilityData.getConstraints(); + retVal.put(property.getName(), constraints); + + return retVal; + } + + private class TransformCapabilityData { + + private RequirementNodeFilterPropertyDataDefinition property; + private Map<String, List<Object>> retVal; + private List<Object> constraints; + + public TransformCapabilityData(RequirementNodeFilterPropertyDataDefinition property) { + this.property = property; + } + + public Map<String, List<Object>> getRetVal() { + return retVal; + } + + public List<Object> getConstraints() { + return constraints; + } + + public TransformCapabilityData invoke() { + final List<String> propertyConstraints = property.getConstraints(); + if (CollectionUtils.isEmpty(propertyConstraints)) { + return this; + } + this.constraints = propertyConstraints.stream().map(c -> (Object) c).collect(Collectors.toList()); + return this; + } + } + + public UINodeFilter convertToUi(CINodeFilterDataDefinition inNodeFilter) { + UINodeFilter retVal = new UINodeFilter(); + final ConstraintConvertor constraintConvertor = new ConstraintConvertor(); + if (inNodeFilter.getProperties() == null || inNodeFilter.getProperties().isEmpty()) { + return retVal; + } + List<UIConstraint> constraints = inNodeFilter.getProperties().getListToscaDataDefinition().stream() + .map(property -> property.getConstraints().iterator().next()) + .map(str -> constraintConvertor.convert(str)) + .collect(Collectors.toList()); + retVal.setProperties(constraints); + return retVal; + } +} diff --git a/catalog-be/src/main/resources/config/error-configuration.yaml b/catalog-be/src/main/resources/config/error-configuration.yaml index 315027b43e..69f67e63ed 100644 --- a/catalog-be/src/main/resources/config/error-configuration.yaml +++ b/catalog-be/src/main/resources/config/error-configuration.yaml @@ -2173,6 +2173,68 @@ errors: message: "Error: Invalid input, only pre-defined operation names are allowed in global interface type '%1'", messageId: "SVC4713" } + + #---------SVC4714----------------------------- + NODE_FILTER_NOT_FOUND: { + code: 400, + message: "Error: Node Filter was not found", + messageId: "SVC4714" + } + #---------SVC4715---------------------------- + UNSUPPORTED_VALUE_PROVIDED: { + code: 400, + message: "Error: Supported value type is %1 for %2 property. Provided Value: %3", + messageId: "SVC4715" + } + #---------SVC4716---------------------------- + # %1 - Property Name + SELECTED_PROPERTY_NOT_PRESENT: { + code: 400, + message: "Error: %1 property does not exists in Service anymore.", + messageId: "SVC4716" + } + + #---------SVC4717---------------------------- + # %1 - Property Name + MAPPED_PROPERTY_NOT_FOUND: { + code: 400, + message: "Error: %1 property does not exist.", + messageId: "SVC4717" + } + + #---------SVC4718---------------------------- + # %1 - Property Name + # %2 - Operator Name + UNSUPPORTED_OPERATOR_PROVIDED: { + code: 400, + message: "Error: %1 property does not support %2 operator.", + messageId: "SVC4718" + } + + #---------SVC4719---------------------------- + CONSTRAINT_FORMAT_INCORRECT: { + code: 400, + message: "Error: Constraint provided does not contains expected values.", + messageId: "SVC4719" + } + + #---------SVC4720---------------------------- + # %1 - Property Name + # %2 - Operator Type + SOURCE_TARGET_PROPERTY_TYPE_MISMATCH: { + code: 400, + message: "Error: %1 property and %2 property type is not same.", + messageId: "SVC4720" + } + + #---------SVC4721---------------------------- + # %1 - Property Type + # %2 - Operator Type + UNSUPPORTED_PROPERTY_TYPE: { + code: 400, + message: "Error: Property type %1 provided against %2 is not supported for static value.", + messageId: "SVC4721" + } #---------SVC4714----------------------------- # %1 - Interface Operation output name INTERFACE_OPERATION_MAPPED_OUTPUT_DELETED: { diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/components/validation/NodeFilterValidationTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/components/validation/NodeFilterValidationTest.java new file mode 100644 index 0000000000..fe9827f362 --- /dev/null +++ b/catalog-be/src/test/java/org/openecomp/sdc/be/components/validation/NodeFilterValidationTest.java @@ -0,0 +1,287 @@ +package org.openecomp.sdc.be.components.validation; + +import fj.data.Either; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.mockito.InjectMocks; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; +import org.openecomp.sdc.be.components.impl.utils.NodeFilterConstraintAction; +import org.openecomp.sdc.be.dao.api.ActionStatus; +import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition; +import org.openecomp.sdc.be.datatypes.elements.SchemaDefinition; +import org.openecomp.sdc.be.impl.ComponentsUtils; +import org.openecomp.sdc.be.model.ComponentInstance; +import org.openecomp.sdc.be.model.ComponentInstanceProperty; +import org.openecomp.sdc.be.model.PropertyDefinition; +import org.openecomp.sdc.be.model.Service; +import org.openecomp.sdc.exception.ResponseFormat; + +public class NodeFilterValidationTest { + + private static final String UI_CONSTRAINT_STATIC = "Prop1: {equal: 'value'}"; + private static final String INNER_SERVICE = "innerService"; + private static final String PROPERTY_NAME = "Prop1"; + private static final String VALUE = "value"; + private static final String FLOAT_TYPE = "float"; + private static final String STRING_TYPE = "string"; + private static final String LIST_TYPE = "list"; + private static final String COMPONENT1_ID = "component1"; + private static final String INTEGER_TYPE = "integer"; + private static final String PARENTSERVICE_ID = "parentservice"; + private static final String COMPONENT2_ID = "component2"; + private ComponentsUtils componentsUtils; + + @InjectMocks + private NodeFilterValidator nodeFilterValidator; + + @Before + public void setup() { + componentsUtils = Mockito.mock(ComponentsUtils.class); + MockitoAnnotations.initMocks(this); + } + + @Test + public void testValidateNodeFilterStaticIncorrectPropertyTypeProvided() { + Service service = createService("booleanIncorrect"); + Either<Boolean, ResponseFormat> either = + nodeFilterValidator.validateNodeFilter(service, INNER_SERVICE, + Collections.singletonList(UI_CONSTRAINT_STATIC.replace(VALUE, "true")), + NodeFilterConstraintAction.ADD); + + Assert.assertFalse(either.isLeft()); + } + + @Test + public void testValidateNodeFilterStaticIncorrectOperatorProvidedBoolean() { + Service service = createService("boolean"); + Either<Boolean, ResponseFormat> either = + nodeFilterValidator.validateNodeFilter(service, INNER_SERVICE, + Collections.singletonList(UI_CONSTRAINT_STATIC.replace(VALUE, "true") + .replace("equal", "greater_than")), + NodeFilterConstraintAction.ADD); + + Assert.assertFalse(either.isLeft()); + } + + @Test + public void testValidateNodeFilterStaticIncorrectValueProvidedBoolean() { + Service service = createService("boolean"); + Either<Boolean, ResponseFormat> either = + nodeFilterValidator.validateNodeFilter(service, INNER_SERVICE, + Collections.singletonList(UI_CONSTRAINT_STATIC.replace(VALUE, "trues")), + NodeFilterConstraintAction.ADD); + + Assert.assertFalse(either.isLeft()); + } + + @Test + public void testValidateNodeFilterStaticIncorrectOperatorProvidedString() { + Service service = createService(STRING_TYPE); + Either<Boolean, ResponseFormat> either = + nodeFilterValidator.validateNodeFilter(service, INNER_SERVICE, + Collections.singletonList(UI_CONSTRAINT_STATIC.replace(VALUE, "true") + .replace("equal", "greater_than")), + NodeFilterConstraintAction.ADD); + + Assert.assertTrue(either.isLeft()); + } + + @Test + public void testValidateNodeFilterIntegerValueSuccess() { + Service service = createService(INTEGER_TYPE); + Either<Boolean, ResponseFormat> either = + nodeFilterValidator.validateNodeFilter(service, INNER_SERVICE, + Collections.singletonList(UI_CONSTRAINT_STATIC.replace(VALUE, "1")), + NodeFilterConstraintAction.ADD); + + Assert.assertTrue(either.isLeft()); + } + + @Test + public void testValidateNodeFilterIntegerValueFail() { + Service service = createService(INTEGER_TYPE); + + Mockito.when(componentsUtils.getResponseFormat(ActionStatus.UNSUPPORTED_VALUE_PROVIDED, "param1")) + .thenReturn(new ResponseFormat()); + + Either<Boolean, ResponseFormat> either = + nodeFilterValidator.validateNodeFilter(service, INNER_SERVICE, + Collections.singletonList(UI_CONSTRAINT_STATIC.replace(VALUE, "1.0")), + NodeFilterConstraintAction.ADD); + + Assert.assertTrue(either.isRight()); + } + + @Test + public void testValidateNodeFilterFloatValueSuccess() { + Service service = createService(FLOAT_TYPE); + Either<Boolean, ResponseFormat> either = + nodeFilterValidator.validateNodeFilter(service, INNER_SERVICE, + Collections.singletonList(UI_CONSTRAINT_STATIC.replace(VALUE, "1.0")), + NodeFilterConstraintAction.ADD); + + Assert.assertTrue(either.isLeft()); + } + + @Test + public void testValidateNodeFilterFloatValueFail() { + Service service = createService(FLOAT_TYPE); + + Mockito.when(componentsUtils.getResponseFormat(ActionStatus.UNSUPPORTED_VALUE_PROVIDED, "param1")) + .thenReturn(new ResponseFormat()); + + Either<Boolean, ResponseFormat> either = + nodeFilterValidator.validateNodeFilter(service, INNER_SERVICE, + Collections.singletonList(UI_CONSTRAINT_STATIC), NodeFilterConstraintAction.ADD); + + Assert.assertTrue(either.isRight()); + } + + @Test + public void testValidateNodeFilterStringValueSuccess() { + Service service = createService(STRING_TYPE); + Either<Boolean, ResponseFormat> either = + nodeFilterValidator.validateNodeFilter(service, INNER_SERVICE, + Collections.singletonList(UI_CONSTRAINT_STATIC), NodeFilterConstraintAction.ADD); + + Assert.assertTrue(either.isLeft()); + } + + @Test + public void testValidatePropertyConstraintBrotherSuccess() { + Service service = createService(STRING_TYPE); + Either<Boolean, ResponseFormat> either = + nodeFilterValidator.validateNodeFilter(service, COMPONENT1_ID, Collections.singletonList("Prop1:\n" + + " equal: { get_property :[component2, Prop1]}\n"), NodeFilterConstraintAction.ADD); + + Assert.assertTrue(either.isLeft()); + } + + @Test + public void testValidatePropertyConstraintParentSuccess() { + Service service = createService(STRING_TYPE); + Either<Boolean, ResponseFormat> either = + nodeFilterValidator.validateNodeFilter(service, COMPONENT1_ID, Collections.singletonList("Prop1:\n" + + " equal: { get_property : [parentservice, Prop1]}\n"), NodeFilterConstraintAction.ADD); + + Assert.assertTrue(either.isLeft()); + } + + @Test + public void testValidatePropertyConstraintBrotherPropertyTypeMismatch() { + Service service = createService(STRING_TYPE); + service.getComponentInstancesProperties().get(COMPONENT2_ID).get(0).setType(INTEGER_TYPE); + + Either<Boolean, ResponseFormat> either = + nodeFilterValidator.validateNodeFilter(service, COMPONENT1_ID, Collections.singletonList("Prop1:\n" + + " equal: { get_property : [component2, Prop1]}\n"), NodeFilterConstraintAction.ADD); + + Assert.assertFalse(either.isLeft()); + } + + @Test + public void testValidatePropertyConstraintParentPropertyTypeMismatch() { + Service service = createService(STRING_TYPE); + service.getComponentInstancesProperties().get(COMPONENT1_ID).get(0).setType(INTEGER_TYPE); + + Either<Boolean, ResponseFormat> either = + nodeFilterValidator.validateNodeFilter(service, COMPONENT1_ID, Collections.singletonList("Prop1:\n" + + " equal: { get_property : [parentservice, Prop1]}\n"), NodeFilterConstraintAction.ADD); + + Assert.assertFalse(either.isLeft()); + } + + @Test + public void testValidatePropertyConstraintParentPropertyNotFound() { + Service service = createService(STRING_TYPE); + service.getComponentInstancesProperties().get(COMPONENT1_ID).get(0).setName("Prop2"); + + Either<Boolean, ResponseFormat> either = + nodeFilterValidator.validateNodeFilter(service, COMPONENT1_ID, Collections.singletonList("Prop1:\n" + + " equal: { get_property : [parentservice, Prop1]}\n"), NodeFilterConstraintAction.ADD); + + Assert.assertFalse(either.isLeft()); + } + + @Test + public void testvalidatePropertyConstraintBrotherPropertyNotFound() { + Service service = createService(STRING_TYPE); + service.getComponentInstancesProperties().get(COMPONENT1_ID).get(0).setName("Prop2"); + + Either<Boolean, ResponseFormat> either = + nodeFilterValidator.validateNodeFilter(service, COMPONENT1_ID, Collections.singletonList("Prop1:\n" + + " equal: { get_property : [parentservice, Prop1]}\n"), NodeFilterConstraintAction.ADD); + + Assert.assertFalse(either.isLeft()); + } + + @Test + public void testValidatePropertyConstraintParentPropertySchemaMismatch() { + Service service = createService(LIST_TYPE,STRING_TYPE); + service.getComponentInstancesProperties().get(COMPONENT1_ID).get(0).setType(LIST_TYPE); + + Either<Boolean, ResponseFormat> either = + nodeFilterValidator.validateNodeFilter(service, COMPONENT1_ID, Collections.singletonList("Prop1:\n" + + " equal: { get_property : [parentservice, Prop1]}\n"), NodeFilterConstraintAction.ADD); + + Assert.assertFalse(either.isLeft()); + } + + private Service createService(String type) { + return createService(type, null); + } + + private Service createService(String type, String schemaType) { + Service service = new Service(); + service.setName(PARENTSERVICE_ID); + + PropertyDefinition propertyDefinition = new PropertyDefinition(); + propertyDefinition.setName(PROPERTY_NAME); + propertyDefinition.setType(type); + if (schemaType != null){ + SchemaDefinition schemaDefinition = new SchemaDefinition(); + PropertyDataDefinition schemaProperty = new PropertyDataDefinition(); + schemaProperty.setType(schemaType); + schemaDefinition.setProperty(schemaProperty); + propertyDefinition.setSchema(schemaDefinition); + } + service.setProperties(Collections.singletonList(propertyDefinition)); + + ComponentInstance componentInstance = new ComponentInstance(); + componentInstance.setUniqueId(COMPONENT1_ID); + componentInstance.setName(COMPONENT1_ID); + + ComponentInstance componentInstance2 = new ComponentInstance(); + componentInstance2.setUniqueId(COMPONENT2_ID); + componentInstance2.setName(COMPONENT2_ID); + + service.setComponentInstances(Arrays.asList(componentInstance, componentInstance2)); + + ComponentInstanceProperty componentInstanceProperty = new ComponentInstanceProperty(); + componentInstanceProperty.setName(PROPERTY_NAME); + componentInstanceProperty.setType(type); + + ComponentInstanceProperty componentInstanceProperty2 = new ComponentInstanceProperty(); + componentInstanceProperty2.setName(PROPERTY_NAME); + componentInstanceProperty2.setType(type); + + Map<String, List<ComponentInstanceProperty>> componentInstancePropertyMap = new HashMap<>(); + componentInstancePropertyMap.put(componentInstance.getUniqueId(), + Collections.singletonList(componentInstanceProperty)); + componentInstancePropertyMap.put(componentInstance2.getUniqueId(), + Collections.singletonList(componentInstanceProperty2)); + componentInstancePropertyMap.put(INNER_SERVICE, Collections.singletonList(componentInstanceProperty)); + + service.setComponentInstancesProperties(componentInstancePropertyMap); + + return service; + } + +}
\ No newline at end of file diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/tosca/model/ConstraintConvertorTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/tosca/model/ConstraintConvertorTest.java new file mode 100644 index 0000000000..942a279ec7 --- /dev/null +++ b/catalog-be/src/test/java/org/openecomp/sdc/be/tosca/model/ConstraintConvertorTest.java @@ -0,0 +1,176 @@ +/* + * Copyright © 2016-2018 European Support Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openecomp.sdc.be.tosca.model; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.util.List; +import java.util.Map; +import org.junit.Test; +import org.openecomp.sdc.be.datamodel.utils.ConstraintConvertor; +import org.openecomp.sdc.be.ui.model.UIConstraint; + +public class ConstraintConvertorTest { + + @Test + public void convertStatic(){ + ConstraintConvertor constraintConvertor = new ConstraintConvertor(); + UIConstraint uiConstraint = constraintConvertor.convert("mem_size: {equal: some static}\n"); + assertNotNull(uiConstraint); + assertEquals(uiConstraint.getConstraintOperator(),"equal"); + assertEquals(uiConstraint.getValue(),"some static"); + assertEquals(uiConstraint.getServicePropertyName().trim(),"mem_size"); + } + + @Test + public void convertFromStatic(){ + ConstraintConvertor constraintConvertor = new ConstraintConvertor(); + UIConstraint uiConstraint = new UIConstraint("mem_size", "equal" , ConstraintConvertor.STATIC_CONSTRAINT, "some static"); + String constraint = constraintConvertor.convert(uiConstraint); + assertNotNull(constraint); + assertEquals("mem_size: {equal: some static}\n", constraint); + } + + @Test + public void convertSelfProperty(){ + ConstraintConvertor constraintConvertor = new ConstraintConvertor(); + UIConstraint uiConstraint = constraintConvertor.convert("mem_size:\n {equal: { get_property: [SELF, size] }}"); + assertNotNull(uiConstraint); + assertEquals(uiConstraint.getConstraintOperator(),"equal"); + assertEquals(uiConstraint.getValue(),"size"); + assertEquals(uiConstraint.getServicePropertyName().trim(),"mem_size"); + assertEquals(uiConstraint.getSourceName().trim(),"SELF"); + assertEquals(uiConstraint.getSourceType(), ConstraintConvertor.PROPERTY_CONSTRAINT); + } + + @Test + public void convertFromSelfProperty(){ + ConstraintConvertor constraintConvertor = new ConstraintConvertor(); + UIConstraint uiConstraint = new UIConstraint("mem_size", "equal" , ConstraintConvertor.PROPERTY_CONSTRAINT, "SELF" ,"some static"); + String constraint = constraintConvertor.convert(uiConstraint); + assertNotNull(constraint); + assertEquals("mem_size:\n" + " equal:\n" + " get_property: [SELF, some static]\n", constraint); + } + + @Test + public void convertCIProperty(){ + ConstraintConvertor constraintConvertor = new ConstraintConvertor(); + UIConstraint uiConstraint = constraintConvertor.convert("mem_size:\n" + " equal: { get_property: [A, size]}"); + assertNotNull(uiConstraint); + assertEquals(uiConstraint.getConstraintOperator(),"equal"); + assertEquals(uiConstraint.getValue(),"size"); + assertEquals(uiConstraint.getServicePropertyName().trim(),"mem_size"); + assertEquals(uiConstraint.getSourceName().trim(),"A"); + } + + + @Test + public void convertFromCIProperty(){ + ConstraintConvertor constraintConvertor = new ConstraintConvertor(); + UIConstraint uiConstraint = new UIConstraint("mem_size", "equal" , ConstraintConvertor.PROPERTY_CONSTRAINT, "A" ,"size"); + String constraint = constraintConvertor.convert(uiConstraint); + assertNotNull(constraint); + assertEquals("mem_size:\n" + " equal:\n" + " get_property: [A, size]\n", constraint); + } + + @Test + public void convertServiceTemplateInput(){ + ConstraintConvertor constraintConvertor = new ConstraintConvertor(); + UIConstraint uiConstraint = constraintConvertor.convert("mem_size: {equal: {get_input: InputName}}\n"); + assertNotNull(uiConstraint); + } + + @Test + public void convertFromServiceTemplateInput(){ + ConstraintConvertor constraintConvertor = new ConstraintConvertor(); + UIConstraint uiConstraint = new UIConstraint("mem_size", "equal" , ConstraintConvertor.SERVICE_INPUT_CONSTRAINT, "InputName"); + String constraint = constraintConvertor.convert(uiConstraint); + assertNotNull(constraint); + assertEquals("mem_size:\n equal: {get_input: InputName}\n", constraint); + } + + @Test + public void convertGreaterThanStatic(){ + ConstraintConvertor constraintConvertor = new ConstraintConvertor(); + UIConstraint uiConstraint = constraintConvertor.convert("mem_size: {greater_than: 2}\n"); + assertNotNull(uiConstraint); + assertEquals(uiConstraint.getConstraintOperator(),"greater_than"); + assertEquals(uiConstraint.getValue(),2); + assertEquals(uiConstraint.getServicePropertyName().trim(),"mem_size"); + } + + @Test + public void convertFromGreaterThanStatic(){ + ConstraintConvertor constraintConvertor = new ConstraintConvertor(); + UIConstraint uiConstraint = new UIConstraint("mem_size", "greater_than" , ConstraintConvertor.STATIC_CONSTRAINT, 2); + String constraint = constraintConvertor.convert(uiConstraint); + assertNotNull(constraint); + assertEquals("mem_size: {greater_than: 2}\n", constraint); + } + + @Test + public void convertLessThanServiceProperty(){ + ConstraintConvertor constraintConvertor = new ConstraintConvertor(); + UIConstraint uiConstraint = constraintConvertor.convert("mem_size: {less_then: {get_input: InputName}}"); + assertNotNull(uiConstraint); + } + + @Test + public void convertFromLessThanServiceProperty(){ + ConstraintConvertor constraintConvertor = new ConstraintConvertor(); + UIConstraint uiConstraint = new UIConstraint("mem_size", "less_then" , ConstraintConvertor.SERVICE_INPUT_CONSTRAINT, "InputName"); + String constraint = constraintConvertor.convert(uiConstraint); + assertNotNull(constraint); + assertEquals("mem_size:\n" + " less_then: {get_input: InputName}\n", constraint); + } + + @Test + public void convertFromEqualStaticMap(){ + ConstraintConvertor constraintConvertor = new ConstraintConvertor(); + UIConstraint uiConstraint = new UIConstraint("mem_size", "equal" , ConstraintConvertor.STATIC_CONSTRAINT, "{x: xx,"+ + " y: yy}\n"); + String constraint = constraintConvertor.convert(uiConstraint); + assertNotNull(constraint); + assertEquals("mem_size:\n" + " equal: {x: xx, y: yy}\n", constraint); + } + + @Test + public void convertStringToMap(){ + ConstraintConvertor constraintConvertor = new ConstraintConvertor(); + UIConstraint uiConstraint = constraintConvertor.convert("mem_size:\n" + " equal: {x: xx, y: yy}\n"); + assertNotNull(uiConstraint); + assertTrue(uiConstraint.getValue() instanceof Map); + } + + @Test + public void convertFromEqualStaticList(){ + ConstraintConvertor constraintConvertor = new ConstraintConvertor(); + UIConstraint uiConstraint = new UIConstraint("mem_size", "equal" , ConstraintConvertor.STATIC_CONSTRAINT, "[x, y]\n"); + String constraint = constraintConvertor.convert(uiConstraint); + assertNotNull(constraint); + assertEquals("mem_size:\n" + " equal: [x, y]\n", constraint); + } + + @Test + public void convertStringToList(){ + ConstraintConvertor constraintConvertor = new ConstraintConvertor(); + UIConstraint uiConstraint = constraintConvertor.convert("mem_size:\n" + " equal: [x, y]\n"); + assertNotNull(uiConstraint); + assertTrue(uiConstraint.getValue() instanceof List); + } +} diff --git a/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/api/ActionStatus.java b/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/api/ActionStatus.java index fd6bace35e..8715e1d9c6 100644 --- a/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/api/ActionStatus.java +++ b/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/api/ActionStatus.java @@ -129,6 +129,18 @@ public enum ActionStatus { INTERFACE_OPERATION_INPUT_PROPERTY_NOT_FOUND_IN_COMPONENT, INTERFACE_OPERATION_INVALID_FOR_LOCAL_TYPE, INTERFACE_OPERATION_INVALID_FOR_GLOBAL_TYPE, + //NodeFilter + NODE_FILTER_NOT_FOUND, + UNSUPPORTED_VALUE_PROVIDED, + SELECTED_PROPERTY_NOT_PRESENT, + MAPPED_PROPERTY_NOT_FOUND, + UNSUPPORTED_OPERATOR_PROVIDED, + CONSTRAINT_FORMAT_INCORRECT, + SOURCE_TARGET_PROPERTY_TYPE_MISMATCH, + SOURCE_TARGET_SCHEMA_MISMATCH, + UNSUPPORTED_PROPERTY_TYPE, + + //InterfaceLifeCycleType INTERFACE_LIFECYCLE_TYPES_NOT_FOUND; } diff --git a/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/jsongraph/types/EdgeLabelEnum.java b/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/jsongraph/types/EdgeLabelEnum.java index c7a2f2eae7..119888b10e 100644 --- a/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/jsongraph/types/EdgeLabelEnum.java +++ b/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/jsongraph/types/EdgeLabelEnum.java @@ -63,7 +63,8 @@ public enum EdgeLabelEnum { PROXY_OF, ALLOTTED_OF, INTERFACE, - INTERFACE_OPERATION; + INTERFACE_OPERATION, + NODE_FILTER_TEMPLATE; /** * Returns EdgeLabelEnum according received name diff --git a/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/jsongraph/types/VertexTypeEnum.java b/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/jsongraph/types/VertexTypeEnum.java index aa4de11375..108d5e7201 100644 --- a/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/jsongraph/types/VertexTypeEnum.java +++ b/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/jsongraph/types/VertexTypeEnum.java @@ -60,7 +60,8 @@ public enum VertexTypeEnum { CATALOG_ROOT ("catalogRoot", null), ARCHIVE_ROOT ("archiveRoot", null), INTERFACE ("interface", InterfaceDataDefinition.class), - INTERFACE_OPERATION ("interfaceOperation", OperationDataDefinition.class); + INTERFACE_OPERATION ("interfaceOperation", OperationDataDefinition.class), + NODE_FILTER_TEMPLATE ("NodeTemplateFilter", CINodeFilterDataDefinition.class),; private String name; private Class classOfJson; diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/Component.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/Component.java index 115f084dbc..7c5368887b 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/Component.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/Component.java @@ -66,6 +66,7 @@ public abstract class Component { private String derivedFromGenericVersion; private String toscaType; protected List<AdditionalInformationDefinition> additionalInformation; + protected List<PropertyDefinition> properties; private Map<String, InterfaceDefinition> interfaces; public Map<String, InterfaceDefinition> getInterfaces() { @@ -533,6 +534,14 @@ public abstract class Component { this.policies = policies; } + public List<PropertyDefinition> getProperties() { + return properties; + } + + public void setProperties(List<PropertyDefinition> properties) { + this.properties = properties; + } + @Override public int hashCode() { final int prime = 31; @@ -555,6 +564,7 @@ public abstract class Component { result = prime * result + ((derivedFromGenericType == null) ? 0 : derivedFromGenericType.hashCode()); result = prime * result + ((derivedFromGenericVersion == null) ? 0 : derivedFromGenericVersion.hashCode()); result = prime * result + ((interfaces == null) ? 0 : interfaces.hashCode()); + result = prime * result + ((properties == null) ? 0 : properties.hashCode()); return result; } @@ -691,6 +701,9 @@ public abstract class Component { else if (!interfaces.equals(other.interfaces)) { return false; } + else if (!properties.equals(other.properties)) { + return false; + } return true; } diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/ComponentInstance.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/ComponentInstance.java index 4a622866ff..ef9b409735 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/ComponentInstance.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/ComponentInstance.java @@ -23,6 +23,7 @@ package org.openecomp.sdc.be.model; import org.openecomp.sdc.be.datatypes.elements.ComponentInstanceDataDefinition; import org.openecomp.sdc.be.datatypes.elements.PropertiesOwner; import org.openecomp.sdc.common.api.ArtifactGroupTypeEnum; +import org.openecomp.sdc.be.datatypes.elements.CINodeFilterDataDefinition; import java.util.Collections; import java.util.List; @@ -35,6 +36,7 @@ public class ComponentInstance extends ComponentInstanceDataDefinition implement private Map<String, ArtifactDefinition> deploymentArtifacts; private Map<String, ArtifactDefinition> artifacts; private List<GroupInstance> groupInstances; + private CINodeFilterDataDefinition nodeFilter; public ComponentInstance() { super(); @@ -106,4 +108,13 @@ public class ComponentInstance extends ComponentInstanceDataDefinition implement } return safeGetInformationalArtifacts().get(artifactLabel) != null; } + + public CINodeFilterDataDefinition getNodeFilter() { + return nodeFilter; + } + + public void setNodeFilter(CINodeFilterDataDefinition nodeFilter) { + this.nodeFilter = nodeFilter; + } + } diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/UploadNodeFilterCapabilitiesInfo.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/UploadNodeFilterCapabilitiesInfo.java new file mode 100644 index 0000000000..2339534266 --- /dev/null +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/UploadNodeFilterCapabilitiesInfo.java @@ -0,0 +1,40 @@ +/* + * Copyright © 2016-2018 European Support Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openecomp.sdc.be.model; + +import java.util.List; + +public class UploadNodeFilterCapabilitiesInfo { + + private String name; + private List<UploadNodeFilterPropertyInfo> properties; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public List<UploadNodeFilterPropertyInfo> getProperties() { + return properties; + } + + public void setProperties(List<UploadNodeFilterPropertyInfo> properties) { + this.properties = properties; + } +} diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/UploadNodeFilterInfo.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/UploadNodeFilterInfo.java new file mode 100644 index 0000000000..2b228d930c --- /dev/null +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/UploadNodeFilterInfo.java @@ -0,0 +1,62 @@ +/* + * Copyright © 2016-2018 European Support Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.openecomp.sdc.be.model; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class UploadNodeFilterInfo { + + private String name; + private Object tosca_id; + private List<UploadNodeFilterPropertyInfo> properties = new ArrayList<>(); + private Map<String, UploadNodeFilterCapabilitiesInfo> capabilities = new HashMap<>(); + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public List<UploadNodeFilterPropertyInfo> getProperties() { + return properties; + } + + public void setProperties(List<UploadNodeFilterPropertyInfo> properties) { + this.properties = properties; + } + + public Map<String, UploadNodeFilterCapabilitiesInfo> getCapabilities() { + return capabilities; + } + + public void setCapabilities(Map<String, UploadNodeFilterCapabilitiesInfo> capabilities) { + this.capabilities = capabilities; + } + + public Object getTosca_id() { + return tosca_id; + } + + public void setTosca_id(Object tosca_id) { + this.tosca_id = tosca_id; + } +} diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/UploadNodeFilterPropertyInfo.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/UploadNodeFilterPropertyInfo.java new file mode 100644 index 0000000000..ea94ca23e4 --- /dev/null +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/UploadNodeFilterPropertyInfo.java @@ -0,0 +1,48 @@ +/* + * Copyright © 2016-2018 European Support Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openecomp.sdc.be.model; + +import java.util.List; + +public class UploadNodeFilterPropertyInfo { + + private String name; + private List<String> values; + + public UploadNodeFilterPropertyInfo() { + } + + public UploadNodeFilterPropertyInfo(String name, List<String> value) { + this.name = name; + this.values = value; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public List<String> getValues() { + return values; + } + + public void setValue(List<String> values) { + this.values = values; + } +} diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/NodeFilterOperation.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/NodeFilterOperation.java new file mode 100644 index 0000000000..989708c8d6 --- /dev/null +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/NodeFilterOperation.java @@ -0,0 +1,179 @@ +/*- + * ============LICENSE_START======================================================= + * SDC + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdc.be.model.jsontitan.operations; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Sets; +import fj.data.Either; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Set; +import org.openecomp.sdc.be.dao.jsongraph.GraphVertex; +import org.openecomp.sdc.be.dao.jsongraph.types.EdgeLabelEnum; +import org.openecomp.sdc.be.dao.jsongraph.types.JsonParseFlagEnum; +import org.openecomp.sdc.be.dao.jsongraph.types.VertexTypeEnum; +import org.openecomp.sdc.be.dao.titan.TitanOperationStatus; +import org.openecomp.sdc.be.datatypes.elements.CINodeFilterDataDefinition; +import org.openecomp.sdc.be.datatypes.elements.ListDataDefinition; +import org.openecomp.sdc.be.datatypes.elements.RequirementNodeFilterPropertyDataDefinition; +import org.openecomp.sdc.be.datatypes.enums.JsonPresentationFields; +import org.openecomp.sdc.be.model.Service; +import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus; +import org.openecomp.sdc.be.model.operations.impl.DaoStatusConverter; +import org.openecomp.sdc.common.jsongraph.util.CommonUtility; +import org.openecomp.sdc.common.log.elements.LoggerFactory; +import org.openecomp.sdc.common.log.wrappers.Logger; + +@org.springframework.stereotype.Component("service-filter-operations") +public class NodeFilterOperation extends BaseOperation { + + private static Logger logger = LoggerFactory.getLogger(NodeFilterOperation.class, + org.slf4j.LoggerFactory.getLogger(NodeFilterOperation.class)); + + public Either<Set<String>, StorageOperationStatus> deleteNodeFilters(Service service, + Set<String> componentInstanceIds) { + Either<GraphVertex, TitanOperationStatus> getComponentVertex; + Either<GraphVertex, TitanOperationStatus> getNodeFilterVertex; + StorageOperationStatus status; + + getComponentVertex = titanDao.getVertexById(service.getUniqueId(), JsonParseFlagEnum.NoParse); + if (getComponentVertex.isRight()) { + return Either.right( + DaoStatusConverter.convertTitanStatusToStorageStatus(getComponentVertex.right().value())); + } + + getNodeFilterVertex = + titanDao.getChildVertex(getComponentVertex.left().value(), EdgeLabelEnum.NODE_FILTER_TEMPLATE, + JsonParseFlagEnum.NoParse); + if (getNodeFilterVertex.isLeft()) { + status = deleteToscaDataElements(service.getUniqueId(), EdgeLabelEnum.NODE_FILTER_TEMPLATE, + new ArrayList<>(componentInstanceIds)); + if (status != StorageOperationStatus.OK) { + return Either.right(status); + } + } + + return Either.left(componentInstanceIds); + } + + + public Either<String, StorageOperationStatus> deleteNodeFilter(Service service, String componentInstanceId) { + final Either<Set<String>, StorageOperationStatus> listStorageOperationStatusEither = + deleteNodeFilters(service, ImmutableSet.of(componentInstanceId)); + if (listStorageOperationStatusEither.isRight()) { + return Either.right(listStorageOperationStatusEither.right().value()); + } + return Either.left(componentInstanceId); + } + + + public Either<CINodeFilterDataDefinition, StorageOperationStatus> createNodeFilter(String serviceId, + String componentInstanceId) { + CINodeFilterDataDefinition nodeFilterDataDefinition = new CINodeFilterDataDefinition(); + return addOrUpdateNodeFilter(false, serviceId, componentInstanceId, nodeFilterDataDefinition); + } + + public Either<CINodeFilterDataDefinition, StorageOperationStatus> deleteConstraint(String serviceId, + String componentInstanceId, CINodeFilterDataDefinition nodeFilterDataDefinition, int propertyIndex) { + ListDataDefinition<RequirementNodeFilterPropertyDataDefinition> properties = + nodeFilterDataDefinition.getProperties(); + properties.getListToscaDataDefinition().remove(propertyIndex); + nodeFilterDataDefinition.setProperties(properties); + return addOrUpdateNodeFilter(true, serviceId, componentInstanceId, nodeFilterDataDefinition); + } + + public Either<CINodeFilterDataDefinition, StorageOperationStatus> addNewProperty(String serviceId, + String componentInstanceId, CINodeFilterDataDefinition nodeFilterDataDefinition, + RequirementNodeFilterPropertyDataDefinition requirementNodeFilterPropertyDataDefinition) { + ListDataDefinition<RequirementNodeFilterPropertyDataDefinition> properties = + nodeFilterDataDefinition.getProperties(); + if (properties == null) { + properties = new ListDataDefinition<>(); + nodeFilterDataDefinition.setProperties(properties); + } + properties.getListToscaDataDefinition().add(requirementNodeFilterPropertyDataDefinition); + nodeFilterDataDefinition.setProperties(properties); + return addOrUpdateNodeFilter(true, serviceId, componentInstanceId, nodeFilterDataDefinition); + } + + public Either<CINodeFilterDataDefinition, StorageOperationStatus> updateProperties(String serviceId, + String componentInstanceId, CINodeFilterDataDefinition nodeFilterDataDefinition, + List<RequirementNodeFilterPropertyDataDefinition> requirementNodeFilterPropertyDataDefinition) { + ListDataDefinition<RequirementNodeFilterPropertyDataDefinition> properties = + nodeFilterDataDefinition.getProperties(); + properties.getListToscaDataDefinition().clear(); + properties.getListToscaDataDefinition().addAll(requirementNodeFilterPropertyDataDefinition); + nodeFilterDataDefinition.setProperties(properties); + return addOrUpdateNodeFilter(true, serviceId, componentInstanceId, nodeFilterDataDefinition); + } + + public Either<CINodeFilterDataDefinition, StorageOperationStatus> updateNodeFilter(String serviceId, + String componentInstanceId, CINodeFilterDataDefinition ciNodeFilterDataDefinition) { + return addOrUpdateNodeFilter(true, serviceId, componentInstanceId, ciNodeFilterDataDefinition); + } + + private Either<CINodeFilterDataDefinition, StorageOperationStatus> addOrUpdateNodeFilter(boolean isUpdateAction, + String serviceId, String componentInstanceId, CINodeFilterDataDefinition ciNodeFilterDataDefinition) { + + StorageOperationStatus statusRes; + Either<GraphVertex, TitanOperationStatus> getToscaElementRes; + + getToscaElementRes = titanDao.getVertexById(serviceId, JsonParseFlagEnum.NoParse); + if (getToscaElementRes.isRight()) { + TitanOperationStatus status = getToscaElementRes.right().value(); + CommonUtility.addRecordToLog(logger, CommonUtility.LogLevelEnum.DEBUG, + "Failed to get tosca element {} upon adding the properties. Status is {}. ", serviceId, status); + statusRes = DaoStatusConverter.convertTitanStatusToStorageStatus(status); + return Either.right(statusRes); + } + GraphVertex serviceVertex = getToscaElementRes.left().value(); + ciNodeFilterDataDefinition.setID(componentInstanceId); + statusRes = performUpdateToscaAction(isUpdateAction, serviceVertex, ImmutableList.of(ciNodeFilterDataDefinition)); + if (!statusRes.equals(StorageOperationStatus.OK)) { + titanDao.rollback(); + logger.error( + " Failed to perform tosca update for node filter in service {} , component instance {}. status is {}", + serviceId, componentInstanceId, statusRes); + return Either.right(statusRes); + } + titanDao.commit(); + return Either.left(ciNodeFilterDataDefinition); + + } + + + private StorageOperationStatus performUpdateToscaAction(boolean isUpdate, GraphVertex graphVertex, + List<CINodeFilterDataDefinition> toscaDataList) { + if (isUpdate) { + return updateToscaDataOfToscaElement(graphVertex, EdgeLabelEnum.NODE_FILTER_TEMPLATE, + VertexTypeEnum.NODE_FILTER_TEMPLATE, toscaDataList, JsonPresentationFields.UNIQUE_ID); + } else { + return addToscaDataToToscaElement(graphVertex, EdgeLabelEnum.NODE_FILTER_TEMPLATE, + VertexTypeEnum.NODE_FILTER_TEMPLATE, toscaDataList, JsonPresentationFields.UNIQUE_ID); + } + } + +} + + + diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/constraints/ConstraintType.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/constraints/ConstraintType.java index c78afd8b4a..6fb699124a 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/constraints/ConstraintType.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/constraints/ConstraintType.java @@ -25,6 +25,8 @@ import java.util.List; public enum ConstraintType { + EQUAL("equal", "equal"), + IN_RANGE("inRange"), GREATER_THAN("greaterThan", "greater_than"), diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/ui/model/UIConstraint.java b/catalog-model/src/main/java/org/openecomp/sdc/be/ui/model/UIConstraint.java new file mode 100644 index 0000000000..63353c167d --- /dev/null +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/ui/model/UIConstraint.java @@ -0,0 +1,117 @@ +/* + * Copyright © 2016-2018 European Support Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.openecomp.sdc.be.ui.model; + +import com.google.common.base.MoreObjects; +import com.google.common.base.Objects; +import java.io.Serializable; + +public class UIConstraint implements Serializable { + + private String servicePropertyName; + private String constraintOperator; + private String sourceType; + private String sourceName; + private Object value; + + public UIConstraint() { + } + + public UIConstraint(String servicePropertyName, String constraintOperator, String sourceType, Object value) { + this.servicePropertyName = servicePropertyName; + this.constraintOperator = constraintOperator; + this.sourceType = sourceType; + this.value = value; + } + + public UIConstraint(String servicePropertyName, String constraintOperator, String sourceType, String sourceName, + Object value) { + this.servicePropertyName = servicePropertyName; + this.constraintOperator = constraintOperator; + this.sourceType = sourceType; + this.sourceName = sourceName; + this.value = value; + } + + public String getServicePropertyName() { + return servicePropertyName; + } + + public void setServicePropertyName(String servicePropertyName) { + this.servicePropertyName = servicePropertyName; + } + + public String getConstraintOperator() { + return constraintOperator; + } + + public void setConstraintOperator(String constraintOperator) { + this.constraintOperator = constraintOperator; + } + + public String getSourceType() { + return sourceType; + } + + public void setSourceType(String sourceType) { + this.sourceType = sourceType; + } + + public Object getValue() { + return value; + } + + public void setValue(Object value) { + this.value = value; + } + + public String getSourceName() { + return sourceName; + } + + public void setSourceName(String sourceName) { + this.sourceName = sourceName; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof UIConstraint)) { + return false; + } + UIConstraint that = (UIConstraint) o; + return Objects.equal(getServicePropertyName(), that.getServicePropertyName()) && Objects.equal( + getConstraintOperator(), that.getConstraintOperator()) && Objects.equal(getSourceType(), + that.getSourceType()) && Objects.equal(getSourceName(), that.getSourceName()) && Objects.equal( + getValue(), that.getValue()); + } + + @Override + public int hashCode() { + return Objects.hashCode(getServicePropertyName(), getConstraintOperator(), getSourceType(), getSourceName(), + getValue()); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this).add("servicePropertyName", servicePropertyName) + .add("constraintOperator", constraintOperator).add("sourceType", sourceType) + .add("sourceName", sourceName).add("value", value).toString(); + } +} diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/ui/model/UINodeFilter.java b/catalog-model/src/main/java/org/openecomp/sdc/be/ui/model/UINodeFilter.java new file mode 100644 index 0000000000..16ce3a837b --- /dev/null +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/ui/model/UINodeFilter.java @@ -0,0 +1,31 @@ +/* + * Copyright © 2016-2018 European Support Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openecomp.sdc.be.ui.model; + +import java.util.List; + +public class UINodeFilter { + + private List<UIConstraint> properties; + + public List<UIConstraint> getProperties() { + return properties; + } + + public void setProperties(List<UIConstraint> properties) { + this.properties = properties; + } +} diff --git a/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/CINodeFilterDataDefinition.java b/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/CINodeFilterDataDefinition.java new file mode 100644 index 0000000000..ffad1a4c16 --- /dev/null +++ b/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/CINodeFilterDataDefinition.java @@ -0,0 +1,81 @@ +/* + * Copyright © 2016-2018 European Support Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openecomp.sdc.be.datatypes.elements; + +import com.fasterxml.jackson.annotation.JsonCreator; +import java.io.Serializable; +import org.openecomp.sdc.be.datatypes.enums.JsonPresentationFields; +import org.openecomp.sdc.be.datatypes.tosca.ToscaDataDefinition; + +public class CINodeFilterDataDefinition extends ToscaDataDefinition implements Serializable { + + @JsonCreator + public CINodeFilterDataDefinition() { + } + + public CINodeFilterDataDefinition(CINodeFilterDataDefinition inData){ + super(); + this.setID(inData.getID()); + this.setName(inData.getName()); + this.setTosca_id(inData.getTosca_id()); + this.setProperties(inData.getProperties()); + this.setCapabilities(inData.getCapabilities()); + } + + public void setTosca_id(Object tosca_id) { + setToscaPresentationValue(JsonPresentationFields.TOSCA_ID, tosca_id); + } + + public Object getTosca_id() { + return getToscaPresentationValue(JsonPresentationFields.TOSCA_ID); + } + + public ListDataDefinition<RequirementNodeFilterPropertyDataDefinition> getProperties() { + return (ListDataDefinition<RequirementNodeFilterPropertyDataDefinition>) getToscaPresentationValue( + JsonPresentationFields.PROPERTIES); + } + + public void setProperties(ListDataDefinition<RequirementNodeFilterPropertyDataDefinition> properties) { + setToscaPresentationValue(JsonPresentationFields.PROPERTIES, properties); + } + + public ListDataDefinition<RequirementNodeFilterCapabilityDataDefinition> getCapabilities() { + return (ListDataDefinition<RequirementNodeFilterCapabilityDataDefinition>) getToscaPresentationValue( + JsonPresentationFields.NODE_FILTER_CAPABILITIES); + } + + public void setCapabilities(ListDataDefinition<RequirementNodeFilterCapabilityDataDefinition> capabilities) { + setToscaPresentationValue(JsonPresentationFields.NODE_FILTER_CAPABILITIES, capabilities); + } + + public String getName() { + return (String) getToscaPresentationValue(JsonPresentationFields.NAME); + } + + public void setName(String name) { + setToscaPresentationValue(JsonPresentationFields.NAME, name); + } + + public String getID() { + return (String) getToscaPresentationValue(JsonPresentationFields.UNIQUE_ID); + } + + public void setID(String name) { + setToscaPresentationValue(JsonPresentationFields.UNIQUE_ID, name); + } + + +} diff --git a/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/RequirementNodeFilterCapabilityDataDefinition.java b/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/RequirementNodeFilterCapabilityDataDefinition.java new file mode 100644 index 0000000000..3df0f28162 --- /dev/null +++ b/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/RequirementNodeFilterCapabilityDataDefinition.java @@ -0,0 +1,47 @@ +/* + * Copyright © 2016-2018 European Support Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.openecomp.sdc.be.datatypes.elements; + +import java.io.Serializable; +import org.openecomp.sdc.be.datatypes.enums.JsonPresentationFields; +import org.openecomp.sdc.be.datatypes.tosca.ToscaDataDefinition; + +public class RequirementNodeFilterCapabilityDataDefinition extends ToscaDataDefinition implements Serializable { + + /** + * Default Constructor + */ + public RequirementNodeFilterCapabilityDataDefinition() { + } + + public String getName() { + return (String) getToscaPresentationValue(JsonPresentationFields.NAME); + } + + public void setName(String name) { + setToscaPresentationValue(JsonPresentationFields.NAME, name); + } + + public ListDataDefinition<RequirementNodeFilterPropertyDataDefinition> getProperties() { + return (ListDataDefinition<RequirementNodeFilterPropertyDataDefinition>) getToscaPresentationValue( + JsonPresentationFields.PROPERTIES); + } + + public void setProperties(ListDataDefinition<RequirementNodeFilterPropertyDataDefinition> properties) { + setToscaPresentationValue(JsonPresentationFields.PROPERTIES, properties); + } +} diff --git a/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/RequirementNodeFilterPropertyDataDefinition.java b/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/RequirementNodeFilterPropertyDataDefinition.java new file mode 100644 index 0000000000..1ee33eeafe --- /dev/null +++ b/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/RequirementNodeFilterPropertyDataDefinition.java @@ -0,0 +1,41 @@ +/* + * Copyright © 2016-2018 European Support Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openecomp.sdc.be.datatypes.elements; + +import java.io.Serializable; +import java.util.List; +import org.openecomp.sdc.be.datatypes.enums.JsonPresentationFields; +import org.openecomp.sdc.be.datatypes.tosca.ToscaDataDefinition; + +public class RequirementNodeFilterPropertyDataDefinition extends ToscaDataDefinition implements Serializable { + + + public List<String> getConstraints() { + return (List<String>) getToscaPresentationValue(JsonPresentationFields.PROPERTY_FILTER_CONSTRAINT); + } + + public void setConstraints(List<String> constraints) { + setToscaPresentationValue(JsonPresentationFields.PROPERTY_FILTER_CONSTRAINT, constraints); + } + + public String getName() { + return (String) getToscaPresentationValue(JsonPresentationFields.PROPERTY_FILTER_NAME); + } + + public void setName(String name) { + setToscaPresentationValue(JsonPresentationFields.PROPERTY_FILTER_NAME, name); + } +} diff --git a/common-be/src/main/java/org/openecomp/sdc/be/datatypes/enums/ComponentFieldsEnum.java b/common-be/src/main/java/org/openecomp/sdc/be/datatypes/enums/ComponentFieldsEnum.java index db0735a5c0..abc426cf85 100644 --- a/common-be/src/main/java/org/openecomp/sdc/be/datatypes/enums/ComponentFieldsEnum.java +++ b/common-be/src/main/java/org/openecomp/sdc/be/datatypes/enums/ComponentFieldsEnum.java @@ -44,6 +44,7 @@ public enum ComponentFieldsEnum { FORWARDING_PATHS("forwardingPaths"), POLICIES("policies"), NON_EXCLUDED_POLICIES("nonExcludedPolicies"), + NODE_FILTER("nodeFilter") ; diff --git a/common-be/src/main/java/org/openecomp/sdc/be/datatypes/enums/JsonPresentationFields.java b/common-be/src/main/java/org/openecomp/sdc/be/datatypes/enums/JsonPresentationFields.java index 40d6a70110..6829c72cb4 100644 --- a/common-be/src/main/java/org/openecomp/sdc/be/datatypes/enums/JsonPresentationFields.java +++ b/common-be/src/main/java/org/openecomp/sdc/be/datatypes/enums/JsonPresentationFields.java @@ -136,6 +136,15 @@ public enum JsonPresentationFields { REQUIREMENT_ID("requirementId", null), PARENT_NAME("parentName", null), PREVIOUS_NAME("previousName", null), + NODE_FILTER_CAPABILITIES("capabilities",null), + PROPERTY_FILTER_NAME("propertyName",null), + PROPERTY_FILTER_CONSTRAINT("propertyFilterConstraint",null), + EQUAL_CONSTRAINT("equal",null), + CONSTRAINT_VALUE("constraintValue",null), + CONSTRAINT_FUNCTION("constraintFunction",null), + NODE_FILTER("nodeFilter",null), + TOSCA_ID("tosca_id",null), + //Relation CAPABILTY_OWNER_ID("capabilityOwnerId", null), REQUIREMENT_OWNER_ID("requirementOwnerId", null), |