107 lines
5.1 KiB
C#
107 lines
5.1 KiB
C#
using Ardalis.Specification;
|
|
using DD.Persistence.Database.EntityAbstractions;
|
|
using DD.Persistence.Database.Postgres.Extensions;
|
|
using DD.Persistence.Database.Specifications;
|
|
using DD.Persistence.Database.Specifications.ValuesItem;
|
|
using DD.Persistence.Filter.Models;
|
|
using DD.Persistence.Filter.Models.Abstractions;
|
|
using DD.Persistence.Filter.Models.Enumerations;
|
|
using DD.Persistence.Filter.Visitors;
|
|
using DD.Persistence.Models;
|
|
using System.Text.Json;
|
|
|
|
namespace DD.Persistence.Database.Postgres.Helpers;
|
|
public static class FilterBuilder
|
|
{
|
|
public static ISpecification<TEntity>? BuildFilter<TEntity>(this DataSchemeDto dataSchemeDto, TNode root)
|
|
where TEntity : IValuesItem
|
|
{
|
|
var result = dataSchemeDto.BuildSpecificationByNextNode<TEntity>(root);
|
|
|
|
return result;
|
|
}
|
|
|
|
private static ISpecification<TEntity>? BuildSpecificationByNextNode<TEntity>(this DataSchemeDto dataSchemeDto, TNode node)
|
|
where TEntity : IValuesItem
|
|
{
|
|
var visitor = new NodeVisitor<ISpecification<TEntity>?>(
|
|
dataSchemeDto.VertexProcessing<TEntity>,
|
|
dataSchemeDto.LeafProcessing<TEntity>
|
|
);
|
|
|
|
var result = node.AcceptVisitor(visitor);
|
|
|
|
return result;
|
|
}
|
|
|
|
private static ISpecification<TEntity>? VertexProcessing<TEntity>(this DataSchemeDto dataSchemeDto, TVertex vertex)
|
|
where TEntity : IValuesItem
|
|
{
|
|
var leftSpecification = dataSchemeDto.BuildSpecificationByNextNode<TEntity>(vertex.Left);
|
|
var rigthSpecification = dataSchemeDto.BuildSpecificationByNextNode<TEntity>(vertex.Rigth);
|
|
if (leftSpecification is null)
|
|
return rigthSpecification;
|
|
if (rigthSpecification is null)
|
|
return leftSpecification;
|
|
|
|
ISpecification<TEntity>? result = null;
|
|
switch (vertex.Operation)
|
|
{
|
|
case OperationEnum.And:
|
|
result = new AndSpecification<TEntity>(leftSpecification, rigthSpecification);
|
|
break;
|
|
case OperationEnum.Or:
|
|
result = new OrSpecification<TEntity>(leftSpecification, rigthSpecification);
|
|
break;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
private static ISpecification<TEntity>? LeafProcessing<TEntity>(this DataSchemeDto dataSchemeDto, TLeaf leaf)
|
|
where TEntity : IValuesItem
|
|
{
|
|
var schemeProperty = dataSchemeDto.FirstOrDefault(e => e.PropertyName.Equals(leaf.PropName));
|
|
if (schemeProperty is null)
|
|
throw new ArgumentException($"Свойство {leaf.PropName} не найдено в схеме данных");
|
|
|
|
ISpecification<TEntity>? result = null;
|
|
switch (schemeProperty.PropertyKind)
|
|
{
|
|
case JsonValueKind.String:
|
|
var stringValue = Convert.ToString(leaf.Value);
|
|
var stringSpecifications = StringSpecifications<TEntity>();
|
|
result = stringSpecifications[leaf.Operation](schemeProperty.Index, stringValue);
|
|
break;
|
|
case JsonValueKind.Number:
|
|
var doubleValue = Convert.ToDouble(leaf.Value);
|
|
var doubleSpecifications = DoubleSpecifications<TEntity>();
|
|
result = doubleSpecifications[leaf.Operation](schemeProperty.Index, doubleValue);
|
|
break;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
private static Dictionary<OperationEnum, Func<int, string?, ISpecification<TEntity>>> StringSpecifications<TEntity>()
|
|
where TEntity : IValuesItem => new()
|
|
{
|
|
{ OperationEnum.Equal, (int index, string? value) => new ValueEqaulSpecification<TEntity>(index, value) },
|
|
{ OperationEnum.NotEqual, (int index, string? value) => new ValueNotEqualSpecification<TEntity>(index, value) },
|
|
{ OperationEnum.Greate, (int index, string? value) => new ValueGreateSpecification<TEntity>(index, value) },
|
|
{ OperationEnum.GreateOrEqual, (int index, string? value) => new ValueGreateOrEqualSpecification<TEntity>(index, value) },
|
|
{ OperationEnum.Less, (int index, string? value) => new ValueLessSpecification<TEntity>(index, value) },
|
|
{ OperationEnum.LessOrEqual, (int index, string? value) => new ValueLessOrEqualSpecification<TEntity>(index, value) }
|
|
};
|
|
private static Dictionary<OperationEnum, Func<int, double?, ISpecification<TEntity>>> DoubleSpecifications<TEntity>()
|
|
where TEntity : IValuesItem => new()
|
|
{
|
|
{ OperationEnum.Equal, (int index, double? value) => new ValueEqaulSpecification<TEntity>(index, value) },
|
|
{ OperationEnum.NotEqual, (int index, double? value) => new ValueNotEqualSpecification<TEntity>(index, value) },
|
|
{ OperationEnum.Greate, (int index, double? value) => new ValueGreateSpecification<TEntity>(index, value) },
|
|
{ OperationEnum.GreateOrEqual, (int index, double? value) => new ValueGreateOrEqualSpecification<TEntity>(index, value) },
|
|
{ OperationEnum.Less, (int index, double? value) => new ValueLessSpecification<TEntity>(index, value) },
|
|
{ OperationEnum.LessOrEqual, (int index, double? value) => new ValueLessOrEqualSpecification<TEntity>(index, value) }
|
|
};
|
|
}
|