diff options
Diffstat (limited to 'catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/PropertyBusinessLogic.java')
-rw-r--r-- | catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/PropertyBusinessLogic.java | 991 |
1 files changed, 473 insertions, 518 deletions
diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/PropertyBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/PropertyBusinessLogic.java index ff26ced5c9..9cc4b9cd3e 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/PropertyBusinessLogic.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/PropertyBusinessLogic.java @@ -20,16 +20,8 @@ package org.openecomp.sdc.be.components.impl; -import java.lang.reflect.Type; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.function.Supplier; - -import javax.servlet.ServletContext; - +import com.google.gson.JsonElement; +import fj.data.Either; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.tuple.ImmutablePair; import org.openecomp.sdc.be.config.BeEcompErrorManager; @@ -41,20 +33,17 @@ import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum; import org.openecomp.sdc.be.impl.WebAppContextWrapper; import org.openecomp.sdc.be.model.DataTypeDefinition; import org.openecomp.sdc.be.model.IComplexDefaultValue; -import org.openecomp.sdc.be.model.PropertyConstraint; import org.openecomp.sdc.be.model.PropertyDefinition; import org.openecomp.sdc.be.model.Resource; import org.openecomp.sdc.be.model.User; import org.openecomp.sdc.be.model.operations.api.IElementOperation; import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus; -import org.openecomp.sdc.be.model.operations.impl.PropertyOperation.PropertyConstraintDeserialiser; 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.EntryData; -import org.openecomp.sdc.be.resources.data.PropertyData; import org.openecomp.sdc.common.api.Constants; import org.openecomp.sdc.exception.ResponseFormat; import org.slf4j.Logger; @@ -62,513 +51,479 @@ import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; import org.springframework.web.context.WebApplicationContext; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import com.google.gson.JsonElement; -import com.google.gson.reflect.TypeToken; - -import fj.data.Either; +import javax.servlet.ServletContext; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.function.Supplier; @Component("propertyBusinessLogic") public class PropertyBusinessLogic extends BaseBusinessLogic { - private static final String CREATE_PROPERTY = "CreateProperty"; - - private static Logger log = LoggerFactory.getLogger(PropertyBusinessLogic.class.getName()); - - private static final String EMPTY_VALUE = null; - - private DataTypeValidatorConverter dataTypeValidatorConverter = DataTypeValidatorConverter.getInstance(); - - protected static IElementOperation getElementDao(Class<IElementOperation> class1, ServletContext context) { - WebAppContextWrapper webApplicationContextWrapper = (WebAppContextWrapper) context.getAttribute(Constants.WEB_APPLICATION_CONTEXT_WRAPPER_ATTR); - - WebApplicationContext webApplicationContext = webApplicationContextWrapper.getWebAppContext(context); - - return webApplicationContext.getBean(class1); - } - - public Either<Map<String, DataTypeDefinition>, ResponseFormat> getAllDataTypes() { - Either<Map<String, DataTypeDefinition>, ResponseFormat> eitherAllDataTypes = getAllDataTypes(applicationDataTypeCache); - return eitherAllDataTypes; - } - - /** - * Create new property on resource in graph - * - * @param resourceId - * @param propertyName - * @param newPropertyDefinition - * @param userId - * @return Either<PropertyDefinition, ActionStatus> - */ - public Either<EntryData<String, PropertyDefinition>, ResponseFormat> createProperty(String resourceId, String propertyName, PropertyDefinition newPropertyDefinition, String userId) { - - Either<EntryData<String, PropertyDefinition>, ResponseFormat> result = null; - - Either<User, ResponseFormat> resp = validateUserExists(userId, "create Property", false); - if (resp.isRight()) { - result = Either.right(resp.right().value()); - return result; - } - - StorageOperationStatus lockResult = graphLockOperation.lockComponent(resourceId, NodeTypeEnum.Resource); - if (!lockResult.equals(StorageOperationStatus.OK)) { - BeEcompErrorManager.getInstance().logBeFailedLockObjectError(CREATE_PROPERTY, NodeTypeEnum.Resource.name().toLowerCase(), resourceId); - log.info("Failed to lock component {}. Error - {}", resourceId, lockResult); - result = Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR)); - return result; - } - - try { - // Get the resource from DB - Either<Resource, StorageOperationStatus> status = toscaOperationFacade.getToscaElement(resourceId); - if (status.isRight()) { - result = Either.right(componentsUtils.getResponseFormat(ActionStatus.RESOURCE_NOT_FOUND, resourceId)); - return result; - } - Resource resource = status.left().value(); - - // verify that resource is checked-out and the user is the last - // updater - if (!ComponentValidationUtils.canWorkOnResource(resource, userId)) { - result = Either.right(componentsUtils.getResponseFormat(ActionStatus.RESTRICTED_OPERATION)); - return result; - } - - // verify property not exist in resource - List<PropertyDefinition> resourceProperties = resource.getProperties(); - - if (resourceProperties != null) { - if (isPropertyExist(resourceProperties, resourceId, propertyName, newPropertyDefinition.getType())) { - result = Either.right(componentsUtils.getResponseFormat(ActionStatus.PROPERTY_ALREADY_EXIST, propertyName)); - return result; - } - } - - Either<Map<String, DataTypeDefinition>, ResponseFormat> allDataTypes = getAllDataTypes(applicationDataTypeCache); - if (allDataTypes.isRight()) { - result = Either.right(allDataTypes.right().value()); - return result; - } - - Map<String, DataTypeDefinition> dataTypes = allDataTypes.left().value(); - - // validate property default values - Either<Boolean, ResponseFormat> defaultValuesValidation = validatePropertyDefaultValue(newPropertyDefinition, dataTypes); - if (defaultValuesValidation.isRight()) { - result = Either.right(defaultValuesValidation.right().value()); - return result; - } - // convert property - ToscaPropertyType type = getType(newPropertyDefinition.getType()); - if (type != null) { - PropertyValueConverter converter = type.getConverter(); - // get inner type - String innerType = null; - if (newPropertyDefinition != null) { - SchemaDefinition schema = newPropertyDefinition.getSchema(); - if (schema != null) { - PropertyDataDefinition prop = schema.getProperty(); - if (prop != null) { - innerType = prop.getType(); - } - } - String convertedValue = null; - if (newPropertyDefinition.getDefaultValue() != null) { - convertedValue = converter.convert(newPropertyDefinition.getDefaultValue(), innerType, allDataTypes.left().value()); - newPropertyDefinition.setDefaultValue(convertedValue); - } - } - } - - // add the new property to resource on graph - // need to get StorageOpaerationStatus and convert to ActionStatus - // from componentsUtils - Either<PropertyDefinition, StorageOperationStatus> either = toscaOperationFacade.addPropertyToResource(propertyName, newPropertyDefinition, resource); - if (either.isRight()) { - result = Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(either.right().value()), resource.getName())); - return result; - } - - PropertyDefinition createdPropertyDefinition = either.left().value(); - EntryData<String, PropertyDefinition> property = new EntryData<String, PropertyDefinition>(propertyName, createdPropertyDefinition); - result = Either.left(property); - return result; - - } finally { - commitOrRollback(result); - // unlock component - graphLockOperation.unlockComponent(resourceId, NodeTypeEnum.Resource); - } - - } - - /** - * Get property of resource - * - * @param resourceId - * @param propertyId - * @param userId - * @return - */ - public Either<Entry<String, PropertyDefinition>, ResponseFormat> getProperty(String resourceId, String propertyId, String userId) { - - Either<User, ResponseFormat> resp = validateUserExists(userId, "create Component Instance", false); - if (resp.isRight()) { - return Either.right(resp.right().value()); - } - - // Get the resource from DB - Either<Resource, StorageOperationStatus> status = toscaOperationFacade.getToscaElement(resourceId); - if (status.isRight()) { - return Either.right(componentsUtils.getResponseFormat(ActionStatus.RESOURCE_NOT_FOUND, resourceId)); - } - Resource resource = status.left().value(); - - // verify property exist in resource - List<PropertyDefinition> properties = resource.getProperties(); - if (properties == null) { - return Either.right(componentsUtils.getResponseFormat(ActionStatus.PROPERTY_NOT_FOUND, "")); - } - for (PropertyDefinition property : properties) { - if (property.getUniqueId().equals(propertyId) ) { - Map<String, PropertyDefinition> propMap = new HashMap<>(); - propMap.put(property.getName(), property); - return Either.left(propMap.entrySet().iterator().next()); - } - } - return Either.right(componentsUtils.getResponseFormat(ActionStatus.PROPERTY_NOT_FOUND, "")); - } - - private boolean isPropertyBelongsToResource(PropertyDataDefinition property, String resourceId) { - return property.getOwnerId() == null || property.getOwnerId().equals(resourceId); - } - - /** - * delete property of resource from graph - * - * @param resourceId - * @param propertyId - * @param userId - * @return - */ - public Either<Entry<String, PropertyDefinition>, ResponseFormat> deleteProperty(String resourceId, String propertyId, String userId) { - - Either<Entry<String, PropertyDefinition>, ResponseFormat> result = null; - - Either<User, ResponseFormat> resp = validateUserExists(userId, "delete Property", false); - if (resp.isRight()) { - return Either.right(resp.right().value()); - } - - StorageOperationStatus lockResult = graphLockOperation.lockComponent(resourceId, NodeTypeEnum.Resource); - if (!lockResult.equals(StorageOperationStatus.OK)) { - BeEcompErrorManager.getInstance().logBeFailedLockObjectError(CREATE_PROPERTY, NodeTypeEnum.Resource.name().toLowerCase(), resourceId); - result = Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR)); - return result; - } - - try { - - // Get the resource from DB - Either<Resource, StorageOperationStatus> getResourceRes = toscaOperationFacade.getToscaElement(resourceId); - if (getResourceRes.isRight()) { - result = Either.right(componentsUtils.getResponseFormat(ActionStatus.RESOURCE_NOT_FOUND, resourceId)); - return result; - } - Resource resource = getResourceRes.left().value(); - - // verify that resource is checked-out and the user is the last - // updater - if (!ComponentValidationUtils.canWorkOnResource(resource, userId)) { - result = Either.right(componentsUtils.getResponseFormat(ActionStatus.RESTRICTED_OPERATION)); - return result; - } - - // verify property exist in resource - Either<Entry<String, PropertyDefinition>, ResponseFormat> statusGetProperty = getProperty(resourceId, propertyId, userId); - if (statusGetProperty.isRight()) { - result = Either.right(statusGetProperty.right().value()); - return result; - } - - StorageOperationStatus status = toscaOperationFacade.deletePropertyOfResource(resource, statusGetProperty.left().value().getKey()); - if (status != StorageOperationStatus.OK) { - result = Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(status), resource.getName())); - return result; - } - // propertyOperation.getTitanGenericDao().commit(); - result = Either.left(statusGetProperty.left().value()); - return result; - - } finally { - commitOrRollback(result); - // unlock component - graphLockOperation.unlockComponent(resourceId, NodeTypeEnum.Resource); - } - } - - /** - * update property - * - * @param resourceId - * @param propertyId - * @param newPropertyDefinition - * @param userId - * @return - */ - public Either<EntryData<String, PropertyDefinition>, ResponseFormat> updateProperty(String resourceId, String propertyId, PropertyDefinition newPropertyDefinition, String userId) { - - Either<EntryData<String, PropertyDefinition>, ResponseFormat> result = null; - - Either<Resource, StorageOperationStatus> status = toscaOperationFacade.getToscaElement(resourceId); - if (status.isRight()) { - return Either.right(componentsUtils.getResponseFormat(ActionStatus.RESOURCE_NOT_FOUND, resourceId)); - } - Resource resource = status.left().value(); - - if (!ComponentValidationUtils.canWorkOnResource(resource, userId)) { - return Either.right(componentsUtils.getResponseFormat(ActionStatus.RESTRICTED_OPERATION)); - } - - StorageOperationStatus lockResult = graphLockOperation.lockComponent(resourceId, NodeTypeEnum.Resource); - if (!lockResult.equals(StorageOperationStatus.OK)) { - BeEcompErrorManager.getInstance().logBeFailedLockObjectError(CREATE_PROPERTY, NodeTypeEnum.Resource.name().toLowerCase(), resourceId); - result = Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR)); - return result; - } - - try { - Either<Entry<String, PropertyDefinition>, ResponseFormat> statusGetProperty = getProperty(resourceId, propertyId, userId); - if (statusGetProperty.isRight()) { - result = Either.right(statusGetProperty.right().value()); - return result; - } - String propertyName = statusGetProperty.left().value().getKey(); - - Either<Map<String, DataTypeDefinition>, ResponseFormat> allDataTypes = getAllDataTypes(applicationDataTypeCache); - if (allDataTypes.isRight()) { - result = Either.right(allDataTypes.right().value()); - return result; - } - Map<String, DataTypeDefinition> dataTypes = allDataTypes.left().value(); - - Either<Boolean, ResponseFormat> defaultValuesValidation = validatePropertyDefaultValue(newPropertyDefinition, dataTypes); - if (defaultValuesValidation.isRight()) { - result = Either.right(defaultValuesValidation.right().value()); - return result; - } - - Either<PropertyDefinition, StorageOperationStatus> either = handleProperty(propertyId, newPropertyDefinition, dataTypes); - if (either.isRight()) { - log.debug("Problem while updating property with id {}. Reason - {}", propertyId, either.right().value()); - result = Either.right(componentsUtils.getResponseFormatByResource(componentsUtils.convertFromStorageResponse(either.right().value()), resource.getName())); - return result; - } - - - either = toscaOperationFacade.updatePropertyOfResource(resource, newPropertyDefinition); - if (either.isRight()) { - result = Either.right(componentsUtils.getResponseFormatByResource(componentsUtils.convertFromStorageResponse(either.right().value()), resource.getName())); - return result; - } - - EntryData<String, PropertyDefinition> property = new EntryData<String, PropertyDefinition>(propertyName, either.left().value()); - result = Either.left(property); - return result; - - } finally { - commitOrRollback(result); - graphLockOperation.unlockComponent(resourceId, NodeTypeEnum.Resource); - } - - } - - private boolean isPropertyExist(List<PropertyDefinition> properties, String resourceUid, String propertyName, String propertyType) { - boolean result = false; - if (!CollectionUtils.isEmpty(properties)) { - for (PropertyDefinition propertyDefinition : properties) { - - if ( propertyDefinition.getName().equals(propertyName) && - (propertyDefinition.getParentUniqueId().equals(resourceUid) || !propertyDefinition.getType().equals(propertyType)) ) { - result = true; - break; - } - } - } - return result; - } - - private PropertyDefinition convertPropertyDataToPropertyDefinition(PropertyData propertyDataResult, String propertyName, String resourceId) { - log.debug("The object returned after create property is {}", propertyDataResult); - PropertyDefinition propertyDefResult = new PropertyDefinition(propertyDataResult.getPropertyDataDefinition()); - propertyDefResult.setConstraints(convertConstraints(propertyDataResult.getConstraints())); - propertyDefResult.setName(propertyName); - propertyDefResult.setParentUniqueId(resourceId); - return propertyDefResult; - } - - private List<PropertyConstraint> convertConstraints(List<String> constraints) { - - if (constraints == null || constraints.size() == 0) { - return null; - } - - List<PropertyConstraint> list = new ArrayList<PropertyConstraint>(); - Type constraintType = new TypeToken<PropertyConstraint>() { - }.getType(); - - Gson gson = new GsonBuilder().registerTypeAdapter(constraintType, new PropertyConstraintDeserialiser()).create(); - - for (String constraintJson : constraints) { - PropertyConstraint propertyConstraint = gson.fromJson(constraintJson, constraintType); - list.add(propertyConstraint); - } - - return list; - } - - private Either<PropertyDefinition, StorageOperationStatus> handleProperty(String propertyId, PropertyDefinition newPropertyDefinition, Map<String, DataTypeDefinition> dataTypes) { - - StorageOperationStatus validateAndUpdateProperty = validateAndUpdateProperty(newPropertyDefinition, dataTypes); - if (validateAndUpdateProperty != StorageOperationStatus.OK) { - return Either.right(validateAndUpdateProperty); - } - - return Either.left(newPropertyDefinition); - } - - private StorageOperationStatus validateAndUpdateProperty(IComplexDefaultValue propertyDefinition, Map<String, DataTypeDefinition> dataTypes) { - - log.trace("Going to validate property type and value. {}", propertyDefinition); - - String propertyType = propertyDefinition.getType(); - String value = propertyDefinition.getDefaultValue(); - - ToscaPropertyType type = getType(propertyType); - - if (type == null) { - - DataTypeDefinition dataTypeDefinition = dataTypes.get(propertyType); - if (dataTypeDefinition == null) { - log.debug("The type {} of property cannot be found.", propertyType); - return StorageOperationStatus.INVALID_TYPE; - } - - StorageOperationStatus status = validateAndUpdateComplexValue(propertyDefinition, propertyType, value, dataTypeDefinition, dataTypes); - - return status; - - } - String innerType = null; - - Either<String, TitanOperationStatus> checkInnerType = getInnerType(type, () -> propertyDefinition.getSchema()); - if (checkInnerType.isRight()) { - return StorageOperationStatus.INVALID_TYPE; - } - innerType = checkInnerType.left().value(); - - log.trace("After validating property type {}", propertyType); - - boolean isValidProperty = isValidValue(type, value, innerType, dataTypes); - if (false == isValidProperty) { - log.info("The value {} of property from type {} is invalid", value, type); - return StorageOperationStatus.INVALID_VALUE; - } - - PropertyValueConverter converter = type.getConverter(); - - if (isEmptyValue(value)) { - log.debug("Default value was not sent for property {}. Set default value to {}", propertyDefinition.getName(), EMPTY_VALUE); - propertyDefinition.setDefaultValue(EMPTY_VALUE); - } else if (false == isEmptyValue(value)) { - String convertedValue = converter.convert(value, innerType, dataTypes); - propertyDefinition.setDefaultValue(convertedValue); - } - return StorageOperationStatus.OK; - } - - protected StorageOperationStatus validateAndUpdateComplexValue(IComplexDefaultValue propertyDefinition, String propertyType, - - String value, DataTypeDefinition dataTypeDefinition, Map<String, DataTypeDefinition> dataTypes) { - - ImmutablePair<JsonElement, Boolean> validateResult = dataTypeValidatorConverter.validateAndUpdate(value, dataTypeDefinition, dataTypes); - - if (validateResult.right.booleanValue() == false) { - log.debug("The value {} of property from type {} is invalid", propertyType, propertyType); - return StorageOperationStatus.INVALID_VALUE; - } - - JsonElement jsonElement = validateResult.left; - - log.trace("Going to update value in property definition {} {}" , propertyDefinition.getName() , (jsonElement != null ? jsonElement.toString() : null)); - - updateValue(propertyDefinition, jsonElement); - - return StorageOperationStatus.OK; - } - - protected void updateValue(IComplexDefaultValue propertyDefinition, JsonElement jsonElement) { - - propertyDefinition.setDefaultValue(getValueFromJsonElement(jsonElement)); - - } - - 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; - } - - protected Either<String, TitanOperationStatus> getInnerType(ToscaPropertyType type, Supplier<SchemaDefinition> schemeGen) { - String innerType = null; - if (type == ToscaPropertyType.LIST || type == ToscaPropertyType.MAP) { - - SchemaDefinition def = schemeGen.get();// propDataDef.getSchema(); - if (def == null) { - log.debug("Schema doesn't exists for property of type {}", type); - return Either.right(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(TitanOperationStatus.ILLEGAL_ARGUMENT); - } - innerType = propDef.getType(); - } - return Either.left(innerType); - } - protected boolean isValidValue(ToscaPropertyType type, String value, String innerType, Map<String, DataTypeDefinition> dataTypes) { - if (isEmptyValue(value)) { - return true; - } - - PropertyTypeValidator validator = type.getValidator(); - - boolean isValid = validator.isValid(value, innerType, dataTypes); - if (true == isValid) { - return true; - } else { - return false; - } - - } - - public boolean isEmptyValue(String value) { - if (value == null) { - return true; - } - return false; - } + private static final String CREATE_PROPERTY = "CreateProperty"; + + private static final Logger log = LoggerFactory.getLogger(PropertyBusinessLogic.class); + + private static final String EMPTY_VALUE = null; + + private DataTypeValidatorConverter dataTypeValidatorConverter = DataTypeValidatorConverter.getInstance(); + + protected static IElementOperation getElementDao(Class<IElementOperation> class1, ServletContext context) { + WebAppContextWrapper webApplicationContextWrapper = (WebAppContextWrapper) context.getAttribute(Constants.WEB_APPLICATION_CONTEXT_WRAPPER_ATTR); + + WebApplicationContext webApplicationContext = webApplicationContextWrapper.getWebAppContext(context); + + return webApplicationContext.getBean(class1); + } + + public Either<Map<String, DataTypeDefinition>, ResponseFormat> getAllDataTypes() { + Either<Map<String, DataTypeDefinition>, ResponseFormat> eitherAllDataTypes = getAllDataTypes(applicationDataTypeCache); + return eitherAllDataTypes; + } + + /** + * Create new property on resource in graph + * + * @param resourceId + * @param propertyName + * @param newPropertyDefinition + * @param userId + * @return Either<PropertyDefinition, ActionStatus> + */ + public Either<EntryData<String, PropertyDefinition>, ResponseFormat> createProperty(String resourceId, String propertyName, PropertyDefinition newPropertyDefinition, String userId) { + + Either<EntryData<String, PropertyDefinition>, ResponseFormat> result = null; + + Either<User, ResponseFormat> resp = validateUserExists(userId, "create Property", false); + if (resp.isRight()) { + result = Either.right(resp.right().value()); + return result; + } + + StorageOperationStatus lockResult = graphLockOperation.lockComponent(resourceId, NodeTypeEnum.Resource); + if (!lockResult.equals(StorageOperationStatus.OK)) { + BeEcompErrorManager.getInstance().logBeFailedLockObjectError(CREATE_PROPERTY, NodeTypeEnum.Resource.name().toLowerCase(), resourceId); + log.info("Failed to lock component {}. Error - {}", resourceId, lockResult); + result = Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR)); + return result; + } + + try { + // Get the resource from DB + Either<Resource, StorageOperationStatus> status = toscaOperationFacade.getToscaElement(resourceId); + if (status.isRight()) { + result = Either.right(componentsUtils.getResponseFormat(ActionStatus.RESOURCE_NOT_FOUND, "")); + return result; + } + Resource resource = status.left().value(); + + // verify that resource is checked-out and the user is the last + // updater + if (!ComponentValidationUtils.canWorkOnResource(resource, userId)) { + result = Either.right(componentsUtils.getResponseFormat(ActionStatus.RESTRICTED_OPERATION)); + return result; + } + + // verify property not exist in resource + List<PropertyDefinition> resourceProperties = resource.getProperties(); + + if (resourceProperties != null) { + if (isPropertyExist(resourceProperties, resourceId, propertyName, newPropertyDefinition.getType())) { + result = Either.right(componentsUtils.getResponseFormat(ActionStatus.PROPERTY_ALREADY_EXIST, propertyName)); + return result; + } + } + + Either<Map<String, DataTypeDefinition>, ResponseFormat> allDataTypes = getAllDataTypes(applicationDataTypeCache); + if (allDataTypes.isRight()) { + result = Either.right(allDataTypes.right().value()); + return result; + } + + Map<String, DataTypeDefinition> dataTypes = allDataTypes.left().value(); + + // validate property default values + Either<Boolean, ResponseFormat> defaultValuesValidation = validatePropertyDefaultValue(newPropertyDefinition, dataTypes); + if (defaultValuesValidation.isRight()) { + result = Either.right(defaultValuesValidation.right().value()); + return result; + } + // convert property + ToscaPropertyType type = getType(newPropertyDefinition.getType()); + if (type != null) { + PropertyValueConverter converter = type.getConverter(); + // get inner type + String innerType = null; + if (newPropertyDefinition != null) { + SchemaDefinition schema = newPropertyDefinition.getSchema(); + if (schema != null) { + PropertyDataDefinition prop = schema.getProperty(); + if (prop != null) { + innerType = prop.getType(); + } + } + String convertedValue = null; + if (newPropertyDefinition.getDefaultValue() != null) { + convertedValue = converter.convert(newPropertyDefinition.getDefaultValue(), innerType, allDataTypes.left().value()); + newPropertyDefinition.setDefaultValue(convertedValue); + } + } + } + + // add the new property to resource on graph + // need to get StorageOpaerationStatus and convert to ActionStatus + // from componentsUtils + Either<PropertyDefinition, StorageOperationStatus> either = toscaOperationFacade.addPropertyToResource(propertyName, newPropertyDefinition, resource); + if (either.isRight()) { + result = Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(either.right().value()), resource.getName())); + return result; + } + + PropertyDefinition createdPropertyDefinition = either.left().value(); + EntryData<String, PropertyDefinition> property = new EntryData<String, PropertyDefinition>(propertyName, createdPropertyDefinition); + result = Either.left(property); + return result; + + } finally { + commitOrRollback(result); + // unlock component + graphLockOperation.unlockComponent(resourceId, NodeTypeEnum.Resource); + } + + } + + /** + * Get property of resource + * + * @param resourceId + * @param propertyId + * @param userId + * @return + */ + public Either<Entry<String, PropertyDefinition>, ResponseFormat> getProperty(String resourceId, String propertyId, String userId) { + + Either<User, ResponseFormat> resp = validateUserExists(userId, "create Component Instance", false); + if (resp.isRight()) { + return Either.right(resp.right().value()); + } + + // Get the resource from DB + Either<Resource, StorageOperationStatus> status = toscaOperationFacade.getToscaElement(resourceId); + if (status.isRight()) { + return Either.right(componentsUtils.getResponseFormat(ActionStatus.RESOURCE_NOT_FOUND, "")); + } + Resource resource = status.left().value(); + + // verify property exist in resource + List<PropertyDefinition> properties = resource.getProperties(); + if (properties == null) { + return Either.right(componentsUtils.getResponseFormat(ActionStatus.PROPERTY_NOT_FOUND, "")); + } + for (PropertyDefinition property : properties) { + if (property.getUniqueId().equals(propertyId) ) { + Map<String, PropertyDefinition> propMap = new HashMap<>(); + propMap.put(property.getName(), property); + return Either.left(propMap.entrySet().iterator().next()); + } + } + return Either.right(componentsUtils.getResponseFormat(ActionStatus.PROPERTY_NOT_FOUND, "")); + } + + /** + * delete property of resource from graph + * + * @param resourceId + * @param propertyId + * @param userId + * @return + */ + public Either<Entry<String, PropertyDefinition>, ResponseFormat> deleteProperty(String resourceId, String propertyId, String userId) { + + Either<Entry<String, PropertyDefinition>, ResponseFormat> result = null; + + Either<User, ResponseFormat> resp = validateUserExists(userId, "delete Property", false); + if (resp.isRight()) { + return Either.right(resp.right().value()); + } + + StorageOperationStatus lockResult = graphLockOperation.lockComponent(resourceId, NodeTypeEnum.Resource); + if (!lockResult.equals(StorageOperationStatus.OK)) { + BeEcompErrorManager.getInstance().logBeFailedLockObjectError(CREATE_PROPERTY, NodeTypeEnum.Resource.name().toLowerCase(), resourceId); + result = Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR)); + return result; + } + + try { + + // Get the resource from DB + Either<Resource, StorageOperationStatus> getResourceRes = toscaOperationFacade.getToscaElement(resourceId); + if (getResourceRes.isRight()) { + result = Either.right(componentsUtils.getResponseFormat(ActionStatus.RESOURCE_NOT_FOUND, "")); + return result; + } + Resource resource = getResourceRes.left().value(); + + // verify that resource is checked-out and the user is the last + // updater + if (!ComponentValidationUtils.canWorkOnResource(resource, userId)) { + result = Either.right(componentsUtils.getResponseFormat(ActionStatus.RESTRICTED_OPERATION)); + return result; + } + + // verify property exist in resource + Either<Entry<String, PropertyDefinition>, ResponseFormat> statusGetProperty = getProperty(resourceId, propertyId, userId); + if (statusGetProperty.isRight()) { + result = Either.right(statusGetProperty.right().value()); + return result; + } + + StorageOperationStatus status = toscaOperationFacade.deletePropertyOfResource(resource, statusGetProperty.left().value().getKey()); + if (status != StorageOperationStatus.OK) { + result = Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(status), resource.getName())); + return result; + } + result = Either.left(statusGetProperty.left().value()); + return result; + + } finally { + commitOrRollback(result); + // unlock component + graphLockOperation.unlockComponent(resourceId, NodeTypeEnum.Resource); + } + } + + /** + * update property + * + * @param resourceId + * @param propertyId + * @param newPropertyDefinition + * @param userId + * @return + */ + public Either<EntryData<String, PropertyDefinition>, ResponseFormat> updateProperty(String resourceId, String propertyId, PropertyDefinition newPropertyDefinition, String userId) { + + Either<EntryData<String, PropertyDefinition>, ResponseFormat> result = null; + + Either<Resource, StorageOperationStatus> status = toscaOperationFacade.getToscaElement(resourceId); + if (status.isRight()) { + return Either.right(componentsUtils.getResponseFormat(ActionStatus.RESOURCE_NOT_FOUND, "")); + } + Resource resource = status.left().value(); + + if (!ComponentValidationUtils.canWorkOnResource(resource, userId)) { + return Either.right(componentsUtils.getResponseFormat(ActionStatus.RESTRICTED_OPERATION)); + } + + StorageOperationStatus lockResult = graphLockOperation.lockComponent(resourceId, NodeTypeEnum.Resource); + if (!lockResult.equals(StorageOperationStatus.OK)) { + BeEcompErrorManager.getInstance().logBeFailedLockObjectError(CREATE_PROPERTY, NodeTypeEnum.Resource.name().toLowerCase(), resourceId); + result = Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR)); + return result; + } + + try { + Either<Entry<String, PropertyDefinition>, ResponseFormat> statusGetProperty = getProperty(resourceId, propertyId, userId); + if (statusGetProperty.isRight()) { + result = Either.right(statusGetProperty.right().value()); + return result; + } + String propertyName = statusGetProperty.left().value().getKey(); + + Either<Map<String, DataTypeDefinition>, ResponseFormat> allDataTypes = getAllDataTypes(applicationDataTypeCache); + if (allDataTypes.isRight()) { + result = Either.right(allDataTypes.right().value()); + return result; + } + Map<String, DataTypeDefinition> dataTypes = allDataTypes.left().value(); + + Either<Boolean, ResponseFormat> defaultValuesValidation = validatePropertyDefaultValue(newPropertyDefinition, dataTypes); + if (defaultValuesValidation.isRight()) { + result = Either.right(defaultValuesValidation.right().value()); + return result; + } + + Either<PropertyDefinition, StorageOperationStatus> either = handleProperty(propertyId, newPropertyDefinition, dataTypes); + if (either.isRight()) { + log.debug("Problem while updating property with id {}. Reason - {}", propertyId, either.right().value()); + result = Either.right(componentsUtils.getResponseFormatByResource(componentsUtils.convertFromStorageResponse(either.right().value()), resource.getName())); + return result; + } + + + either = toscaOperationFacade.updatePropertyOfResource(resource, newPropertyDefinition); + if (either.isRight()) { + result = Either.right(componentsUtils.getResponseFormatByResource(componentsUtils.convertFromStorageResponse(either.right().value()), resource.getName())); + return result; + } + + EntryData<String, PropertyDefinition> property = new EntryData<String, PropertyDefinition>(propertyName, either.left().value()); + result = Either.left(property); + return result; + + } finally { + commitOrRollback(result); + graphLockOperation.unlockComponent(resourceId, NodeTypeEnum.Resource); + } + + } + + private boolean isPropertyExist(List<PropertyDefinition> properties, String resourceUid, String propertyName, String propertyType) { + boolean result = false; + if (!CollectionUtils.isEmpty(properties)) { + for (PropertyDefinition propertyDefinition : properties) { + + if ( propertyDefinition.getName().equals(propertyName) && + (propertyDefinition.getParentUniqueId().equals(resourceUid) || !propertyDefinition.getType().equals(propertyType)) ) { + result = true; + break; + } + } + } + return result; + } + + private Either<PropertyDefinition, StorageOperationStatus> handleProperty(String propertyId, PropertyDefinition newPropertyDefinition, Map<String, DataTypeDefinition> dataTypes) { + + StorageOperationStatus validateAndUpdateProperty = validateAndUpdateProperty(newPropertyDefinition, dataTypes); + if (validateAndUpdateProperty != StorageOperationStatus.OK) { + return Either.right(validateAndUpdateProperty); + } + + return Either.left(newPropertyDefinition); + } + + private StorageOperationStatus validateAndUpdateProperty(IComplexDefaultValue propertyDefinition, Map<String, DataTypeDefinition> dataTypes) { + + log.trace("Going to validate property type and value. {}", propertyDefinition); + + String propertyType = propertyDefinition.getType(); + String value = propertyDefinition.getDefaultValue(); + + ToscaPropertyType type = getType(propertyType); + + if (type == null) { + + DataTypeDefinition dataTypeDefinition = dataTypes.get(propertyType); + if (dataTypeDefinition == null) { + log.debug("The type {} of property cannot be found.", propertyType); + return StorageOperationStatus.INVALID_TYPE; + } + + StorageOperationStatus status = validateAndUpdateComplexValue(propertyDefinition, propertyType, value, dataTypeDefinition, dataTypes); + + return status; + + } + String innerType = null; + + Either<String, TitanOperationStatus> checkInnerType = getInnerType(type, () -> propertyDefinition.getSchema()); + if (checkInnerType.isRight()) { + return StorageOperationStatus.INVALID_TYPE; + } + innerType = checkInnerType.left().value(); + + log.trace("After validating property type {}", propertyType); + + boolean isValidProperty = isValidValue(type, value, innerType, dataTypes); + if (false == isValidProperty) { + log.info("The value {} of property from type {} is invalid", value, type); + return StorageOperationStatus.INVALID_VALUE; + } + + PropertyValueConverter converter = type.getConverter(); + + if (isEmptyValue(value)) { + log.debug("Default value was not sent for property {}. Set default value to {}", propertyDefinition.getName(), EMPTY_VALUE); + propertyDefinition.setDefaultValue(EMPTY_VALUE); + } else if (false == isEmptyValue(value)) { + String convertedValue = converter.convert(value, innerType, dataTypes); + propertyDefinition.setDefaultValue(convertedValue); + } + return StorageOperationStatus.OK; + } + + protected StorageOperationStatus validateAndUpdateComplexValue(IComplexDefaultValue propertyDefinition, String propertyType, + + String value, DataTypeDefinition dataTypeDefinition, Map<String, DataTypeDefinition> dataTypes) { + + ImmutablePair<JsonElement, Boolean> validateResult = dataTypeValidatorConverter.validateAndUpdate(value, dataTypeDefinition, dataTypes); + + if (validateResult.right.booleanValue() == false) { + log.debug("The value {} of property from type {} is invalid", propertyType, propertyType); + return StorageOperationStatus.INVALID_VALUE; + } + + JsonElement jsonElement = validateResult.left; + + log.trace("Going to update value in property definition {} {}" , propertyDefinition.getName() , jsonElement); + + updateValue(propertyDefinition, jsonElement); + + return StorageOperationStatus.OK; + } + + protected void updateValue(IComplexDefaultValue propertyDefinition, JsonElement jsonElement) { + + propertyDefinition.setDefaultValue(getValueFromJsonElement(jsonElement)); + + } + + 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; + } + + protected Either<String, TitanOperationStatus> getInnerType(ToscaPropertyType type, Supplier<SchemaDefinition> schemeGen) { + String innerType = null; + if (type == ToscaPropertyType.LIST || type == ToscaPropertyType.MAP) { + + SchemaDefinition def = schemeGen.get(); + if (def == null) { + log.debug("Schema doesn't exists for property of type {}", type); + return Either.right(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(TitanOperationStatus.ILLEGAL_ARGUMENT); + } + innerType = propDef.getType(); + } + return Either.left(innerType); + } + protected boolean isValidValue(ToscaPropertyType type, String value, String innerType, Map<String, DataTypeDefinition> dataTypes) { + if (isEmptyValue(value)) { + return true; + } + + PropertyTypeValidator validator = type.getValidator(); + + boolean isValid = validator.isValid(value, innerType, dataTypes); + if (true == isValid) { + return true; + } else { + return false; + } + + } + + public boolean isEmptyValue(String value) { + if (value == null) { + return true; + } + return false; + } } |