/*- * ============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.components.impl; import com.google.gson.JsonElement; import fj.data.Either; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.ImmutablePair; import org.openecomp.sdc.be.components.validation.UserValidations; import org.openecomp.sdc.be.config.BeEcompErrorManager; import org.openecomp.sdc.be.config.BeEcompErrorManager.ErrorSeverity; import org.openecomp.sdc.be.dao.api.ActionStatus; import org.openecomp.sdc.be.dao.jsongraph.TitanDao; import org.openecomp.sdc.be.dao.titan.TitanGenericDao; import org.openecomp.sdc.be.dao.titan.TitanOperationStatus; import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition; import org.openecomp.sdc.be.datatypes.elements.PropertyRule; import org.openecomp.sdc.be.datatypes.elements.SchemaDefinition; import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum; import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum; import org.openecomp.sdc.be.impl.ComponentsUtils; import org.openecomp.sdc.be.model.*; import org.openecomp.sdc.be.model.cache.ApplicationDataTypeCache; import org.openecomp.sdc.be.model.jsontitan.operations.ArtifactsOperations; import org.openecomp.sdc.be.model.jsontitan.operations.ForwardingPathOperation; import org.openecomp.sdc.be.model.jsontitan.operations.ToscaOperationFacade; import org.openecomp.sdc.be.model.operations.api.IElementOperation; import org.openecomp.sdc.be.model.operations.api.IGraphLockOperation; import org.openecomp.sdc.be.model.operations.api.IGroupInstanceOperation; import org.openecomp.sdc.be.model.operations.api.IGroupOperation; import org.openecomp.sdc.be.model.operations.api.IGroupTypeOperation; import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus; import org.openecomp.sdc.be.model.operations.impl.DaoStatusConverter; import org.openecomp.sdc.be.model.operations.impl.PolicyTypeOperation; import org.openecomp.sdc.be.model.operations.impl.PropertyOperation; import org.openecomp.sdc.be.model.operations.utils.ComponentValidationUtils; import org.openecomp.sdc.be.model.tosca.ToscaPropertyType; import org.openecomp.sdc.be.model.tosca.converters.PropertyValueConverter; import org.openecomp.sdc.be.model.tosca.validators.DataTypeValidatorConverter; import org.openecomp.sdc.be.model.tosca.validators.PropertyTypeValidator; import org.openecomp.sdc.be.resources.data.PropertyValueData; import org.openecomp.sdc.be.user.IUserBusinessLogic; import org.openecomp.sdc.be.user.Role; import org.openecomp.sdc.be.user.UserBusinessLogic; import org.openecomp.sdc.common.api.Constants; import org.openecomp.sdc.common.datastructure.Wrapper; import org.openecomp.sdc.common.util.ValidationUtils; import org.openecomp.sdc.exception.ResponseFormat; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.function.Function; import static org.apache.commons.collections.CollectionUtils.isEmpty; public abstract class BaseBusinessLogic { private static final Logger log = LoggerFactory.getLogger(BaseBusinessLogic.class); private static final String EMPTY_VALUE = null; @Autowired protected ComponentsUtils componentsUtils; @Autowired protected IUserBusinessLogic userAdmin; @Autowired protected IGraphLockOperation graphLockOperation; @Autowired protected TitanDao titanDao; @Autowired protected TitanGenericDao titanGenericDao; @Autowired protected IElementOperation elementDao; @Autowired protected IGroupOperation groupOperation; @Autowired protected IGroupInstanceOperation groupInstanceOperation; @Autowired protected IGroupTypeOperation groupTypeOperation; @Autowired protected GroupBusinessLogic groupBusinessLogic; @Autowired protected PolicyTypeOperation policyTypeOperation; @javax.annotation.Resource protected ArtifactsOperations artifactToscaOperation; @Autowired protected PropertyOperation propertyOperation; @Autowired protected ApplicationDataTypeCache applicationDataTypeCache; @Autowired protected ToscaOperationFacade toscaOperationFacade; @Autowired protected ApplicationDataTypeCache dataTypeCache; @Autowired protected ForwardingPathOperation forwardingPathOperation; @javax.annotation.Resource private UserValidations userValidations; protected DataTypeValidatorConverter dataTypeValidatorConverter = DataTypeValidatorConverter.getInstance(); public void setUserAdmin(UserBusinessLogic userAdmin) { this.userAdmin = userAdmin; } public void setUserValidations(UserValidations userValidations) { this.userValidations = userValidations; } public void setComponentsUtils(ComponentsUtils componentsUtils) { this.componentsUtils = componentsUtils; } public void setGraphLockOperation(IGraphLockOperation graphLockOperation) { this.graphLockOperation = graphLockOperation; } public void setToscaOperationFacade(ToscaOperationFacade toscaOperationFacade) { this.toscaOperationFacade = toscaOperationFacade; } public void setForwardingPathOperation(ForwardingPathOperation forwardingPathOperation){ this.forwardingPathOperation = forwardingPathOperation; } public void setPolicyTypeOperation(PolicyTypeOperation policyTypeOperation) { this.policyTypeOperation = policyTypeOperation; } public void setDataTypeCache(ApplicationDataTypeCache dataTypeCache) { this.dataTypeCache = dataTypeCache; } public void setPropertyOperation(PropertyOperation propertyOperation) { this.propertyOperation = propertyOperation; } protected Either validateUserNotEmpty(User user, String ecompErrorContext) { return userValidations.validateUserNotEmpty(user, ecompErrorContext); } protected Either validateUserExists(User user, String ecompErrorContext, boolean inTransaction) { return userValidations.validateUserExists(user.getUserId(), ecompErrorContext, inTransaction); } protected void validateUserExist(String userId, String ecompErrorContext, Wrapper errorWrapper) { userValidations.validateUserExist(userId, ecompErrorContext, errorWrapper); } public Either validateUserExistsActionStatus(String userId, String ecompErrorContext) { return userValidations.validateUserExistsActionStatus(userId, ecompErrorContext); } public Either validateUserExists(String userId, String ecompErrorContext, boolean inTransaction) { return userValidations.validateUserExists(userId, ecompErrorContext, inTransaction); } protected Either validateUserRole(User user, List roles) { return userValidations.validateUserRole(user, roles); } protected Either lockComponent(Component component, String ecompErrorContext) { return lockComponent(component.getUniqueId(), component, ecompErrorContext); } protected Either lockComponent(Component component, boolean shoulLock, String ecompErrorContext) { return shoulLock ? lockComponent(component.getUniqueId(), component, ecompErrorContext) .either(l -> Either.left(component), Either::right) : Either.left(component); } protected Either lockComponent(String componentId, Component component, String ecompErrorContext) { ComponentTypeEnum componentType = component.getComponentType(); NodeTypeEnum nodeType = componentType.getNodeType(); StorageOperationStatus lockResourceStatus = graphLockOperation.lockComponent(componentId, nodeType); if (lockResourceStatus.equals(StorageOperationStatus.OK)) { return Either.left(true); } else { BeEcompErrorManager.getInstance().logBeFailedLockObjectError(ecompErrorContext, nodeType.getName(), componentId); ActionStatus actionStatus = componentsUtils.convertFromStorageResponse(lockResourceStatus, componentType); ResponseFormat responseFormat = componentsUtils.getResponseFormat(actionStatus, component.getName()); log.debug("Failed to lock component {} error - {}", componentId, actionStatus); return Either.right(responseFormat); } } protected void unlockComponent(Either either, Component component, boolean inTransaction) { ComponentTypeEnum componentType = component.getComponentType(); NodeTypeEnum nodeType = componentType.getNodeType(); if (!inTransaction) { if (either == null || either.isRight()) { titanDao.rollback(); } else { titanDao.commit(); } } // unlock resource graphLockOperation.unlockComponent(component.getUniqueId(), nodeType); } protected void unlockComponent(Either either, Component component) { unlockComponent(either, component, false); } protected void unlockComponentById(Either either, String componentId) { Either component = toscaOperationFacade.getToscaElement(componentId); if(component.isLeft() && component != null) { unlockComponent(either, component.left().value(), false); } } protected Either validateJsonBody(T bodyObject, Class clazz) { if (bodyObject == null) { log.debug("Invalid JSON received for object of type {}", clazz.getSimpleName()); return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT)); } else { return Either.left(true); } } protected Either validateComponentType(String componentType) { ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(componentType); if (componentTypeEnum == null) { log.debug("Invalid component type {}", componentType); return Either.right(componentsUtils.getResponseFormat(ActionStatus.UNSUPPORTED_ERROR, componentType)); } else { return Either.left(componentTypeEnum); } } protected Either validateComponentExists(String componentId, ComponentTypeEnum componentType, ComponentParametersView filter) { if (filter == null) { filter = new ComponentParametersView(); } return toscaOperationFacade.getToscaElement(componentId, filter) .right() .map(err -> handleGetComponentError(componentId, componentType, err)) .left() .bind(cmpt -> validateComponentType(cmpt, componentType)); } private Either validateComponentType(Component cmpt, ComponentTypeEnum componentType) { if (componentType != cmpt.getComponentType()) { log.debug("component {} is not of requested type {}", cmpt.getUniqueId(), componentType); ActionStatus cmptNotFoundError = componentsUtils.convertFromStorageResponse(StorageOperationStatus.NOT_FOUND, componentType); return Either.right(componentsUtils.getResponseFormat(cmptNotFoundError)); } return Either.left(cmpt); } protected Either updatePropertyObjectValue(T property, boolean isInput) { Either, TitanOperationStatus> allDataTypesEither = dataTypeCache.getAll(); if (allDataTypesEither.isRight()) { TitanOperationStatus status = allDataTypesEither.right().value(); BeEcompErrorManager.getInstance().logInternalFlowError("UpdatePropertyValueOnComponentInstance", "Failed to update property value on instance. Status is " + status, ErrorSeverity.ERROR); return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(DaoStatusConverter.convertTitanStatusToStorageStatus(status)))); } Map allDataTypes = allDataTypesEither.left().value(); String innerType = null; String propertyType = property.getType(); ToscaPropertyType type = ToscaPropertyType.isValidType(propertyType); log.debug("The type of the property {} is {}", property.getUniqueId(), propertyType); if (type == ToscaPropertyType.LIST || type == ToscaPropertyType.MAP) { SchemaDefinition def = property.getSchema(); if (def == null) { log.debug("Schema doesn't exists for property of type {}", type); return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(StorageOperationStatus.INVALID_VALUE))); } PropertyDataDefinition propDef = def.getProperty(); if (propDef == null) { log.debug("Property in Schema Definition inside property of type {} doesn't exist", type); return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(StorageOperationStatus.INVALID_VALUE))); } innerType = propDef.getType(); } // Specific Update Logic Either isValid = propertyOperation.validateAndUpdatePropertyValue(propertyType, property.getValue(), true, innerType, allDataTypes); String newValue = property.getValue(); if (isValid.isRight()) { Boolean res = isValid.right().value(); if (Boolean.FALSE.equals(res)) { return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(DaoStatusConverter.convertTitanStatusToStorageStatus(TitanOperationStatus.ILLEGAL_ARGUMENT)))); } } else { Object object = isValid.left().value(); if (object != null) { newValue = object.toString(); } } if (!isInput) { ImmutablePair pair = propertyOperation.validateAndUpdateRules(propertyType, ((ComponentInstanceProperty) property).getRules(), innerType, allDataTypes, true); if (Boolean.FALSE.equals(pair.getRight())) { BeEcompErrorManager.getInstance().logBeInvalidValueError("Add property value", pair.getLeft(), property.getName(), propertyType); return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(DaoStatusConverter.convertTitanStatusToStorageStatus(TitanOperationStatus.ILLEGAL_ARGUMENT)))); } } return Either.left(newValue); } public Either validateCanWorkOnComponent(Component component, String userId) { Either canWork = Either.right(componentsUtils.getResponseFormat(ActionStatus.RESTRICTED_OPERATION)); if (component.getLifecycleState() != LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT) { log.debug("Component {} is not checked-out", component.getName()); return canWork; } // verify userId is not null if (userId == null) { log.debug("Current user userId is null"); return canWork; } // verify component last update user is the current user String lastUpdaterUserId = component.getLastUpdaterUserId(); if (!userId.equals(lastUpdaterUserId)) { log.debug("Current user is not last updater, last updater userId: {}, current user userId: {}", lastUpdaterUserId, userId); return canWork; } // verify resource is not deleted if (Boolean.TRUE.equals(component.getIsDeleted())) { log.debug("Component {} is marked as deleted", component.getUniqueId()); return canWork; } return Either.left(true); } public ComponentTypeEnum getComponentTypeByParentComponentType(ComponentTypeEnum parentComponentType) { switch (parentComponentType) { case SERVICE: return ComponentTypeEnum.RESOURCE; case RESOURCE: return ComponentTypeEnum.RESOURCE; case PRODUCT: return ComponentTypeEnum.SERVICE; default: break; } return null; } // For UT public void setTitanGenericDao(TitanDao titanDao) { this.titanDao = titanDao; } protected Either, ResponseFormat> getAllDataTypes(ApplicationDataTypeCache applicationDataTypeCache) { Either, TitanOperationStatus> allDataTypes = applicationDataTypeCache.getAll(); if (allDataTypes.isRight()) { TitanOperationStatus operationStatus = allDataTypes.right().value(); if (operationStatus == TitanOperationStatus.NOT_FOUND) { BeEcompErrorManager.getInstance().logInternalDataError("FetchDataTypes", "Data types are not loaded", ErrorSeverity.ERROR); return Either.right(componentsUtils.getResponseFormat(ActionStatus.DATA_TYPE_CANNOT_BE_EMPTY)); } else { BeEcompErrorManager.getInstance().logInternalFlowError("FetchDataTypes", "Failed to fetch data types", ErrorSeverity.ERROR); return Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR)); } } return Either.left(allDataTypes.left().value()); } protected Either validatePropertyDefaultValue(IComplexDefaultValue property, Map dataTypes) { String type = null; String innerType = null; if (!propertyOperation.isPropertyTypeValid(property)) { log.info("Invalid type for property {} type {}", property.getName(), property.getType()); ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_PROPERTY_TYPE, property.getType(), property.getName()); return Either.right(responseFormat); } type = property.getType(); if (type.equals(ToscaPropertyType.LIST.getType()) || type.equals(ToscaPropertyType.MAP.getType())) { ImmutablePair propertyInnerTypeValid = propertyOperation.isPropertyInnerTypeValid(property, dataTypes); innerType = propertyInnerTypeValid.getLeft(); if (!propertyInnerTypeValid.getRight().booleanValue()) { log.info("Invalid inner type for property {} type {}", property.getName(), property.getType()); ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_PROPERTY_INNER_TYPE, innerType, property.getName()); return Either.right(responseFormat); } } if (!propertyOperation.isPropertyDefaultValueValid(property, dataTypes)) { log.info("Invalid default value for property {} type {}", property.getName(), property.getType()); ResponseFormat responseFormat; if (type.equals(ToscaPropertyType.LIST.getType()) || type.equals(ToscaPropertyType.MAP.getType())) { responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_COMPLEX_DEFAULT_VALUE, property.getName(), type, innerType, property.getDefaultValue()); } else { responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_DEFAULT_VALUE, property.getName(), type, property.getDefaultValue()); } return Either.right(responseFormat); } return Either.left(true); } protected void handleDefaultValue(IComplexDefaultValue newAttributeDef, Map dataTypes) { // convert property ToscaPropertyType type = ToscaPropertyType.isValidType(newAttributeDef.getType()); PropertyValueConverter converter = type.getConverter(); // get inner type String innerType = null; if (newAttributeDef != null) { SchemaDefinition schema = newAttributeDef.getSchema(); if (schema != null) { PropertyDataDefinition prop = schema.getProperty(); if (schema.getProperty() != null) { innerType = prop.getType(); } } String convertedValue = null; if (newAttributeDef.getDefaultValue() != null) { convertedValue = converter.convert(newAttributeDef.getDefaultValue(), innerType, dataTypes); newAttributeDef.setDefaultValue(convertedValue); } } } protected void validateComponentTypeEnum(ComponentTypeEnum componentTypeEnum, String errorContext, Wrapper errorWrapper) { if (componentTypeEnum == null) { BeEcompErrorManager.getInstance().logInvalidInputError(errorContext, "invalid component type", ErrorSeverity.INFO); errorWrapper.setInnerElement(componentsUtils.getResponseFormat(ActionStatus.NOT_ALLOWED)); } } protected void validateCanWorkOnComponent(String componentId, ComponentTypeEnum componentTypeEnum, String userId, Wrapper errorWrapper) { if (!ComponentValidationUtils.canWorkOnComponent(componentId, toscaOperationFacade, userId)) { log.info("Restricted operation for user {} on {} {}", userId, componentTypeEnum.getValue(), componentId); errorWrapper.setInnerElement(componentsUtils.getResponseFormat(ActionStatus.RESTRICTED_OPERATION)); } } protected void validateComponentLock(String componentId, ComponentTypeEnum componentTypeEnum, Wrapper errorWrapper) { StorageOperationStatus lockStatus = graphLockOperation.lockComponent(componentId, componentTypeEnum.getNodeType()); if (lockStatus != StorageOperationStatus.OK) { log.debug("Failed to lock {} {}", componentTypeEnum.getValue(), componentId); errorWrapper.setInnerElement(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(lockStatus))); } } protected ToscaPropertyType getType(String propertyType) { return ToscaPropertyType.isValidType(propertyType); } protected void commitOrRollback(Either result) { if (result == null || result.isRight()) { log.warn("operation failed. do rollback"); titanDao.rollback(); } else { log.debug("operation success. do commit"); titanDao.commit(); } } protected Either lockComponentByName(String name, Component component, String ecompErrorContext) { ComponentTypeEnum componentType = component.getComponentType(); NodeTypeEnum nodeType = componentType.getNodeType(); StorageOperationStatus lockResourceStatus = graphLockOperation.lockComponentByName(name, nodeType); if (lockResourceStatus.equals(StorageOperationStatus.OK)) { return Either.left(true); } else { BeEcompErrorManager.getInstance().logBeFailedLockObjectError(ecompErrorContext, nodeType.getName(), name); ActionStatus actionStatus = componentsUtils.convertFromStorageResponse(lockResourceStatus, componentType); ResponseFormat responseFormat = componentsUtils.getResponseFormat(actionStatus, component.getName()); log.debug("Failed to lock component {} error - {}", name, actionStatus); return Either.right(responseFormat); } } protected Either validateComponentExistsByFilter(String componentId, ComponentTypeEnum componentType, ComponentParametersView componentParametersView) { return toscaOperationFacade.getToscaElement(componentId, componentParametersView) .right() .map(err -> handleGetComponentError(componentId, componentType, err)); } private ResponseFormat handleGetComponentError(String componentId, ComponentTypeEnum componentType, StorageOperationStatus getComponentError) { ActionStatus actionStatus = componentsUtils.convertFromStorageResponse(getComponentError, componentType); ResponseFormat responseFormat = componentsUtils.getResponseFormat(actionStatus, Constants.EMPTY_STRING); log.debug("error fetching component with id {}. error status: {}", componentId, getComponentError); return responseFormat; } protected Either validateFreeText(GroupProperty groupPropertyToUpdate) { Either ret; final String groupTypeValue = groupPropertyToUpdate.getValue(); if (!StringUtils.isEmpty(groupTypeValue)) { if (!ValidationUtils.validateDescriptionLength(groupTypeValue)) { ret = Either.right(componentsUtils.getResponseFormat(ActionStatus.COMPONENT_DESCRIPTION_EXCEEDS_LIMIT, NodeTypeEnum.Property.getName(), String.valueOf(ValidationUtils.COMPONENT_DESCRIPTION_MAX_LENGTH))); } else if (!ValidationUtils.validateIsEnglish(groupTypeValue)) { ret = Either.right(componentsUtils.getResponseFormat(ActionStatus.COMPONENT_INVALID_DESCRIPTION, NodeTypeEnum.Property.getName())); } else { ret = Either.left(groupPropertyToUpdate); } } else { ret = Either.left(groupPropertyToUpdate); } return ret; } @SafeVarargs static > boolean enumHasValueFilter(String name, Function enumGetter, T... enumValues) { T enumFound = enumGetter.apply(name); return Arrays.asList(enumValues).contains(enumFound); } Either validatePropValueBeforeCreate(IPropertyInputCommon property, String value, boolean isValidate, String innerType, Map allDataTypes) { String propertyType = property.getType(); ToscaPropertyType type = ToscaPropertyType.isValidType(propertyType); if (type == ToscaPropertyType.LIST || type == ToscaPropertyType.MAP) { SchemaDefinition def = property.getSchema(); if (def == null) { log.debug("Schema doesn't exists for property of type {}", type); return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(TitanOperationStatus.ILLEGAL_ARGUMENT)); } PropertyDataDefinition propDef = def.getProperty(); if (propDef == null) { log.debug("Property in Schema Definition inside property of type {} doesn't exist", type); return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(TitanOperationStatus.ILLEGAL_ARGUMENT)); } innerType = propDef.getType(); } Either isValid = validateAndUpdatePropertyValue(propertyType, value, isValidate, innerType, allDataTypes); String newValue = value; if (isValid.isRight()) { Boolean res = isValid.right().value(); if (Boolean.FALSE.equals(res)) { return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(TitanOperationStatus.ILLEGAL_ARGUMENT)); } } else { Object object = isValid.left().value(); if (object != null) { newValue = object.toString(); } } ImmutablePair pair = validateAndUpdateRules(propertyType, property.getRules(), innerType, allDataTypes, isValidate); log.trace("After validateAndUpdateRules. pair = {}", pair); if (Boolean.FALSE.equals(pair.getRight())) { BeEcompErrorManager.getInstance().logBeInvalidValueError("Add property value", pair.getLeft(), property.getName(), propertyType); return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(TitanOperationStatus.ILLEGAL_ARGUMENT)); } return Either.left(newValue); } protected Either validateInputValueBeforeCreate(ComponentInstanceInput property, String value, boolean isValidate, String innerType, Map allDataTypes) { String propertyType = property.getType(); ToscaPropertyType type = ToscaPropertyType.isValidType(propertyType); if (type == ToscaPropertyType.LIST || type == ToscaPropertyType.MAP) { SchemaDefinition def = property.getSchema(); if (def == null) { log.debug("Schema doesn't exists for property of type {}", type); return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(TitanOperationStatus.ILLEGAL_ARGUMENT)); } PropertyDataDefinition propDef = def.getProperty(); if (propDef == null) { log.debug("Property in Schema Definition inside property of type {} doesn't exist", type); return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(TitanOperationStatus.ILLEGAL_ARGUMENT)); } innerType = propDef.getType(); } Either isValid = validateAndUpdatePropertyValue(propertyType, value, isValidate, innerType, allDataTypes); String newValue = value; if (isValid.isRight()) { Boolean res = isValid.right().value(); if (Boolean.FALSE.equals(res)) { return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(TitanOperationStatus.ILLEGAL_ARGUMENT)); } } else { Object object = isValid.left().value(); if (object != null) { newValue = object.toString(); } } ImmutablePair pair = validateAndUpdateRules(propertyType, property.getRules(), innerType, allDataTypes, isValidate); log.debug("After validateAndUpdateRules. pair = {}", pair); if (Boolean.FALSE.equals(pair.getRight())) { BeEcompErrorManager.getInstance().logBeInvalidValueError("Add property value", pair.getLeft(), property.getName(), propertyType); return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(TitanOperationStatus.ILLEGAL_ARGUMENT)); } return Either.left(newValue); } public Either validateAndUpdatePropertyValue(String propertyType, String value, boolean isValidate, String innerType, Map dataTypes) { log.trace("Going to validate property value and its type. type = {}, value = {}", propertyType, value); ToscaPropertyType type = getType(propertyType); if (isValidate) { if (type == null) { DataTypeDefinition dataTypeDefinition = dataTypes.get(propertyType); ImmutablePair validateResult = dataTypeValidatorConverter.validateAndUpdate(value, dataTypeDefinition, dataTypes); if (Boolean.FALSE.equals(validateResult.right)) { log.debug("The value {} of property from type {} is invalid", value, propertyType); return Either.right(false); } JsonElement jsonElement = validateResult.left; String valueFromJsonElement = getValueFromJsonElement(jsonElement); return Either.left(valueFromJsonElement); } log.trace("before validating property type {}", propertyType); boolean isValidProperty = isValidValue(type, value, innerType, dataTypes); if (!isValidProperty) { log.debug("The value {} of property from type {} is invalid", value, type); return Either.right(false); } } Object convertedValue = value; if (!isEmptyValue(value) && isValidate) { PropertyValueConverter converter = type.getConverter(); convertedValue = converter.convert(value, innerType, dataTypes); } return Either.left(convertedValue); } public ImmutablePair validateAndUpdateRules(String propertyType, List rules, String innerType, Map dataTypes, boolean isValidate) { if (rules == null || rules.isEmpty()) { return ImmutablePair.of(null, true); } for (PropertyRule rule : rules) { String value = rule.getValue(); Either updateResult = validateAndUpdatePropertyValue(propertyType, value, isValidate, innerType, dataTypes); if (updateResult.isRight()) { Boolean status = updateResult.right().value(); if (Boolean.FALSE.equals(status)) { return ImmutablePair.of(value, status); } } else { String newValue = null; Object object = updateResult.left().value(); if (object != null) { newValue = object.toString(); } rule.setValue(newValue); } } return ImmutablePair.of(null, true); } protected boolean isValidValue(ToscaPropertyType type, String value, String innerType, Map dataTypes) { if (isEmptyValue(value)) { return true; } PropertyTypeValidator validator = type.getValidator(); return validator.isValid(value, innerType, dataTypes); } public boolean isEmptyValue(String value) { if (value == null) { return true; } return false; } public boolean isNullParam(String value) { if (value == null) { return true; } return false; } public void addRulesToNewPropertyValue(PropertyValueData propertyValueData, ComponentInstanceProperty resourceInstanceProperty, String resourceInstanceId) { List rules = resourceInstanceProperty.getRules(); if (rules == null) { PropertyRule propertyRule = buildRuleFromPath(propertyValueData, resourceInstanceProperty, resourceInstanceId); rules = new ArrayList<>(); rules.add(propertyRule); } else { rules = sortRules(rules); } propertyValueData.setRules(rules); } private PropertyRule buildRuleFromPath(PropertyValueData propertyValueData, ComponentInstanceProperty resourceInstanceProperty, String resourceInstanceId) { List path = resourceInstanceProperty.getPath(); // FOR BC. Since old Property values on VFC/VF does not have rules on // graph. // Update could be done on one level only, thus we can use this // operation to avoid migration. if (isEmpty(path)) { path = new ArrayList<>(); path.add(resourceInstanceId); } PropertyRule propertyRule = new PropertyRule(); propertyRule.setRule(path); propertyRule.setValue(propertyValueData.getValue()); return propertyRule; } private List sortRules(List rules) { // TODO: sort the rules by size and binary representation. // (x, y, .+) --> 110 6 priority 1 // (x, .+, z) --> 101 5 priority 2 return rules; } protected String getValueFromJsonElement(JsonElement jsonElement) { String value = null; if (jsonElement == null || jsonElement.isJsonNull()) { value = EMPTY_VALUE; } else { if (jsonElement.toString().isEmpty()) { value = ""; } else { value = jsonElement.toString(); } } return value; } }