diff options
Diffstat (limited to 'dropped/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/ColumnMetadata.cs')
-rw-r--r-- | dropped/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/ColumnMetadata.cs | 188 |
1 files changed, 188 insertions, 0 deletions
diff --git a/dropped/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/ColumnMetadata.cs b/dropped/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/ColumnMetadata.cs new file mode 100644 index 0000000..7247ff1 --- /dev/null +++ b/dropped/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/ColumnMetadata.cs @@ -0,0 +1,188 @@ +namespace CrupestApi.Commons.Crud; + +public static class ColumnMetadataKeys +{ + public const string ColumnName = nameof(ColumnAttribute.ColumnName); + public const string NotNull = nameof(ColumnAttribute.NotNull); + public const string IsPrimaryKey = nameof(ColumnAttribute.IsPrimaryKey); + public const string Index = nameof(ColumnAttribute.Index); + + /// <summary> + /// This will add hooks for string type column to coerce null to ""(empty string) when get or set. No effect on non-string type. + /// </summary> + public const string DefaultEmptyForString = nameof(ColumnAttribute.DefaultEmptyForString); + + /// <summary> + /// This indicates that you take care of generate this column value when create entity. User calling the api can not specify the value. + /// </summary> + public const string OnlyGenerated = nameof(ColumnAttribute.OnlyGenerated); + + /// <summary> + /// The default value generator method name in entity type. Default to null, aka, search for ColumnNameDefaultValueGenerator. + /// Generator has signature <code>static void DefaultValueGenerator(ColumnInfo column)</code> + /// </summary> + public const string DefaultValueGenerator = nameof(ColumnAttribute.DefaultValueGenerator); + + /// <summary> + /// The validator method name in entity type. Default to null, aka, the default validator. + /// Validator has signature <code>static void Validator(ColumnInfo column, object value)</code> + /// Value param is never null. If you want to mean NULL, it should be a <see cref="DbNullValue"/>. + /// </summary> + public const string Validator = nameof(ColumnAttribute.Validator); + + /// <summary> + /// The column can only be set when inserted, can't be changed in update. + /// </summary> + /// <returns></returns> + public const string NoUpdate = nameof(ColumnAttribute.NoUpdate); + + /// <summary> + /// This column acts as key when get one entity for http get method in path. + /// </summary> + public const string ActAsKey = nameof(ColumnAttribute.ActAsKey); + + /// <summary> + /// The default value used for the column. + /// </summary> + public const string DefaultValue = nameof(ColumnAttribute.DefaultValue); +} + +public interface IColumnMetadata +{ + bool TryGetValue(string key, out object? value); + + object? GetValueOrDefault(string key) + { + if (TryGetValue(key, out var value)) + { + return value; + } + else + { + return null; + } + } + + T? GetValueOrDefault<T>(string key) + { + return (T?)GetValueOrDefault(key); + } + + object? this[string key] + { + get + { + if (TryGetValue(key, out var value)) + { + return value; + } + else + { + throw new KeyNotFoundException("Key not found."); + } + } + } +} + +public enum ColumnIndexType +{ + None, + Unique, + NonUnique +} + +[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] +public class ColumnAttribute : Attribute, IColumnMetadata +{ + // if null, use the property name. + public string? ColumnName { get; init; } + + // default false. + public bool NotNull { get; init; } + + // default false + public bool IsPrimaryKey { get; init; } + + // default None + public ColumnIndexType Index { get; init; } = ColumnIndexType.None; + + /// <seealso cref="ColumnMetadataKeys.DefaultEmptyForString"/> + public bool DefaultEmptyForString { get; init; } + + /// <seealso cref="ColumnMetadataKeys.OnlyGenerated"/> + public bool OnlyGenerated { get; init; } + + /// <seealso cref="ColumnMetadataKeys.DefaultValueGenerator"/> + public string? DefaultValueGenerator { get; init; } + + /// <seealso cref="ColumnMetadataKeys.Validator"/> + public string? Validator { get; init; } + + /// <seealso cref="ColumnMetadataKeys.NoUpdate"/> + public bool NoUpdate { get; init; } + + /// <seealso cref="ColumnMetadataKeys.ActAsKey"/> + public bool ActAsKey { get; init; } + + public object? DefaultValue { get; init; } + + public bool TryGetValue(string key, out object? value) + { + var property = GetType().GetProperty(key); + if (property is null) + { + value = null; + return false; + } + value = property.GetValue(this); + return true; + } +} + +public class AggregateColumnMetadata : IColumnMetadata +{ + private IDictionary<string, object?> _own = new Dictionary<string, object?>(); + private IList<IColumnMetadata> _children = new List<IColumnMetadata>(); + + public void Add(string key, object? value) + { + _own[key] = value; + } + + public void Remove(string key) + { + _own.Remove(key); + } + + public void Add(IColumnMetadata child) + { + _children.Add(child); + } + + public void Remove(IColumnMetadata child) + { + _children.Remove(child); + } + + public bool TryGetValue(string key, out object? value) + { + if (_own.ContainsKey(key)) + { + value = _own[key]; + return true; + } + + bool found = false; + value = null; + foreach (var child in _children) + { + if (child.TryGetValue(key, out var tempValue)) + { + value = tempValue; + found = true; + } + } + + return found; + } +} |