< Summary

Information
Class: Fluorite.Strainer.Services.Modules.StrainerModuleBuilder<T>
Assembly: Fluorite.Strainer
File(s): /builds/fluorite/strainer/src/Strainer/Services/Modules/StrainerModuleBuilder{T}.cs
Line coverage
100%
Covered lines: 61
Uncovered lines: 0
Coverable lines: 61
Total lines: 208
Line coverage: 100%
Branch coverage
100%
Covered branches: 10
Total branches: 10
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%11100%
get_Options()100%11100%
get_Module()100%11100%
get_PropertyInfoProvider()100%11100%
AddCustomFilterMethod(...)100%22100%
AddCustomSortMethod(...)100%22100%
AddFilterOperator(...)100%22100%
AddObject(...)100%22100%
AddProperty(...)100%22100%
RemoveBuiltInFilterOperator(...)100%11100%

File(s)

/builds/fluorite/strainer/src/Strainer/Services/Modules/StrainerModuleBuilder{T}.cs

#LineLine coverage
 1using Fluorite.Strainer.Models;
 2using Fluorite.Strainer.Models.Filtering;
 3using Fluorite.Strainer.Models.Filtering.Operators;
 4using Fluorite.Strainer.Models.Metadata;
 5using Fluorite.Strainer.Models.Sorting;
 6using Fluorite.Strainer.Services.Filtering;
 7using Fluorite.Strainer.Services.Metadata;
 8using Fluorite.Strainer.Services.Sorting;
 9using System.Linq.Expressions;
 10using System.Reflection;
 11
 12namespace Fluorite.Strainer.Services.Modules;
 13
 14/// <summary>
 15/// Default implementation of Strainer Module builder service.
 16/// </summary>
 17/// <typeparam name="T">
 18/// The type of model for which this module builder is for.
 19/// </typeparam>
 20public class StrainerModuleBuilder<T> : IStrainerModuleBuilder<T>
 21{
 22    /// <summary>
 23    /// Initializes a new instance of the <see cref="StrainerModuleBuilder{T}"/>
 24    /// class.
 25    /// </summary>
 26    /// <param name="strainerModule">
 27    /// The Strainer moduel to operate on.
 28    /// </param>
 29    /// <param name="strainerOptions">
 30    /// The Stariner options.
 31    /// </param>
 32    /// <param name="propertyInfoProvider">
 33    /// The <see cref="PropertyInfo"/> provider.
 34    /// </param>
 35    /// <exception cref="ArgumentNullException">
 36    /// <paramref name="strainerModule"/> is <see langword="null"/>.
 37    /// </exception>
 38    /// <exception cref="ArgumentNullException">
 39    /// <paramref name="strainerOptions"/> is <see langword="null"/>.
 40    /// </exception>
 41    /// <exception cref="ArgumentNullException">
 42    /// <paramref name="propertyInfoProvider"/> is <see langword="null"/>.
 43    /// </exception>
 1144    public StrainerModuleBuilder(
 1145        IPropertyInfoProvider propertyInfoProvider,
 1146        IStrainerModule strainerModule,
 1147        StrainerOptions strainerOptions)
 48    {
 1149        PropertyInfoProvider = Guard.Against.Null(propertyInfoProvider);
 1150        Module = Guard.Against.Null(strainerModule);
 1151        Options = Guard.Against.Null(strainerOptions);
 1152    }
 53
 54    /// <inheritdoc/>
 555    public StrainerOptions Options { get; }
 56
 57    /// <summary>
 58    /// Gets the Strainer module on which this builder operates on.
 59    /// </summary>
 1460    protected IStrainerModule Module { get; }
 61
 62    /// <summary>
 63    /// Gets the property info provider.
 64    /// </summary>
 365    protected IPropertyInfoProvider PropertyInfoProvider { get; }
 66
 67    /// <inheritdoc/>
 68    /// <exception cref="ArgumentException">
 69    /// <paramref name="buildingDelegate"/> is <see langword="null"/>.
 70    /// </exception>
 71    public IStrainerModuleBuilder<T> AddCustomFilterMethod(Func<ICustomFilterMethodBuilder<T>, ICustomFilterMethod<T>> b
 72    {
 173        Guard.Against.Null(buildingDelegate);
 74
 175        var builder = new CustomFilterMethodBuilder<T>();
 176        var customMethod = buildingDelegate.Invoke(builder);
 77
 178        if (!Module.CustomFilterMethods.ContainsKey(typeof(T)))
 79        {
 180            Module.CustomFilterMethods[typeof(T)] = new Dictionary<string, ICustomFilterMethod>();
 81        }
 82
 183        Module.CustomFilterMethods[typeof(T)][customMethod.Name] = customMethod;
 84
 185        return this;
 86    }
 87
 88    /// <inheritdoc/>
 89    /// <exception cref="ArgumentException">
 90    /// <paramref name="buildingDelegate"/> is <see langword="null"/>.
 91    /// </exception>
 92    public IStrainerModuleBuilder<T> AddCustomSortMethod(
 93        Func<ICustomSortMethodBuilder<T>, ICustomSortMethod<T>> buildingDelegate)
 94    {
 195        Guard.Against.Null(buildingDelegate);
 96
 197        var builder = new CustomSortMethodBuilder<T>();
 198        var customMethod = buildingDelegate.Invoke(builder);
 99
 1100        if (!Module.CustomSortMethods.ContainsKey(typeof(T)))
 101        {
 1102            Module.CustomSortMethods[typeof(T)] = new Dictionary<string, ICustomSortMethod>();
 103        }
 104
 1105        Module.CustomSortMethods[typeof(T)][customMethod.Name] = customMethod;
 106
 1107        return this;
 108    }
 109
 110    /// <inheritdoc/>
 111    /// <exception cref="ArgumentException">
 112    /// <paramref name="buildingDelegate"/> is <see langword="null"/>.
 113    /// </exception>
 114    /// <exception cref="InvalidOperationException">
 115    /// <paramref name="buildingDelegate"/> is used by already defined filter operator.
 116    /// </exception>
 117    public IStrainerModuleBuilder<T> AddFilterOperator(Func<IFilterOperatorBuilder, IFilterOperator> buildingDelegate)
 118    {
 2119        Guard.Against.Null(buildingDelegate);
 120
 2121        var builder = new FilterOperatorBuilder();
 2122        var filterOperator = buildingDelegate.Invoke(builder);
 123
 2124        if (Module.FilterOperators.Keys.Contains(filterOperator.Symbol))
 125        {
 1126            throw new InvalidOperationException(
 1127                $"There is an already existing operator with a symbol {filterOperator.Symbol}. " +
 1128                $"Please, choose a different symbol.");
 129        }
 130
 1131        Module.FilterOperators.Add(filterOperator.Symbol, filterOperator);
 132
 1133        return this;
 134    }
 135
 136    /// <inheritdoc/>
 137    /// <exception cref="ArgumentException">
 138    /// <paramref name="defaultSortingPropertyExpression"/> is <see langword="null"/>.
 139    /// </exception>
 140    /// <exception cref="NotSupportedException">
 141    /// Fluent API is not supported.
 142    /// </exception>
 143    public IObjectMetadataBuilder<T> AddObject(
 144        Expression<Func<T, object>> defaultSortingPropertyExpression)
 145    {
 3146        Guard.Against.Null(defaultSortingPropertyExpression);
 147
 3148        if (!Options.MetadataSourceType.HasFlag(MetadataSourceType.FluentApi))
 149        {
 1150            throw new NotSupportedException(
 1151                $"Current {nameof(MetadataSourceType)} setting does not " +
 1152                $"support {nameof(MetadataSourceType.FluentApi)}. " +
 1153                $"Include {nameof(MetadataSourceType.FluentApi)} option to " +
 1154                $"be able to use it.");
 155        }
 156
 2157        return new ObjectMetadataBuilder<T>(
 2158            PropertyInfoProvider,
 2159            Module.ObjectMetadata,
 2160            defaultSortingPropertyExpression);
 161    }
 162
 163    /// <inheritdoc/>
 164    /// <exception cref="ArgumentException">
 165    /// <paramref name="propertyExpression"/> is <see langword="null"/>.
 166    /// </exception>
 167    /// <exception cref="NotSupportedException">
 168    /// Fluent API is not supported.
 169    /// </exception>
 170    public IPropertyMetadataBuilder<T> AddProperty(
 171        Expression<Func<T, object>> propertyExpression)
 172    {
 2173        Guard.Against.Null(propertyExpression);
 174
 2175        if (!Options.MetadataSourceType.HasFlag(MetadataSourceType.FluentApi))
 176        {
 1177            throw new NotSupportedException(
 1178                $"Current {nameof(MetadataSourceType)} setting does not " +
 1179                $"support {nameof(MetadataSourceType.FluentApi)}. " +
 1180                $"Include {nameof(MetadataSourceType.FluentApi)} option to " +
 1181                $"be able to use it.");
 182        }
 183
 1184        var (propertyInfo, fullName) = PropertyInfoProvider.GetPropertyInfoAndFullName(propertyExpression);
 185
 1186        return new PropertyMetadataBuilder<T>(
 1187            Module.PropertyMetadata,
 1188            Module.DefaultMetadata,
 1189            propertyInfo,
 1190            fullName);
 191    }
 192
 193    /// <inheritdoc/>
 194    /// <exception cref="ArgumentNullException">
 195    /// <paramref name="symbol"/> is <see langword="null"/>.
 196    /// </exception>
 197    /// <exception cref="ArgumentException">
 198    /// <paramref name="symbol"/> is empty or whitespace.
 199    /// </exception>
 200    public IStrainerModuleBuilder<T> RemoveBuiltInFilterOperator(string symbol)
 201    {
 1202        Guard.Against.NullOrWhiteSpace(symbol);
 203
 1204        Module.ExcludedBuiltInFilterOperators.Add(symbol);
 205
 1206        return this;
 207    }
 208}