< Summary - Code Coverage

Information
Class: Plainquire.Filter.ValueFilterExpressions.EnumFilterExpression
Assembly: Plainquire.Filter
File(s): /home/runner/work/plainquire/plainquire/Plainquire.Filter/Plainquire.Filter/ValueFilterExpressions/EnumFilterExpression.cs
Tag: 64_13932151703
Line coverage
98%
Covered lines: 65
Uncovered lines: 1
Coverable lines: 66
Total lines: 130
Line coverage: 98.4%
Branch coverage
93%
Covered branches: 28
Total branches: 30
Branch coverage: 93.3%
Method coverage
100%
Covered methods: 7
Total methods: 7
Method coverage: 100%

Metrics

MethodBranch coverage Cyclomatic complexity NPath complexity Sequence coverage
CanCreateExpressionFor(...)100%11100%
CreateExpressionForValue(...)100%66100%
CreateEnumFromStringExpression(...)100%22100%
CreateEnumExpressionByFilterOperator(...)91.66%121288.88%
GetEnumValuesMatchByStringFilter(...)100%88100%
EnumGetName(...)50%22100%

File(s)

/home/runner/work/plainquire/plainquire/Plainquire.Filter/Plainquire.Filter/ValueFilterExpressions/EnumFilterExpression.cs

