diff --git a/Photo.db b/Photo.db deleted file mode 100644 index 499428c..0000000 Binary files a/Photo.db and /dev/null differ diff --git a/Photo.db-shm b/Photo.db-shm deleted file mode 100644 index fe9ac28..0000000 Binary files a/Photo.db-shm and /dev/null differ diff --git a/Photo.db-wal b/Photo.db-wal deleted file mode 100644 index e69de29..0000000 diff --git a/src/Spg.AloMalo.Api/Controllers/PhotosCqsController.cs b/src/Spg.AloMalo.Api/Controllers/PhotosCqsController.cs index e27c594..1887d57 100644 --- a/src/Spg.AloMalo.Api/Controllers/PhotosCqsController.cs +++ b/src/Spg.AloMalo.Api/Controllers/PhotosCqsController.cs @@ -1,13 +1,9 @@ using MediatR; -using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Spg.AloMalo.Application.Services.PhotoUseCases.Query; using Spg.AloMalo.DomainModel.Commands; using Spg.AloMalo.DomainModel.Dtos; -using Spg.AloMalo.DomainModel.Exceptions; using Spg.AloMalo.DomainModel.Queries; -using static Bogus.DataSets.Name; -using static Microsoft.EntityFrameworkCore.DbLoggerCategory.Database; namespace Spg.AloMalo.Api.Controllers { @@ -26,9 +22,10 @@ public PhotosCqsController(IMediator mediator) [HttpGet()] public IActionResult GetFiltered([FromQuery] GetPhotosQuery query) { - var result = _mediator.Send( - new GetPhotosQueryModel(query) - ); + List result = _mediator + .Send(new GetPhotosQueryModel(query)) + .Result + .ToList(); return Ok(result); } diff --git a/src/Spg.AloMalo.Api/Program.cs b/src/Spg.AloMalo.Api/Program.cs index d016591..ae69ee7 100644 --- a/src/Spg.AloMalo.Api/Program.cs +++ b/src/Spg.AloMalo.Api/Program.cs @@ -117,7 +117,7 @@ options.RegisterServicesFromAssembly(Assembly.GetExecutingAssembly()); }); builder.Services.AddTransient, CreatePhotoCommandHandler>(); -builder.Services.AddTransient>, GetPhotosQueryHandler>(); +builder.Services.AddTransient>, GetPhotosQueryHandler>(); // // Build App var app = builder.Build(); diff --git a/src/Spg.AloMalo.Application/ExpressionMapper.cs b/src/Spg.AloMalo.Application/ExpressionMapper.cs new file mode 100644 index 0000000..fd3cbb3 --- /dev/null +++ b/src/Spg.AloMalo.Application/ExpressionMapper.cs @@ -0,0 +1,69 @@ +using Spg.AloMalo.DomainModel.Interfaces.Repositories; +using System.Reflection; + +namespace Spg.AloMalo.Application +{ + public class ExpressionMapper + where TEntity : class + { + private readonly PropertyInfo _propertyInfo; + private readonly string? _propertyName; + private readonly string? _value1; + private readonly string? _value2; + + public ExpressionMapper(PropertyInfo propertyInfo, string? propertyName = null + , string? value1 = null, string? value2 = null) + { + _propertyInfo = propertyInfo; + _propertyName = propertyName; + _value1 = value1; + _value2 = value2; + } + + + public void Use(Func>? action) + { + if (string.IsNullOrEmpty(_value1)) + { + return; + } + if (action is null) + { + return; + } + + T target1 = TConverter.ChangeType(_value1); + + if ((_propertyInfo?.Name?.Trim()?.ToLower() ?? string.Empty) + == (_propertyName?.Trim()?.ToLower() ?? string.Empty)) + { + action(target1); + } + } + + public void Use(Func>? action) + { + if (string.IsNullOrEmpty(_value1)) + { + return; + } + if (string.IsNullOrEmpty(_value2)) + { + return; + } + if (action is null) + { + return; + } + + T1 target1 = TConverter.ChangeType(_value1); + T2 target2 = TConverter.ChangeType(_value2); + + if ((_propertyInfo?.Name?.Trim()?.ToLower() ?? string.Empty) + == (_propertyName?.Trim()?.ToLower() ?? string.Empty)) + { + action(target1, target2); + } + } + } +} diff --git a/src/Spg.AloMalo.Application/InterpretParameterBase.cs b/src/Spg.AloMalo.Application/InterpretParameterBase.cs new file mode 100644 index 0000000..f8f9f71 --- /dev/null +++ b/src/Spg.AloMalo.Application/InterpretParameterBase.cs @@ -0,0 +1,54 @@ +using System.Linq.Expressions; +using System.Reflection; + +namespace Spg.AloMalo.Application +{ + public abstract class InterpretParameterBase + where TEntity : class + { + private readonly string _operator; + + public InterpretParameterBase(string @operator) + { + _operator = @operator; + } + + public ExpressionMapper ForProperty( + string? queryParameter, + Expression> propertyExpression) + { + MemberExpression? member = propertyExpression.Body as MemberExpression; + if (member == null) + { + throw new ArgumentException($"{propertyExpression} is a Method!"); + } + PropertyInfo? propInfo = member.Member as PropertyInfo; + if (propInfo == null) + { + throw new ArgumentException($"{propertyExpression} is a Field!"); + } + + if (string.IsNullOrEmpty(queryParameter)) + { + return new ExpressionMapper(propInfo); + } + string[] parts = queryParameter.Split(' '); + if (parts.Length < 3 || parts.Length > 4) + { + throw new ArgumentException($"Incorrect Expression ('xxxx ct xxxx' or 'xxxx bw xxxx xxxx')"); + } + if (parts[1].Trim().ToLower() == _operator.Trim().ToLower()) + { + if (parts.Length == 3) + { + return new ExpressionMapper(propInfo, parts[0], parts[2]); + } + if (parts.Length == 4) + { + return new ExpressionMapper(propInfo, parts[0], parts[2], parts[3]); + } + } + return new ExpressionMapper(propInfo); + } + } +} diff --git a/src/Spg.AloMalo.Application/Services/PhotoService.cs b/src/Spg.AloMalo.Application/Services/PhotoService.cs index bfdab22..a1edd24 100644 --- a/src/Spg.AloMalo.Application/Services/PhotoService.cs +++ b/src/Spg.AloMalo.Application/Services/PhotoService.cs @@ -37,7 +37,7 @@ public IQueryable GetPhotos() { IQueryable result = _readOnlyPhotoRepository .FilterBuilder - .ApplyNameContainsFilter("My") + //.ApplyNameContainsFilter("My") .Build() .Select(p => new PhotoDto( diff --git a/src/Spg.AloMalo.Application/Services/PhotoUseCases/Filters/NameContainsParameter.cs b/src/Spg.AloMalo.Application/Services/PhotoUseCases/Filters/NameContainsParameter.cs new file mode 100644 index 0000000..b4151d0 --- /dev/null +++ b/src/Spg.AloMalo.Application/Services/PhotoUseCases/Filters/NameContainsParameter.cs @@ -0,0 +1,27 @@ +using Spg.AloMalo.Application.Services.PhotoUseCases.Query; +using Spg.AloMalo.DomainModel.Filters; +using Spg.AloMalo.DomainModel.Interfaces.Repositories; +using Spg.AloMalo.DomainModel.Model; + +namespace Spg.AloMalo.Application.Services.PhotoUseCases.Filters +{ + public class NameContainsParameter : IQueryParameter + { + private readonly IPhotoFilterBuilder _photoFilterBuilder; + + public NameContainsParameter(IPhotoFilterBuilder photoFilterBuilder) + { + _photoFilterBuilder = photoFilterBuilder; + } + + public IPhotoFilterBuilder Compile(string queryParameter) + { + string[] parts = queryParameter.Split(' '); + if (parts.Length == 3 && parts[0]?.Trim().ToLower() == "name" && parts[1]?.Trim().ToLower() == "contains") + { + return _photoFilterBuilder.ApplyFilter(new ContainsFilter(p => p.Name, parts[2])); + } + return _photoFilterBuilder; + } + } +} diff --git a/src/Spg.AloMalo.Application/Services/PhotoUseCases/Filters/NameEndsWithParameter.cs b/src/Spg.AloMalo.Application/Services/PhotoUseCases/Filters/NameEndsWithParameter.cs new file mode 100644 index 0000000..6e05d15 --- /dev/null +++ b/src/Spg.AloMalo.Application/Services/PhotoUseCases/Filters/NameEndsWithParameter.cs @@ -0,0 +1,28 @@ +using Spg.AloMalo.Application.Services.PhotoUseCases.Query; +using Spg.AloMalo.DomainModel.Filters; +using Spg.AloMalo.DomainModel.Interfaces.Repositories; +using Spg.AloMalo.DomainModel.Model; + +namespace Spg.AloMalo.Application.Services.PhotoUseCases.Filters +{ + public class NameEndsWithParameter : IQueryParameter + { + private readonly IPhotoFilterBuilder _photoFilterBuilder; + + public NameEndsWithParameter(IPhotoFilterBuilder photoFilterBuilder) + { + _photoFilterBuilder = photoFilterBuilder; + } + + public IPhotoFilterBuilder Compile(string queryParameter) + { + string[] parts = queryParameter.Split(' '); + if (parts.Length == 3 && parts[0]?.Trim().ToLower() == "name" && parts[1]?.Trim().ToLower() == "endswith") + { + return _photoFilterBuilder.ApplyFilter(new EndsWithFilter(p => p.Name, parts[2])); + } + return _photoFilterBuilder; + } + } + +} diff --git a/src/Spg.AloMalo.Application/Services/PhotoUseCases/Filters/NameEqualsParameter.cs b/src/Spg.AloMalo.Application/Services/PhotoUseCases/Filters/NameEqualsParameter.cs new file mode 100644 index 0000000..6c081e4 --- /dev/null +++ b/src/Spg.AloMalo.Application/Services/PhotoUseCases/Filters/NameEqualsParameter.cs @@ -0,0 +1,28 @@ +using Spg.AloMalo.Application.Services.PhotoUseCases.Query; +using Spg.AloMalo.DomainModel.Filters; +using Spg.AloMalo.DomainModel.Interfaces.Repositories; +using Spg.AloMalo.DomainModel.Model; + +namespace Spg.AloMalo.Application.Services.PhotoUseCases.Filters +{ + public class NameEqualsParameter : IQueryParameter + { + private readonly IPhotoFilterBuilder _photoFilterBuilder; + + public NameEqualsParameter(IPhotoFilterBuilder photoFilterBuilder) + { + _photoFilterBuilder = photoFilterBuilder; + } + + public IPhotoFilterBuilder Compile(string queryParameter) + { + string[] parts = queryParameter.Split(' '); + if (parts.Length == 3 && parts[0]?.Trim().ToLower() == "name" && parts[1]?.Trim().ToLower() == "equals") + { + return _photoFilterBuilder.ApplyFilter(new EqualsFilter(p => p.Name, parts[2])); + } + return _photoFilterBuilder; + } + } + +} diff --git a/src/Spg.AloMalo.Application/Services/PhotoUseCases/Filters/NameRegexParameter.cs b/src/Spg.AloMalo.Application/Services/PhotoUseCases/Filters/NameRegexParameter.cs new file mode 100644 index 0000000..880b6de --- /dev/null +++ b/src/Spg.AloMalo.Application/Services/PhotoUseCases/Filters/NameRegexParameter.cs @@ -0,0 +1,28 @@ +using Spg.AloMalo.Application.Services.PhotoUseCases.Query; +using Spg.AloMalo.DomainModel.Filters; +using Spg.AloMalo.DomainModel.Interfaces.Repositories; +using Spg.AloMalo.DomainModel.Model; + +namespace Spg.AloMalo.Application.Services.PhotoUseCases.Filters +{ + public class NameRegexParameter : IQueryParameter + { + private readonly IPhotoFilterBuilder _photoFilterBuilder; + + public NameRegexParameter(IPhotoFilterBuilder photoFilterBuilder) + { + _photoFilterBuilder = photoFilterBuilder; + } + + public IPhotoFilterBuilder Compile(string queryParameter) + { + string[] parts = queryParameter.Split(' '); + if (parts.Length == 3 && parts[0]?.Trim().ToLower() == "name" && parts[1]?.Trim().ToLower() == "regex") + { + return _photoFilterBuilder.ApplyFilter(new RegexFilter(p => p.Name, parts[2])); + } + return _photoFilterBuilder; + } + } + +} diff --git a/src/Spg.AloMalo.Application/Services/PhotoUseCases/Filters/NameStartsWithParameter.cs b/src/Spg.AloMalo.Application/Services/PhotoUseCases/Filters/NameStartsWithParameter.cs new file mode 100644 index 0000000..b190268 --- /dev/null +++ b/src/Spg.AloMalo.Application/Services/PhotoUseCases/Filters/NameStartsWithParameter.cs @@ -0,0 +1,27 @@ +using Spg.AloMalo.Application.Services.PhotoUseCases.Query; +using Spg.AloMalo.DomainModel.Filters; +using Spg.AloMalo.DomainModel.Interfaces.Repositories; +using Spg.AloMalo.DomainModel.Model; + +namespace Spg.AloMalo.Application.Services.PhotoUseCases.Filters +{ + public class NameStartsWithParameter : IQueryParameter + { + private readonly IPhotoFilterBuilder _photoFilterBuilder; + + public NameStartsWithParameter(IPhotoFilterBuilder photoFilterBuilder) + { + _photoFilterBuilder = photoFilterBuilder; + } + + public IPhotoFilterBuilder Compile(string queryParameter) + { + string[] parts = queryParameter.Split(' '); + if (parts.Length == 3 && parts[0]?.Trim().ToLower() == "name" && parts[1]?.Trim().ToLower() == "startswith") + { + return _photoFilterBuilder.ApplyFilter(new StartsWithFilter(p => p.Name, parts[2])); + } + return _photoFilterBuilder; + } + } +} diff --git a/src/Spg.AloMalo.Application/Services/PhotoUseCases/Filters/PropertyFilterParameter.cs b/src/Spg.AloMalo.Application/Services/PhotoUseCases/Filters/PropertyFilterParameter.cs new file mode 100644 index 0000000..3baefcd --- /dev/null +++ b/src/Spg.AloMalo.Application/Services/PhotoUseCases/Filters/PropertyFilterParameter.cs @@ -0,0 +1,103 @@ +using Spg.AloMalo.Application.Services.PhotoUseCases.Query; +using Spg.AloMalo.DomainModel.Filters; +using Spg.AloMalo.DomainModel.Interfaces.Repositories; +using Spg.AloMalo.DomainModel.Model; +using System.Linq.Expressions; + +namespace Spg.AloMalo.Application.Services.PhotoUseCases.Filters +{ + public class PropertyFilterParameter : IQueryParameter + { + private readonly IPhotoFilterBuilder _photoFilterBuilder; + private readonly Expression> _propertyExpression; + private readonly string _operation; + private readonly string _value; + + public PropertyFilterParameter(IPhotoFilterBuilder photoFilterBuilder, Expression> propertyExpression, string operation, string value) + { + _photoFilterBuilder = photoFilterBuilder; + _propertyExpression = propertyExpression; + _operation = operation; + _value = value; + } + + public IPhotoFilterBuilder Compile(string queryParameter) + { + var parts = queryParameter.Split(' '); + if (parts.Length != 3) + throw new ArgumentException("Invalid query parameter format. Expected format: 'property operation value'"); + + var property = parts[0]; + var operation = parts[1]; + var value = parts[2]; + + switch (operation.ToLower()) + { + case "equals": + ApplyEqualsFilter(value); + break; + case "contains": + ApplyContainsFilter(value); + break; + case "startswith": + ApplyStartsWithFilter(value); + break; + case "endswith": + ApplyEndsWithFilter(value); + break; + case "regex": + ApplyRegexFilter(value); + break; + default: + throw new InvalidOperationException("Unknown operation"); + } + return _photoFilterBuilder; + } + + private void ApplyEqualsFilter(string value) + { + var propertyType = _propertyExpression.Body.Type; + var convertedValue = Convert.ChangeType(value, propertyType); + var filterType = typeof(EqualsFilter<,>).MakeGenericType(typeof(Photo), propertyType); + var filter = (EqualsFilter)Activator.CreateInstance(filterType, _propertyExpression, convertedValue); + _photoFilterBuilder.ApplyFilter(filter); + } + + private void ApplyContainsFilter(string value) + { + if (_propertyExpression.Body.Type != typeof(string)) + throw new InvalidOperationException("Contains operation is only supported for string properties"); + + var filter = new ContainsFilter(_propertyExpression as Expression>, value); + _photoFilterBuilder.ApplyFilter(filter); + } + + private void ApplyStartsWithFilter(string value) + { + if (_propertyExpression.Body.Type != typeof(string)) + throw new InvalidOperationException("StartsWith operation is only supported for string properties"); + + var filter = new StartsWithFilter(_propertyExpression as Expression>, value); + _photoFilterBuilder.ApplyFilter(filter); + } + + private void ApplyEndsWithFilter(string value) + { + if (_propertyExpression.Body.Type != typeof(string)) + throw new InvalidOperationException("EndsWith operation is only supported for string properties"); + + var filter = new EndsWithFilter(_propertyExpression as Expression>, value); + _photoFilterBuilder.ApplyFilter(filter); + } + + private void ApplyRegexFilter(string value) + { + if (_propertyExpression.Body.Type != typeof(string)) + throw new InvalidOperationException("Regex operation is only supported for string properties"); + + var filter = new RegexFilter(_propertyExpression as Expression>, value); + _photoFilterBuilder.ApplyFilter(filter); + } + + } +} diff --git a/src/Spg.AloMalo.Application/Services/PhotoUseCases/Operations/FilterBetweenOperations.cs b/src/Spg.AloMalo.Application/Services/PhotoUseCases/Operations/FilterBetweenOperations.cs new file mode 100644 index 0000000..9647a56 --- /dev/null +++ b/src/Spg.AloMalo.Application/Services/PhotoUseCases/Operations/FilterBetweenOperations.cs @@ -0,0 +1,25 @@ +using Spg.AloMalo.Application.Services.PhotoUseCases.Query; +using Spg.AloMalo.DomainModel.Interfaces.Repositories; +using Spg.AloMalo.DomainModel.Model; + +namespace Spg.AloMalo.Application.Services.PhotoUseCases.Filters +{ + public class FilterBetweenOperations : InterpretParameterBase, IQueryParameter + { + private readonly IPhotoFilterBuilder _photoFilterBuilder; + + public FilterBetweenOperations(IPhotoFilterBuilder photoFilterBuilder) + : base("bw") + { + _photoFilterBuilder = photoFilterBuilder; + } + + public IPhotoFilterBuilder Compile(string? queryParameter) + { + ForProperty(queryParameter, p => p.CreationTimeStamp) + .Use(_photoFilterBuilder.ApplyCreationTimeStampBetweenFilter); + + return _photoFilterBuilder; + } + } +} diff --git a/src/Spg.AloMalo.Application/Services/PhotoUseCases/Operations/FilterContainsOperations.cs b/src/Spg.AloMalo.Application/Services/PhotoUseCases/Operations/FilterContainsOperations.cs new file mode 100644 index 0000000..104bdf8 --- /dev/null +++ b/src/Spg.AloMalo.Application/Services/PhotoUseCases/Operations/FilterContainsOperations.cs @@ -0,0 +1,28 @@ +using Spg.AloMalo.Application.Services.PhotoUseCases.Query; +using Spg.AloMalo.DomainModel.Interfaces.Repositories; +using Spg.AloMalo.DomainModel.Model; + +namespace Spg.AloMalo.Application.Services.PhotoUseCases.Operations +{ + public class FilterContainsOperations : InterpretParameterBase, IQueryParameter + { + private readonly IPhotoFilterBuilder _photoFilterBuilder; + + public FilterContainsOperations(IPhotoFilterBuilder photoFilterBuilder) + : base("ct") + { + _photoFilterBuilder = photoFilterBuilder; + } + + public IPhotoFilterBuilder Compile(string? queryParameter) + { + ForProperty(queryParameter, p => p.Name) + .Use(_photoFilterBuilder.ApplyNameContainsFilter); + + ForProperty(queryParameter, p => p.Description) + .Use(_photoFilterBuilder.ApplyDescriptionContainsFilter); + + return _photoFilterBuilder; + } + } +} diff --git a/src/Spg.AloMalo.Application/Services/PhotoUseCases/Operations/FilterGreaterThanEqualOperations.cs b/src/Spg.AloMalo.Application/Services/PhotoUseCases/Operations/FilterGreaterThanEqualOperations.cs new file mode 100644 index 0000000..9cc6773 --- /dev/null +++ b/src/Spg.AloMalo.Application/Services/PhotoUseCases/Operations/FilterGreaterThanEqualOperations.cs @@ -0,0 +1,25 @@ +using Spg.AloMalo.Application.Services.PhotoUseCases.Query; +using Spg.AloMalo.DomainModel.Interfaces.Repositories; +using Spg.AloMalo.DomainModel.Model; + +namespace Spg.AloMalo.Application.Services.PhotoUseCases.Operations +{ + public class FilterGreaterThanEqualOperations : InterpretParameterBase, IQueryParameter + { + private readonly IPhotoFilterBuilder _photoFilterBuilder; + + public FilterGreaterThanEqualOperations(IPhotoFilterBuilder photoFilterBuilder) + : base("gte") + { + _photoFilterBuilder = photoFilterBuilder; + } + + public IPhotoFilterBuilder Compile(string? queryParameter) + { + ForProperty(queryParameter, p => p.Width) + .Use(_photoFilterBuilder.ApplyWidthGreaterThanEqualFilter); + + return _photoFilterBuilder; + } + } +} diff --git a/src/Spg.AloMalo.Application/Services/PhotoUseCases/Operations/FilterGreaterThanOperations.cs b/src/Spg.AloMalo.Application/Services/PhotoUseCases/Operations/FilterGreaterThanOperations.cs new file mode 100644 index 0000000..97f6159 --- /dev/null +++ b/src/Spg.AloMalo.Application/Services/PhotoUseCases/Operations/FilterGreaterThanOperations.cs @@ -0,0 +1,25 @@ +using Spg.AloMalo.Application.Services.PhotoUseCases.Query; +using Spg.AloMalo.DomainModel.Interfaces.Repositories; +using Spg.AloMalo.DomainModel.Model; + +namespace Spg.AloMalo.Application.Services.PhotoUseCases.Operations +{ + public class FilterGreaterThanOperations : InterpretParameterBase, IQueryParameter + { + private readonly IPhotoFilterBuilder _photoFilterBuilder; + + public FilterGreaterThanOperations(IPhotoFilterBuilder photoFilterBuilder) + : base("gt") + { + _photoFilterBuilder = photoFilterBuilder; + } + + public IPhotoFilterBuilder Compile(string? queryParameter) + { + ForProperty(queryParameter, p => p.Width) + .Use(_photoFilterBuilder.ApplyWidthGreaterThanFilter); + + return _photoFilterBuilder; + } + } +} diff --git a/src/Spg.AloMalo.Application/Services/PhotoUseCases/Operations/FilterLowerThanEqualOperations.cs b/src/Spg.AloMalo.Application/Services/PhotoUseCases/Operations/FilterLowerThanEqualOperations.cs new file mode 100644 index 0000000..b9f18d6 --- /dev/null +++ b/src/Spg.AloMalo.Application/Services/PhotoUseCases/Operations/FilterLowerThanEqualOperations.cs @@ -0,0 +1,25 @@ +using Spg.AloMalo.Application.Services.PhotoUseCases.Query; +using Spg.AloMalo.DomainModel.Interfaces.Repositories; +using Spg.AloMalo.DomainModel.Model; + +namespace Spg.AloMalo.Application.Services.PhotoUseCases.Operations +{ + public class FilterLowerThanEqualOperations : InterpretParameterBase, IQueryParameter + { + private readonly IPhotoFilterBuilder _photoFilterBuilder; + + public FilterLowerThanEqualOperations(IPhotoFilterBuilder photoFilterBuilder) + : base("lte") + { + _photoFilterBuilder = photoFilterBuilder; + } + + public IPhotoFilterBuilder Compile(string? queryParameter) + { + ForProperty(queryParameter, p => p.Width) + .Use(_photoFilterBuilder.ApplyWidthLowerThanEqualFilter); + + return _photoFilterBuilder; + } + } +} diff --git a/src/Spg.AloMalo.Application/Services/PhotoUseCases/Operations/FilterLowerThanOperations.cs b/src/Spg.AloMalo.Application/Services/PhotoUseCases/Operations/FilterLowerThanOperations.cs new file mode 100644 index 0000000..6e672d4 --- /dev/null +++ b/src/Spg.AloMalo.Application/Services/PhotoUseCases/Operations/FilterLowerThanOperations.cs @@ -0,0 +1,25 @@ +using Spg.AloMalo.Application.Services.PhotoUseCases.Query; +using Spg.AloMalo.DomainModel.Interfaces.Repositories; +using Spg.AloMalo.DomainModel.Model; + +namespace Spg.AloMalo.Application.Services.PhotoUseCases.Operations +{ + public class FilterLowerThanOperations : InterpretParameterBase, IQueryParameter + { + private readonly IPhotoFilterBuilder _photoFilterBuilder; + + public FilterLowerThanOperations(IPhotoFilterBuilder photoFilterBuilder) + : base("lt") + { + _photoFilterBuilder = photoFilterBuilder; + } + + public IPhotoFilterBuilder Compile(string? queryParameter) + { + ForProperty(queryParameter, p => p.Width) + .Use(_photoFilterBuilder.ApplyWidthLowerThanFilter); + + return _photoFilterBuilder; + } + } +} diff --git a/src/Spg.AloMalo.Application/Services/PhotoUseCases/Operations/FilterStartsWithOperations.cs b/src/Spg.AloMalo.Application/Services/PhotoUseCases/Operations/FilterStartsWithOperations.cs new file mode 100644 index 0000000..ad2012a --- /dev/null +++ b/src/Spg.AloMalo.Application/Services/PhotoUseCases/Operations/FilterStartsWithOperations.cs @@ -0,0 +1,28 @@ +using Spg.AloMalo.Application.Services.PhotoUseCases.Query; +using Spg.AloMalo.DomainModel.Interfaces.Repositories; +using Spg.AloMalo.DomainModel.Model; + +namespace Spg.AloMalo.Application.Services.PhotoUseCases.Operations +{ + public class FilterStartsWithOperations : InterpretParameterBase, IQueryParameter + { + private readonly IPhotoFilterBuilder _photoFilterBuilder; + + public FilterStartsWithOperations(IPhotoFilterBuilder photoFilterBuilder) + : base("sw") + { + _photoFilterBuilder = photoFilterBuilder; + } + + public IPhotoFilterBuilder Compile(string? queryParameter) + { + ForProperty(queryParameter, p => p.Name) + .Use(_photoFilterBuilder.ApplyNameStartsWithFilter); + + ForProperty(queryParameter, p => p.Description) + .Use(_photoFilterBuilder.ApplyDescriptionStartsWithFilter); + + return _photoFilterBuilder; + } + } +} diff --git a/src/Spg.AloMalo.Application/Services/PhotoUseCases/Query/GetPhotosQueryHandler.cs b/src/Spg.AloMalo.Application/Services/PhotoUseCases/Query/GetPhotosQueryHandler.cs index 84fed9d..d331a67 100644 --- a/src/Spg.AloMalo.Application/Services/PhotoUseCases/Query/GetPhotosQueryHandler.cs +++ b/src/Spg.AloMalo.Application/Services/PhotoUseCases/Query/GetPhotosQueryHandler.cs @@ -1,10 +1,12 @@ using MediatR; +using Spg.AloMalo.Application.Services.PhotoUseCases.Filters; +using Spg.AloMalo.Application.Services.PhotoUseCases.Operations; using Spg.AloMalo.DomainModel.Dtos; using Spg.AloMalo.DomainModel.Interfaces.Repositories; namespace Spg.AloMalo.Application.Services.PhotoUseCases.Query { - public class GetPhotosQueryHandler : IRequestHandler> + public class GetPhotosQueryHandler : IRequestHandler> { private readonly IReadOnlyPhotoRepository _photoRepository; @@ -13,26 +15,33 @@ public GetPhotosQueryHandler(IReadOnlyPhotoRepository photoRepository) _photoRepository = photoRepository; } - public Task> Handle(GetPhotosQueryModel request, CancellationToken cancellationToken) + public Task> Handle(GetPhotosQueryModel request, CancellationToken cancellationToken) { IPhotoFilterBuilder builder = - _photoRepository - .FilterBuilder; + _photoRepository + .FilterBuilder; - builder = new LastNameContainsParameter(builder) - .Compile(request.Query.Filter); - builder = new LastNameBeginsWithParameter(builder) - .Compile(request.Query.Filter); - builder = new LastNameEndsWithParameter(builder) - .Compile(request.Query.Filter); - // builder = new ... + List operations = + [ + new FilterContainsOperations(builder), + new FilterStartsWithOperations(builder), + new FilterGreaterThanOperations(builder), + new FilterGreaterThanEqualOperations(builder), + new FilterLowerThanOperations(builder), + new FilterLowerThanEqualOperations(builder), + new FilterBetweenOperations(builder), + ]; + foreach (IQueryParameter operation in operations) + { + builder = operation.Compile(request?.Query?.Filter ?? string.Empty); + } - return Task.FromResult( - builder + IQueryable result = builder .Build() - .Select(p => p.ToDto()) - .ToList() - ); + .Select(r => r.ToDto()); + + return Task.FromResult(result); } } + } diff --git a/src/Spg.AloMalo.Application/Services/PhotoUseCases/Query/GetPhotosQueryModel.cs b/src/Spg.AloMalo.Application/Services/PhotoUseCases/Query/GetPhotosQueryModel.cs index 66712c9..8ba638f 100644 --- a/src/Spg.AloMalo.Application/Services/PhotoUseCases/Query/GetPhotosQueryModel.cs +++ b/src/Spg.AloMalo.Application/Services/PhotoUseCases/Query/GetPhotosQueryModel.cs @@ -4,7 +4,7 @@ namespace Spg.AloMalo.Application.Services.PhotoUseCases.Query { - public class GetPhotosQueryModel : IRequest> + public class GetPhotosQueryModel : IRequest> { public GetPhotosQuery Query { get; } diff --git a/src/Spg.AloMalo.Application/Services/PhotoUseCases/Query/IQueryParameter.cs b/src/Spg.AloMalo.Application/Services/PhotoUseCases/Query/IQueryParameter.cs index ef1efd1..c69d7a6 100644 --- a/src/Spg.AloMalo.Application/Services/PhotoUseCases/Query/IQueryParameter.cs +++ b/src/Spg.AloMalo.Application/Services/PhotoUseCases/Query/IQueryParameter.cs @@ -1,9 +1,4 @@ using Spg.AloMalo.DomainModel.Interfaces.Repositories; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace Spg.AloMalo.Application.Services.PhotoUseCases.Query { diff --git a/src/Spg.AloMalo.Application/Services/PhotoUseCases/Query/IQueryParameter1.cs b/src/Spg.AloMalo.Application/Services/PhotoUseCases/Query/IQueryParameter1.cs deleted file mode 100644 index 1dee1a0..0000000 --- a/src/Spg.AloMalo.Application/Services/PhotoUseCases/Query/IQueryParameter1.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Spg.AloMalo.Application.Services.PhotoUseCases.Query -{ - public interface IQueryParameter - { - } -} \ No newline at end of file diff --git a/src/Spg.AloMalo.Application/Services/PhotoUseCases/Query/LastNameBeginsWithParameter.cs b/src/Spg.AloMalo.Application/Services/PhotoUseCases/Query/LastNameBeginsWithParameter.cs index 9c256f4..d538abf 100644 --- a/src/Spg.AloMalo.Application/Services/PhotoUseCases/Query/LastNameBeginsWithParameter.cs +++ b/src/Spg.AloMalo.Application/Services/PhotoUseCases/Query/LastNameBeginsWithParameter.cs @@ -2,27 +2,27 @@ namespace Spg.AloMalo.Application.Services.PhotoUseCases.Query { - public class LastNameBeginsWithParameter : IQueryParameter - { - private readonly IPhotoFilterBuilder _photoFilterBuilder; + //public class LastNameBeginsWithParameter : IQueryParameter + //{ + // private readonly IPhotoFilterBuilder _photoFilterBuilder; - public LastNameBeginsWithParameter(IPhotoFilterBuilder photoFilterBuilder) - { - _photoFilterBuilder = photoFilterBuilder; - } + // public LastNameBeginsWithParameter(IPhotoFilterBuilder photoFilterBuilder) + // { + // _photoFilterBuilder = photoFilterBuilder; + // } - public IPhotoFilterBuilder Compile(string queryParameter) - { - string[] parts = queryParameter.Split(' '); - //TODO: Checks... - if (parts[0]?.Trim().ToLower() == "name") - { - if (parts[1]?.Trim().ToLower() == "bw") - { - return _photoFilterBuilder.ApplyNameBeginsWithFilter(parts[2]); - } - } - return _photoFilterBuilder; - } - } + // public IPhotoFilterBuilder Compile(string queryParameter) + // { + // string[] parts = queryParameter.Split(' '); + // //TODO: Checks... + // if (parts[0]?.Trim().ToLower() == "name") + // { + // if (parts[1]?.Trim().ToLower() == "bw") + // { + // return _photoFilterBuilder.ApplyNameBeginsWithFilter(parts[2]); + // } + // } + // return _photoFilterBuilder; + // } + //} } diff --git a/src/Spg.AloMalo.Application/Services/PhotoUseCases/Query/LastNameContainsParameter.cs b/src/Spg.AloMalo.Application/Services/PhotoUseCases/Query/LastNameContainsParameter.cs index f4dad0c..0a6d971 100644 --- a/src/Spg.AloMalo.Application/Services/PhotoUseCases/Query/LastNameContainsParameter.cs +++ b/src/Spg.AloMalo.Application/Services/PhotoUseCases/Query/LastNameContainsParameter.cs @@ -2,27 +2,27 @@ namespace Spg.AloMalo.Application.Services.PhotoUseCases.Query { - public class LastNameContainsParameter : IQueryParameter - { - private readonly IPhotoFilterBuilder _photoFilterBuilder; + //public class LastNameContainsParameter : IQueryParameter + //{ + // private readonly IPhotoFilterBuilder _photoFilterBuilder; - public LastNameContainsParameter(IPhotoFilterBuilder photoFilterBuilder) - { - _photoFilterBuilder = photoFilterBuilder; - } + // public LastNameContainsParameter(IPhotoFilterBuilder photoFilterBuilder) + // { + // _photoFilterBuilder = photoFilterBuilder; + // } - public IPhotoFilterBuilder Compile(string queryParameter) - { - string[] parts = queryParameter.Split(' '); - //TODO: Checks... - if (parts[0]?.Trim().ToLower() == "name") - { - if (parts[1]?.Trim().ToLower() == "ct") - { - return _photoFilterBuilder.ApplyNameContainsFilter(parts[2]); - } - } - return _photoFilterBuilder; - } - } + // public IPhotoFilterBuilder Compile(string queryParameter) + // { + // string[] parts = queryParameter.Split(' '); + // //TODO: Checks... + // if (parts[0]?.Trim().ToLower() == "name") + // { + // if (parts[1]?.Trim().ToLower() == "ct") + // { + // return _photoFilterBuilder.ApplyNameContainsFilter(parts[2]); + // } + // } + // return _photoFilterBuilder; + // } + //} } diff --git a/src/Spg.AloMalo.Application/Services/PhotoUseCases/Query/LastNameEndsWithParameter.cs b/src/Spg.AloMalo.Application/Services/PhotoUseCases/Query/LastNameEndsWithParameter.cs index 896a0fa..9af5522 100644 --- a/src/Spg.AloMalo.Application/Services/PhotoUseCases/Query/LastNameEndsWithParameter.cs +++ b/src/Spg.AloMalo.Application/Services/PhotoUseCases/Query/LastNameEndsWithParameter.cs @@ -2,27 +2,27 @@ namespace Spg.AloMalo.Application.Services.PhotoUseCases.Query { - public class LastNameEndsWithParameter : IQueryParameter - { - private readonly IPhotoFilterBuilder _photoFilterBuilder; + //public class LastNameEndsWithParameter : IQueryParameter + //{ + // private readonly IPhotoFilterBuilder _photoFilterBuilder; - public LastNameEndsWithParameter(IPhotoFilterBuilder photoFilterBuilder) - { - _photoFilterBuilder = photoFilterBuilder; - } + // public LastNameEndsWithParameter(IPhotoFilterBuilder photoFilterBuilder) + // { + // _photoFilterBuilder = photoFilterBuilder; + // } - public IPhotoFilterBuilder Compile(string queryParameter) - { - string[] parts = queryParameter.Split(' '); - //TODO: Checks... - if (parts[0]?.Trim().ToLower() == "name") - { - if (parts[1]?.Trim().ToLower() == "ew") - { - return _photoFilterBuilder.ApplyNameEndsWithFilter(parts[2]); - } - } - return _photoFilterBuilder; - } - } + // public IPhotoFilterBuilder Compile(string queryParameter) + // { + // string[] parts = queryParameter.Split(' '); + // //TODO: Checks... + // if (parts[0]?.Trim().ToLower() == "name") + // { + // if (parts[1]?.Trim().ToLower() == "ew") + // { + // return _photoFilterBuilder.ApplyNameEndsWithFilter(parts[2]); + // } + // } + // return _photoFilterBuilder; + // } + //} } diff --git a/src/Spg.AloMalo.Application/TConverter.cs b/src/Spg.AloMalo.Application/TConverter.cs new file mode 100644 index 0000000..edd144d --- /dev/null +++ b/src/Spg.AloMalo.Application/TConverter.cs @@ -0,0 +1,23 @@ +using System.ComponentModel; + +namespace Spg.AloMalo.Application +{ + public static class TConverter + { + public static T ChangeType(object value) + { + return (T)ChangeType(typeof(T), value); + } + + public static object ChangeType(Type t, object value) + { + TypeConverter tc = TypeDescriptor.GetConverter(t); + return tc.ConvertFrom(value)!; + } + + public static void RegisterTypeConverter() where TC : TypeConverter + { + TypeDescriptor.AddAttributes(typeof(T), new TypeConverterAttribute(typeof(TC))); + } + } +} diff --git a/src/Spg.AloMalo.DomainModel/Filters/ContainsFilter.cs b/src/Spg.AloMalo.DomainModel/Filters/ContainsFilter.cs new file mode 100644 index 0000000..9140d5a --- /dev/null +++ b/src/Spg.AloMalo.DomainModel/Filters/ContainsFilter.cs @@ -0,0 +1,25 @@ +using Spg.AloMalo.DomainModel.Interfaces; +using System.Linq.Expressions; + +namespace Spg.AloMalo.DomainModel.Filters +{ + public class ContainsFilter : IFilter + { + private readonly Expression> _propertyExpression; + private readonly string _value; + + public ContainsFilter(Expression> propertyExpression, string value) + { + _propertyExpression = propertyExpression; + _value = value; + } + + public IQueryable Apply(IQueryable query) + { + return query.Where(Expression.Lambda>( + Expression.Call(_propertyExpression.Body, nameof(string.Contains), Type.EmptyTypes, Expression.Constant(_value)), + _propertyExpression.Parameters)); + } + } + +} diff --git a/src/Spg.AloMalo.DomainModel/Filters/EndsWithFilter.cs b/src/Spg.AloMalo.DomainModel/Filters/EndsWithFilter.cs new file mode 100644 index 0000000..4d1f066 --- /dev/null +++ b/src/Spg.AloMalo.DomainModel/Filters/EndsWithFilter.cs @@ -0,0 +1,25 @@ +using Spg.AloMalo.DomainModel.Interfaces; +using System.Linq.Expressions; + +namespace Spg.AloMalo.DomainModel.Filters +{ + public class EndsWithFilter : IFilter + { + private readonly Expression> _propertyExpression; + private readonly string _value; + + public EndsWithFilter(Expression> propertyExpression, string value) + { + _propertyExpression = propertyExpression; + _value = value; + } + + public IQueryable Apply(IQueryable query) + { + return query.Where(Expression.Lambda>( + Expression.Call(_propertyExpression.Body, nameof(string.EndsWith), Type.EmptyTypes, Expression.Constant(_value)), + _propertyExpression.Parameters)); + } + } + +} diff --git a/src/Spg.AloMalo.DomainModel/Filters/EqualsFilter.cs b/src/Spg.AloMalo.DomainModel/Filters/EqualsFilter.cs new file mode 100644 index 0000000..ce702ab --- /dev/null +++ b/src/Spg.AloMalo.DomainModel/Filters/EqualsFilter.cs @@ -0,0 +1,23 @@ +using Spg.AloMalo.DomainModel.Interfaces; +using System.Linq.Expressions; + +namespace Spg.AloMalo.DomainModel.Filters +{ + public class EqualsFilter : IFilter + { + private readonly Expression> _propertyExpression; + private readonly TProperty _value; + + public EqualsFilter(Expression> propertyExpression, TProperty value) + { + _propertyExpression = propertyExpression; + _value = value; + } + + public IQueryable Apply(IQueryable query) + { + return query.Where(Expression.Lambda>( + Expression.Equal(_propertyExpression.Body, Expression.Constant(_value)), _propertyExpression.Parameters)); + } + } +} diff --git a/src/Spg.AloMalo.DomainModel/Filters/RegexFilter.cs b/src/Spg.AloMalo.DomainModel/Filters/RegexFilter.cs new file mode 100644 index 0000000..fcbb72a --- /dev/null +++ b/src/Spg.AloMalo.DomainModel/Filters/RegexFilter.cs @@ -0,0 +1,29 @@ +using Spg.AloMalo.DomainModel.Interfaces; +using System.Linq.Expressions; +using System.Text.RegularExpressions; + +namespace Spg.AloMalo.DomainModel.Filters +{ + public class RegexFilter : IFilter + { + private readonly Expression> _propertyExpression; + private readonly string _pattern; + + public RegexFilter(Expression> propertyExpression, string pattern) + { + _propertyExpression = propertyExpression; + _pattern = pattern; + } + + public IQueryable Apply(IQueryable query) + { + var parameter = _propertyExpression.Parameters.Single(); + var body = Expression.Call( + typeof(Regex).GetMethod(nameof(Regex.IsMatch), new[] { typeof(string), typeof(string) }), + _propertyExpression.Body, + Expression.Constant(_pattern)); + var predicate = Expression.Lambda>(body, parameter); + return query.Where(predicate); + } + } +} diff --git a/src/Spg.AloMalo.DomainModel/Filters/StartsWithFilter.cs b/src/Spg.AloMalo.DomainModel/Filters/StartsWithFilter.cs new file mode 100644 index 0000000..89857b0 --- /dev/null +++ b/src/Spg.AloMalo.DomainModel/Filters/StartsWithFilter.cs @@ -0,0 +1,25 @@ +using Spg.AloMalo.DomainModel.Interfaces; +using System.Linq.Expressions; + +namespace Spg.AloMalo.DomainModel.Filters +{ + public class StartsWithFilter : IFilter + { + private readonly Expression> _propertyExpression; + private readonly string _value; + + public StartsWithFilter(Expression> propertyExpression, string value) + { + _propertyExpression = propertyExpression; + _value = value; + } + + public IQueryable Apply(IQueryable query) + { + return query.Where(Expression.Lambda>( + Expression.Call(_propertyExpression.Body, nameof(string.StartsWith), Type.EmptyTypes, Expression.Constant(_value)), + _propertyExpression.Parameters)); + } + } + +} diff --git a/src/Spg.AloMalo.DomainModel/Interfaces/IFilter.cs b/src/Spg.AloMalo.DomainModel/Interfaces/IFilter.cs new file mode 100644 index 0000000..59c4ae5 --- /dev/null +++ b/src/Spg.AloMalo.DomainModel/Interfaces/IFilter.cs @@ -0,0 +1,8 @@ +namespace Spg.AloMalo.DomainModel.Interfaces +{ + public interface IFilter + { + IQueryable Apply(IQueryable query); + } + +} diff --git a/src/Spg.AloMalo.DomainModel/Interfaces/Repositories/IPhotoFilterBuilder.cs b/src/Spg.AloMalo.DomainModel/Interfaces/Repositories/IPhotoFilterBuilder.cs index 34e6727..dc2803f 100644 --- a/src/Spg.AloMalo.DomainModel/Interfaces/Repositories/IPhotoFilterBuilder.cs +++ b/src/Spg.AloMalo.DomainModel/Interfaces/Repositories/IPhotoFilterBuilder.cs @@ -4,12 +4,17 @@ namespace Spg.AloMalo.DomainModel.Interfaces.Repositories { public interface IPhotoFilterBuilder : IEntityFilterBuilder { - IPhotoFilterBuilder ApplyIdFilter(PhotoId id); - IPhotoFilterBuilder ApplyNameContainsFilter(string filter); - IPhotoFilterBuilder ApplyNameBeginsWithFilter(string filter); - IPhotoFilterBuilder ApplyNameEndsWithFilter(string filter); - IPhotoFilterBuilder ApplyOrientationFilter(Orientations orientation); - IPhotoFilterBuilder ApplyAiFilter(bool @is); - //IPhotoFilterBuilder ApplyPaging(int page, int size); + IQueryable EntityList { get; set; } + IPhotoFilterBuilder ApplyFilter(IFilter filter); + IQueryable Build(); + IPhotoFilterBuilder ApplyWidthGreaterThanFilter(int start); + IPhotoFilterBuilder ApplyWidthGreaterThanEqualFilter(int start); + IPhotoFilterBuilder ApplyWidthLowerThanFilter(int start); + IPhotoFilterBuilder ApplyWidthLowerThanEqualFilter(int start); + IPhotoFilterBuilder ApplyNameContainsFilter(string namePart); + IPhotoFilterBuilder ApplyDescriptionContainsFilter(string namePart); + IPhotoFilterBuilder ApplyNameStartsWithFilter(string namePart); + IPhotoFilterBuilder ApplyDescriptionStartsWithFilter(string namePart); + IPhotoFilterBuilder ApplyCreationTimeStampBetweenFilter(DateTime start, DateTime end); } } diff --git a/src/Spg.AloMalo.DomainModel/Queries/GetPhotosQuery.cs b/src/Spg.AloMalo.DomainModel/Queries/GetPhotosQuery.cs index db63077..8475e1a 100644 --- a/src/Spg.AloMalo.DomainModel/Queries/GetPhotosQuery.cs +++ b/src/Spg.AloMalo.DomainModel/Queries/GetPhotosQuery.cs @@ -1,12 +1,5 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Spg.AloMalo.DomainModel.Queries +namespace Spg.AloMalo.DomainModel.Queries { public record GetPhotosQuery( - string Filter, - string Order); + string? Filter = null); } diff --git a/src/Spg.AloMalo.Repository/Builder/PhotoFilterBuilder.cs b/src/Spg.AloMalo.Repository/Builder/PhotoFilterBuilder.cs index 617dc37..c08cc73 100644 --- a/src/Spg.AloMalo.Repository/Builder/PhotoFilterBuilder.cs +++ b/src/Spg.AloMalo.Repository/Builder/PhotoFilterBuilder.cs @@ -1,10 +1,13 @@ -using Spg.AloMalo.DomainModel.Interfaces.Repositories; +using Spg.AloMalo.DomainModel.Interfaces; +using Spg.AloMalo.DomainModel.Interfaces.Repositories; using Spg.AloMalo.DomainModel.Model; namespace Spg.AloMalo.Repository.Builder { public class PhotoFilterBuilder : IPhotoFilterBuilder { + private readonly List> _filters = new(); + public IQueryable EntityList { get; set; } public PhotoFilterBuilder(IQueryable photos) @@ -12,40 +15,79 @@ public PhotoFilterBuilder(IQueryable photos) EntityList = photos; } + public IPhotoFilterBuilder ApplyFilter(IFilter filter) + { + _filters.Add(filter); + return this; + } + public IQueryable Build() { - return EntityList; + var query = EntityList; + foreach (var filter in _filters) + { + query = filter.Apply(query); + } + return query; } - public IPhotoFilterBuilder ApplyIdFilter(PhotoId id) + public IPhotoFilterBuilder ApplyWidthGreaterThanFilter(int start) { - EntityList = EntityList.Where(x => x.Id == id); + EntityList = EntityList.Where(x => x.Width > start); return this; } - public IPhotoFilterBuilder ApplyNameContainsFilter(string name) + + public IPhotoFilterBuilder ApplyWidthGreaterThanEqualFilter(int start) { - EntityList = EntityList.Where(x => x.Name.Contains(name)); + EntityList = EntityList.Where(x => x.Width >= start); return this; } - public IPhotoFilterBuilder ApplyNameBeginsWithFilter(string name) + + public IPhotoFilterBuilder ApplyWidthLowerThanFilter(int start) { - EntityList = EntityList.Where(x => x.Name.StartsWith(name)); + EntityList = EntityList.Where(x => x.Width < start); return this; } - public IPhotoFilterBuilder ApplyNameEndsWithFilter(string name) + + public IPhotoFilterBuilder ApplyWidthLowerThanEqualFilter(int start) { - EntityList = EntityList.Where(x => x.Name.EndsWith(name)); + EntityList = EntityList.Where(x => x.Width <= start); return this; } - public IPhotoFilterBuilder ApplyOrientationFilter(Orientations orientation) + + public IPhotoFilterBuilder ApplyNameContainsFilter(string namePart) { - EntityList = EntityList.Where(x => x.Orientation == orientation); + EntityList = EntityList.Where(x => x.Name.Trim().ToLower() + .Contains(namePart.Trim().ToLower())); return this; } - public IPhotoFilterBuilder ApplyAiFilter(bool @is) + + public IPhotoFilterBuilder ApplyDescriptionContainsFilter(string namePart) { - EntityList = EntityList.Where(x => x.AiGenerated == @is); + EntityList = EntityList.Where(x => x.Description.Trim().ToLower() + .Contains(namePart.Trim().ToLower())); + return this; + } + + public IPhotoFilterBuilder ApplyNameStartsWithFilter(string namePart) + { + EntityList = EntityList.Where(x => x.Name.Trim().ToLower() + .StartsWith(namePart.Trim().ToLower())); + return this; + } + + public IPhotoFilterBuilder ApplyDescriptionStartsWithFilter(string namePart) + { + EntityList = EntityList.Where(x => x.Description.Trim().ToLower() + .StartsWith(namePart.Trim().ToLower())); + return this; + } + + public IPhotoFilterBuilder ApplyCreationTimeStampBetweenFilter(DateTime start, DateTime end) + { + EntityList = EntityList.Where(x => x.CreationTimeStamp > start && x.CreationTimeStamp < end); return this; } } + } diff --git a/test/Spg.AloMalo.Application.Test/PhotoServiceTests.cs b/test/Spg.AloMalo.Application.Test/PhotoServiceTests.cs index d88adfb..1682c62 100644 --- a/test/Spg.AloMalo.Application.Test/PhotoServiceTests.cs +++ b/test/Spg.AloMalo.Application.Test/PhotoServiceTests.cs @@ -1,4 +1,11 @@ -namespace Spg.AloMalo.Application.Test +using Spg.AloMalo.Application.Services.PhotoUseCases.Query; +using Spg.AloMalo.DomainModel.Dtos; +using Spg.AloMalo.DomainModel.Test.Helpers; +using Spg.AloMalo.Infrastructure; +using Spg.AloMalo.Repository.Builder; +using Spg.AloMalo.Repository.Repositories; + +namespace Spg.AloMalo.Application.Test { public class PhotoServiceTests { @@ -7,5 +14,142 @@ public void OK_Test() { Assert.True(true); } + + [Fact] + public void TestIfInsertWorks() + { + using (PhotoContext db = DatabaseUtilities.CreateDb()) + { + db.Photos.AddRange(DatabaseUtilities.GetSeedingPhotos(DatabaseUtilities.GetSeedingPhotographers())); + db.SaveChanges(); + Assert.Equal(8, db.Photos.Count()); + } + } + + [Fact] + public void Should_Get4Photos_When_NameStartsWithB() + { + using (PhotoContext db = DatabaseUtilities.CreateDb()) + { + db.Photos.AddRange(DatabaseUtilities.GetSeedingPhotos(DatabaseUtilities.GetSeedingPhotographers())); + db.SaveChanges(); + GetPhotosQueryModel model = new GetPhotosQueryModel( + new DomainModel.Queries.GetPhotosQuery("name sw b")); + + GetPhotosQueryHandler handler = new GetPhotosQueryHandler( + new PhotoRepository(db, new PhotoFilterBuilder(db.Photos), new PhotoUpdateBuilder(db))); + IQueryable result = handler.Handle(model, CancellationToken.None).Result; + + Assert.Equal(4, result.Count()); + } + } + + [Fact] + public void Should_Get0Photos_When_DateBetween2020And2022() + { + using (PhotoContext db = DatabaseUtilities.CreateDb()) + { + db.Photos.AddRange(DatabaseUtilities.GetSeedingPhotos(DatabaseUtilities.GetSeedingPhotographers())); + db.SaveChanges(); + GetPhotosQueryModel model = new GetPhotosQueryModel( + new DomainModel.Queries.GetPhotosQuery("creationtimestamp bw 2020.01.01 2022.12.31")); + + GetPhotosQueryHandler handler = new GetPhotosQueryHandler( + new PhotoRepository(db, new PhotoFilterBuilder(db.Photos), new PhotoUpdateBuilder(db))); + IQueryable result = handler.Handle(model, CancellationToken.None).Result; + + Assert.Equal(0, result.Count()); + } + } + + [Fact] + public void Should_Get2Photos_When_NameContainsE() + { + using (PhotoContext db = DatabaseUtilities.CreateDb()) + { + db.Photos.AddRange(DatabaseUtilities.GetSeedingPhotos(DatabaseUtilities.GetSeedingPhotographers())); + db.SaveChanges(); + GetPhotosQueryModel model = new GetPhotosQueryModel( + new DomainModel.Queries.GetPhotosQuery("name ct e")); + + GetPhotosQueryHandler handler = new GetPhotosQueryHandler( + new PhotoRepository(db, new PhotoFilterBuilder(db.Photos), new PhotoUpdateBuilder(db))); + IQueryable result = handler.Handle(model, CancellationToken.None).Result; + + Assert.Equal(2, result.Count()); + } + } + + [Fact] + public void Should_Get5Photos_When_WidthGreaterThan200() + { + using (PhotoContext db = DatabaseUtilities.CreateDb()) + { + db.Photos.AddRange(DatabaseUtilities.GetSeedingPhotos(DatabaseUtilities.GetSeedingPhotographers())); + db.SaveChanges(); + GetPhotosQueryModel model = new GetPhotosQueryModel( + new DomainModel.Queries.GetPhotosQuery("width gt 200")); + + GetPhotosQueryHandler handler = new GetPhotosQueryHandler( + new PhotoRepository(db, new PhotoFilterBuilder(db.Photos), new PhotoUpdateBuilder(db))); + IQueryable result = handler.Handle(model, CancellationToken.None).Result; + + Assert.Equal(5, result.Count()); + } + } + + [Fact] + public void Should_Get8Photos_When_WidthGreaterThanEqual200() + { + using (PhotoContext db = DatabaseUtilities.CreateDb()) + { + db.Photos.AddRange(DatabaseUtilities.GetSeedingPhotos(DatabaseUtilities.GetSeedingPhotographers())); + db.SaveChanges(); + GetPhotosQueryModel model = new GetPhotosQueryModel( + new DomainModel.Queries.GetPhotosQuery("width gte 200")); + + GetPhotosQueryHandler handler = new GetPhotosQueryHandler( + new PhotoRepository(db, new PhotoFilterBuilder(db.Photos), new PhotoUpdateBuilder(db))); + IQueryable result = handler.Handle(model, CancellationToken.None).Result; + + Assert.Equal(8, result.Count()); + } + } + + [Fact] + public void Should_Get5Photos_When_WidthLowerThan500() + { + using (PhotoContext db = DatabaseUtilities.CreateDb()) + { + db.Photos.AddRange(DatabaseUtilities.GetSeedingPhotos(DatabaseUtilities.GetSeedingPhotographers())); + db.SaveChanges(); + GetPhotosQueryModel model = new GetPhotosQueryModel( + new DomainModel.Queries.GetPhotosQuery("width lt 500")); + + GetPhotosQueryHandler handler = new GetPhotosQueryHandler( + new PhotoRepository(db, new PhotoFilterBuilder(db.Photos), new PhotoUpdateBuilder(db))); + IQueryable result = handler.Handle(model, CancellationToken.None).Result; + + Assert.Equal(5, result.Count()); + } + } + + [Fact] + public void Should_Get7Photos_When_WidthLowerThanEqual800() + { + using (PhotoContext db = DatabaseUtilities.CreateDb()) + { + db.Photos.AddRange(DatabaseUtilities.GetSeedingPhotos(DatabaseUtilities.GetSeedingPhotographers())); + db.SaveChanges(); + GetPhotosQueryModel model = new GetPhotosQueryModel( + new DomainModel.Queries.GetPhotosQuery("width lte 800")); + + GetPhotosQueryHandler handler = new GetPhotosQueryHandler( + new PhotoRepository(db, new PhotoFilterBuilder(db.Photos), new PhotoUpdateBuilder(db))); + IQueryable result = handler.Handle(model, CancellationToken.None).Result; + + Assert.Equal(7, result.Count()); + } + } } } diff --git a/test/Spg.AloMalo.Application.Test/Spg.AloMalo.Application.Test.csproj b/test/Spg.AloMalo.Application.Test/Spg.AloMalo.Application.Test.csproj index 3018ca0..8343e88 100644 --- a/test/Spg.AloMalo.Application.Test/Spg.AloMalo.Application.Test.csproj +++ b/test/Spg.AloMalo.Application.Test/Spg.AloMalo.Application.Test.csproj @@ -26,6 +26,9 @@ + + +