#LineLine coverage
 1using Plainquire.Filter.Abstractions;
 2using System;
 3using System.Collections.Generic;
 4using System.Globalization;
 5using System.Linq;
 6using System.Linq.Expressions;
 7
 8namespace Plainquire.Filter.ValueFilterExpressions;
 9
 10/// <inheritdoc cref="IEnumFilterExpression"/>
 11public class EnumFilterExpression : DefaultFilterExpression, IEnumFilterExpression
 12{
 13    /// <inheritdoc />
 14    public override ICollection<FilterOperator> SupportedFilterOperators
 15        =>
 357616        [
 357617            FilterOperator.Default,
 357618            FilterOperator.Contains,
 357619            FilterOperator.StartsWith,
 357620            FilterOperator.EndsWith,
 357621            FilterOperator.EqualCaseSensitive,
 357622            FilterOperator.EqualCaseInsensitive,
 357623            FilterOperator.NotEqual,
 357624            FilterOperator.LessThan,
 357625            FilterOperator.LessThanOrEqual,
 357626            FilterOperator.GreaterThan,
 357627            FilterOperator.GreaterThanOrEqual,
 357628            FilterOperator.IsNull,
 357629            FilterOperator.NotNull
 357630        ];
 31
 32    /// <inheritdoc />
 33    public override bool CanCreateExpressionFor(Type type)
 372334        => type.GetUnderlyingType().IsEnum;
 35
 36    /// <inheritdoc />
 37    protected internal override Expression CreateExpressionForValue<TEntity, TProperty>(Expression<Func<TEntity, TProper
 38    {
 348039        var operatorImpliesMatchByName = filterOperator is FilterOperator.Contains or FilterOperator.StartsWith or Filte
 348040        if (operatorImpliesMatchByName)
 98441            return CreateEnumFromStringExpression(propertySelector, filterOperator, value, configuration, interceptor);
 42
 249643        var valueIsNumeric = long.TryParse(value, NumberStyles.Any, new CultureInfo(configuration.CultureName), out var 
 249644        if (!valueIsNumeric)
 153645            return CreateEnumFromStringExpression(propertySelector, filterOperator, value, configuration, interceptor);
 46
 96047        var enumValue = (TProperty)Enum.ToObject(typeof(TProperty).GetUnderlyingType(), numericValue);
 96048        return CreateEnumExpressionByFilterOperator(propertySelector, filterOperator, enumValue);
 49    }
 50
 51    private Expression CreateEnumFromStringExpression<TEntity, TProperty>(Expression<Func<TEntity, TProperty>> propertyS
 52    {
 252053        var enumValues = GetEnumValuesMatchByStringFilter<TProperty>(filterOperator, value, configuration, interceptor).
 252054        if (!enumValues.Any())
 86455            return Expression.Constant(false);
 56
 165657        var result = enumValues
 165658            .Select(x => CreateEnumExpressionByFilterOperator(propertySelector, filterOperator, x))
 165659            .Aggregate(Expression.OrElse);
 60
 165661        return result;
 62    }
 63
 64    private Expression CreateEnumExpressionByFilterOperator<TEntity, TProperty, TEnum>(Expression<Func<TEntity, TPropert
 65    {
 343266        var underlyingEnumType = Enum.GetUnderlyingType(typeof(TProperty).GetUnderlyingType());
 343267        var numericEnumValue = Convert.ChangeType(value, underlyingEnumType, CultureInfo.InvariantCulture);
 68
 69        switch (filterOperator)
 70        {
 71            case FilterOperator.Default:
 72            case FilterOperator.Contains:
 73            case FilterOperator.StartsWith:
 74            case FilterOperator.EndsWith:
 75            case FilterOperator.EqualCaseInsensitive:
 76            case FilterOperator.EqualCaseSensitive:
 211277                return CreateEqualExpression(propertySelector, value);
 78            case FilterOperator.NotEqual:
 26479                return CreateNotEqualExpression(propertySelector, value);
 80            case FilterOperator.LessThan:
 26481                return CreateLessThanExpression(propertySelector, underlyingEnumType, numericEnumValue);
 82            case FilterOperator.LessThanOrEqual:
 26483                return CreateLessThanOrEqualExpression(propertySelector, underlyingEnumType, numericEnumValue);
 84            case FilterOperator.GreaterThan:
 26485                return CreateGreaterThanExpression(propertySelector, underlyingEnumType, numericEnumValue);
 86            case FilterOperator.GreaterThanOrEqual:
 26487                return CreateGreaterThanOrEqualExpression(propertySelector, underlyingEnumType, numericEnumValue);
 88            default:
 089                throw CreateFilterExpressionCreationException($"Filter operator '{filterOperator}' not allowed for prope
 90        }
 91    }
 92
 93    private static IEnumerable<TProperty> GetEnumValuesMatchByStringFilter<TProperty>(FilterOperator filterOperator, str
 94    {
 252095        var stringFilterExpressionCreator = new StringFilterExpression();
 252096        Expression<Func<KeyValuePair<TProperty, string>, string>> dictionaryValueSelector = x => x.Value;
 97
 252098        var stringFilterOperator = filterOperator switch
 252099        {
 312100            FilterOperator.Contains => FilterOperator.Contains,
 336101            FilterOperator.StartsWith => FilterOperator.StartsWith,
 336102            FilterOperator.EndsWith => FilterOperator.EndsWith,
 192103            FilterOperator.EqualCaseInsensitive => FilterOperator.EqualCaseInsensitive,
 192104            FilterOperator.EqualCaseSensitive => FilterOperator.EqualCaseSensitive,
 1152105            _ => FilterOperator.EqualCaseInsensitive
 2520106        };
 107
 2520108        var underlyingEnumType = typeof(TProperty).GetUnderlyingType();
 109
 2520110        var stringFilterExpression = stringFilterExpressionCreator
 2520111            .CreateExpressionForValue(dictionaryValueSelector, stringFilterOperator, value, configuration, interceptor);
 112
 2520113        var stringFilter = Expression
 2520114            .Lambda<Func<KeyValuePair<TProperty, string>, bool>>(stringFilterExpression, dictionaryValueSelector.Paramet
 2520115            .Compile();
 116
 2520117        var filteredValues = Enum
 2520118            .GetValues(underlyingEnumType)
 2520119            .Cast<TProperty>()
 2520120            .Select(enumValue => KeyValuePair.Create(enumValue, EnumGetName(underlyingEnumType, enumValue)))
 2520121            .Where(stringFilter)
 2520122            .Select(x => x.Key);
 123
 2520124        return filteredValues;
 125    }
 126
 127    private static string EnumGetName<TEnum>(Type underlyingEnumType, TEnum value)
 12600128        => Enum.GetName(underlyingEnumType, value!)
 12600129           ?? throw new InvalidOperationException($"Unable to get value of {value} for enum {underlyingEnumType.Name}");
 130}