Documentation Coverage Report
Current view: top level - Cqrs/Repositories/Queries - QueryBuilder.cs Hit Total Coverage
Version: 2.2 Artefacts: 25 25 100.0 %
Date: 2018-08-07 15:04:50

          Line data    Source code
       1             : #region Copyright
       2             : // // -----------------------------------------------------------------------
       3             : // // <copyright company="Chinchilla Software Limited">
       4             : // //   Copyright Chinchilla Software Limited. All rights reserved.
       5             : // // </copyright>
       6             : // // -----------------------------------------------------------------------
       7             : #endregion
       8             : 
       9             : using System;
      10             : using System.Linq;
      11             : using Cqrs.Configuration;
      12             : using Cqrs.Entities;
      13             : using Cqrs.DataStores;
      14             : 
      15             : namespace Cqrs.Repositories.Queries
      16             : {
      17             :         /// <summary>
      18             :         /// Builds an <see cref="IQueryable"/> from a <typeparamref name="TQueryStrategy"/>.
      19             :         /// </summary>
      20             :         /// <typeparam name="TQueryStrategy">The <see cref="Type"/> of the <see cref="IQueryStrategy"/>.</typeparam>
      21             :         /// <typeparam name="TData">The <see cref="Type"/> of data to query.</typeparam>
      22             :         public abstract class QueryBuilder<TQueryStrategy, TData> : IQueryBuilder<TQueryStrategy, TData>
      23             :                 where TQueryStrategy : IQueryStrategy
      24             :                 where TData : Entity
      25           1 :         {
      26             :                 /// <summary>
      27             :                 /// Gets or set the <see cref="IDataStore{TData}"/> to use.
      28             :                 /// </summary>
      29             :                 protected IDataStore<TData> DataStore { get; private set; }
      30             : 
      31             :                 /// <summary>
      32             :                 /// Gets or set the <see cref="IDependencyResolver"/>.
      33             :                 /// </summary>
      34             :                 protected IDependencyResolver DependencyResolver { get; private set; }
      35             : 
      36             :                 /// <summary>
      37             :                 /// Instantiates a new instance of <see cref="QueryBuilder{TQueryStrategy,TData}"/>.
      38             :                 /// </summary>
      39           1 :                 protected QueryBuilder(IDataStore<TData> dataStore, IDependencyResolver dependencyResolver)
      40             :                 {
      41             :                         DataStore = dataStore;
      42             :                         DependencyResolver = dependencyResolver;
      43             :                 }
      44             : 
      45             :                 #region Implementation of IQueryBuilder<UserQueryStrategy,User>
      46             : 
      47             :                 /// <summary>
      48             :                 /// Create an <see cref="IQueryable"/> of <typeparamref name="TData"/>
      49             :                 /// that expects a single <typeparamref name="TData"/> item.
      50             :                 /// </summary>
      51             :                 /// <param name="singleResultQuery">The query.</param>
      52           1 :                 public virtual IQueryable<TData> CreateQueryable(ISingleResultQuery<TQueryStrategy, TData> singleResultQuery)
      53             :                 {
      54             :                         IQueryable<TData> queryable = singleResultQuery.QueryStrategy.QueryPredicate == null ?  GetEmptyQueryPredicate() : GeneratePredicate(singleResultQuery.QueryStrategy.QueryPredicate);
      55             :                         ApplySorting(singleResultQuery.QueryStrategy, ref queryable);
      56             :                         return queryable;
      57             :                 }
      58             : 
      59             :                 /// <summary>
      60             :                 /// Create an <see cref="IQueryable"/> of <typeparamref name="TData"/>
      61             :                 /// that expects a collection of <typeparamref name="TData"/> items.
      62             :                 /// </summary>
      63             :                 /// <param name="collectionResultQuery">The query.</param>
      64           1 :                 public virtual IQueryable<TData> CreateQueryable(ICollectionResultQuery<TQueryStrategy, TData> collectionResultQuery)
      65             :                 {
      66             :                         IQueryable<TData> queryable = collectionResultQuery.QueryStrategy.QueryPredicate == null ? GetEmptyQueryPredicate() : GeneratePredicate(collectionResultQuery.QueryStrategy.QueryPredicate);
      67             :                         ApplySorting(collectionResultQuery.QueryStrategy, ref queryable);
      68             :                         return queryable;
      69             :                 }
      70             : 
      71             :                 #endregion
      72             : 
      73             :                 /// <summary>
      74             :                 /// Returns the <see cref="DataStore"/> itself.
      75             :                 /// </summary>
      76           1 :                 protected virtual IQueryable<TData> GetEmptyQueryPredicate()
      77             :                 {
      78             :                         return DataStore;
      79             :                 }
      80             : 
      81             :                 /// <summary>
      82             :                 /// Builds an <see cref="IQueryable"/> from the <paramref name="queryPredicate"/> and an optional <paramref name="leftHandQueryable"/>.
      83             :                 /// This recursively calls itself and may call <see cref="GeneratePredicateIsNotLogicallyDeleted"/>.
      84             :                 /// </summary>
      85           1 :                 protected virtual IQueryable<TData> GeneratePredicate(IQueryPredicate queryPredicate, IQueryable<TData> leftHandQueryable = null)
      86             :                 {
      87             :                         var andQueryPredicate = queryPredicate as IAndQueryPredicate;
      88             :                         if (andQueryPredicate != null)
      89             :                         {
      90             :                                 IQueryable<TData> innerLeftHandQueryable = GeneratePredicate(andQueryPredicate.LeftQueryPredicate);
      91             :                                 return GeneratePredicate(andQueryPredicate.RightQueryPredicate, innerLeftHandQueryable);
      92             :                         }
      93             :                         var orQueryPredicate = queryPredicate as IOrQueryPredicate;
      94             :                         if (orQueryPredicate != null)
      95             :                         {
      96             :                                 IQueryable<TData> innerLeftHandQueryable = GeneratePredicate(orQueryPredicate.LeftQueryPredicate);
      97             :                                 return GeneratePredicate(orQueryPredicate.RightQueryPredicate, innerLeftHandQueryable);
      98             :                         }
      99             :                         var realQueryPredicate = queryPredicate as QueryPredicate;
     100             :                         if (realQueryPredicate != null)
     101             :                         {
     102             :                                 IQueryable<TData> result = GeneratePredicateIsNotLogicallyDeleted(realQueryPredicate, leftHandQueryable);
     103             :                                 return result ?? GeneratePredicate(realQueryPredicate, leftHandQueryable);
     104             :                         }
     105             :                         throw new InvalidOperationException(string.Format("The query predicate '{0}' is unable to be processed.", queryPredicate == null ? typeof(void) : queryPredicate.GetType()));
     106             :                 }
     107             : 
     108             :                 /// <summary>
     109             :                 /// Builds the relevant <see cref="IQueryable"/> for <see cref="QueryStrategy.IsNotLogicallyDeleted"/>.
     110             :                 /// </summary>
     111           1 :                 protected virtual IQueryable<TData> GeneratePredicateIsNotLogicallyDeleted(QueryPredicate queryPredicate, IQueryable<TData> leftHandQueryable = null)
     112             :                 {
     113             :                         var queryStrategy = GetNullQueryStrategy() as QueryStrategy;
     114             : 
     115             :                         if (queryStrategy == null)
     116             :                                 return null;
     117             : 
     118             :                         if (queryPredicate.Name != GetFunctionName(queryStrategy.IsNotLogicallyDeleted))
     119             :                                 return null;
     120             : 
     121             :                         return (leftHandQueryable ?? GetEmptyQueryPredicate()).Where
     122             :                         (
     123             :                                 entity => !entity.IsLogicallyDeleted
     124             :                         );
     125             :                 }
     126             : 
     127             :                 /// <summary>
     128             :                 /// Builds the relevant <see cref="IQueryable"/> for <see cref="QueryStrategy.WithPermissionScopeAny{TAuthenticationToken}"/>.
     129             :                 /// </summary>
     130           1 :                 protected virtual IQueryable<TData> GeneratePredicateWithPermissionScopeAny<TAuthenticationToken>(QueryPredicate queryPredicate, IQueryable<TData> leftHandQueryable)
     131             :                 {
     132             :                         var queryStrategy = GetNullQueryStrategy() as QueryStrategy;
     133             : 
     134             :                         if (queryStrategy == null)
     135             :                                 return null;
     136             : 
     137             :                         if (queryPredicate.Name != GetFunctionNameOfType<TAuthenticationToken>(queryStrategy.WithPermissionScopeAny))
     138             :                                 return null;
     139             : 
     140             :                         return OnGeneratePredicateWithPermissionScopeAny<TAuthenticationToken>(queryPredicate, leftHandQueryable);
     141             :                 }
     142             : 
     143             :                 /// <summary>
     144             :                 /// Returns <paramref name="leftHandQueryable"/> or calls <see cref="GetEmptyQueryPredicate"/> if <paramref name="leftHandQueryable"/> is null.
     145             :                 /// Override to build the relevant permission scope <see cref="IQueryable"/>.
     146             :                 /// </summary>
     147           1 :                 protected virtual IQueryable<TData> OnGeneratePredicateWithPermissionScopeAny<TAuthenticationToken>(QueryPredicate queryPredicate, IQueryable<TData> leftHandQueryable)
     148             :                 {
     149             :                         return (leftHandQueryable ?? GetEmptyQueryPredicate());
     150             :                 }
     151             : 
     152             :                 /// <summary>
     153             :                 /// Builds the relevant <see cref="IQueryable"/> for <see cref="QueryStrategy.WithPermissionScopeUser{TAuthenticationToken}"/>.
     154             :                 /// </summary>
     155           1 :                 protected virtual IQueryable<TData> GeneratePredicateWithPermissionScopeUser<TAuthenticationToken>(QueryPredicate queryPredicate, IQueryable<TData> leftHandQueryable)
     156             :                 {
     157             :                         var queryStrategy = GetNullQueryStrategy() as QueryStrategy;
     158             : 
     159             :                         if (queryStrategy == null)
     160             :                                 return null;
     161             : 
     162             :                         if (queryPredicate.Name != GetFunctionNameOfType<TAuthenticationToken>(queryStrategy.WithPermissionScopeUser))
     163             :                                 return null;
     164             : 
     165             :                         return OnGeneratePredicateWithPermissionScopeUser<TAuthenticationToken>(queryPredicate, leftHandQueryable);
     166             :                 }
     167             : 
     168             :                 /// <summary>
     169             :                 /// Returns <paramref name="leftHandQueryable"/> or calls <see cref="GetEmptyQueryPredicate"/> if <paramref name="leftHandQueryable"/> is null.
     170             :                 /// Override to build the relevant permission scope <see cref="IQueryable"/>.
     171             :                 /// </summary>
     172           1 :                 protected virtual IQueryable<TData> OnGeneratePredicateWithPermissionScopeUser<TAuthenticationToken>(QueryPredicate queryPredicate, IQueryable<TData> leftHandQueryable)
     173             :                 {
     174             :                         return (leftHandQueryable ?? GetEmptyQueryPredicate());
     175             :                 }
     176             : 
     177             :                 /// <summary>
     178             :                 /// Builds the relevant <see cref="IQueryable"/> for <see cref="QueryStrategy.WithPermissionScopeCompany{TAuthenticationToken}"/>.
     179             :                 /// </summary>
     180           1 :                 protected virtual IQueryable<TData> GeneratePredicateWithPermissionScopeCompany<TAuthenticationToken>(QueryPredicate queryPredicate, IQueryable<TData> leftHandQueryable)
     181             :                 {
     182             :                         var queryStrategy = GetNullQueryStrategy() as QueryStrategy;
     183             : 
     184             :                         if (queryStrategy == null)
     185             :                                 return null;
     186             : 
     187             :                         if (queryPredicate.Name != GetFunctionNameOfType<TAuthenticationToken>(queryStrategy.WithPermissionScopeCompany))
     188             :                                 return null;
     189             : 
     190             :                         return OnGeneratePredicateWithPermissionScopeCompany<TAuthenticationToken>(queryPredicate, leftHandQueryable);
     191             :                 }
     192             : 
     193             :                 /// <summary>
     194             :                 /// Returns <paramref name="leftHandQueryable"/> or calls <see cref="GetEmptyQueryPredicate"/> if <paramref name="leftHandQueryable"/> is null.
     195             :                 /// Override to build the relevant permission scope <see cref="IQueryable"/>.
     196             :                 /// </summary>
     197           1 :                 protected virtual IQueryable<TData> OnGeneratePredicateWithPermissionScopeCompany<TAuthenticationToken>(QueryPredicate queryPredicate, IQueryable<TData> leftHandQueryable)
     198             :                 {
     199             :                         return (leftHandQueryable ?? GetEmptyQueryPredicate());
     200             :                 }
     201             : 
     202             :                 /// <summary>
     203             :                 /// Builds the relevant <see cref="IQueryable"/> for <see cref="QueryStrategy.WithPermissionScopeCompanyAndUser{TAuthenticationToken}"/>.
     204             :                 /// </summary>
     205           1 :                 protected virtual IQueryable<TData> GeneratePredicateWithPermissionScopeCompanyAndUser<TAuthenticationToken>(QueryPredicate queryPredicate, IQueryable<TData> leftHandQueryable)
     206             :                 {
     207             :                         var queryStrategy = GetNullQueryStrategy() as QueryStrategy;
     208             : 
     209             :                         if (queryStrategy == null)
     210             :                                 return null;
     211             : 
     212             :                         if (queryPredicate.Name != GetFunctionNameOfType<TAuthenticationToken>(queryStrategy.WithPermissionScopeCompanyAndUser))
     213             :                                 return null;
     214             : 
     215             :                         return OnGeneratePredicateWithPermissionScopeCompanyAndUser<TAuthenticationToken>(queryPredicate, leftHandQueryable);
     216             :                 }
     217             : 
     218             :                 /// <summary>
     219             :                 /// Returns <paramref name="leftHandQueryable"/> or calls <see cref="GetEmptyQueryPredicate"/> if <paramref name="leftHandQueryable"/> is null.
     220             :                 /// Override to build the relevant permission scope <see cref="IQueryable"/>.
     221             :                 /// </summary>
     222           1 :                 protected virtual IQueryable<TData> OnGeneratePredicateWithPermissionScopeCompanyAndUser<TAuthenticationToken>(QueryPredicate queryPredicate, IQueryable<TData> leftHandQueryable)
     223             :                 {
     224             :                         return (leftHandQueryable ?? GetEmptyQueryPredicate());
     225             :                 }
     226             : 
     227             :                 /// <summary>
     228             :                 /// Override to build an <see cref="IQueryable"/> from the <paramref name="queryPredicate"/> and an optional <paramref name="leftHandQueryable"/>.
     229             :                 /// </summary>
     230           1 :                 protected abstract IQueryable<TData> GeneratePredicate(QueryPredicate queryPredicate, IQueryable<TData> leftHandQueryable = null);
     231             : 
     232             :                 /// <summary>
     233             :                 /// Gets the Name of the method in <paramref name="expression"/>
     234             :                 /// </summary>
     235           1 :                 protected virtual string GetFunctionNameOfType<TParameter1>(Func<TParameter1, IQueryPredicate> expression)
     236             :                 {
     237             :                         return expression.Method.Name;
     238             :                 }
     239             : 
     240             :                 /// <summary>
     241             :                 /// Gets the Name of the method in <paramref name="expression"/>
     242             :                 /// </summary>
     243           1 :                 protected virtual string GetFunctionName<T>(Func<T> expression)
     244             :                 {
     245             :                         return expression.Method.Name;
     246             :                 }
     247             : 
     248             :                 /// <summary>
     249             :                 /// Gets the Name of the method in <paramref name="expression"/>
     250             :                 /// </summary>
     251           1 :                 protected virtual string GetFunctionName<TParameter1>(Func<TParameter1, TQueryStrategy> expression)
     252             :                 {
     253             :                         return expression.Method.Name;
     254             :                 }
     255             : 
     256             :                 /// <summary>
     257             :                 /// Gets the Name of the method in <paramref name="expression"/>
     258             :                 /// </summary>
     259           1 :                 protected virtual string GetFunctionName<TParameter1, TParameter2>(Func<TParameter1, TParameter2, TQueryStrategy> expression)
     260             :                 {
     261             :                         return expression.Method.Name;
     262             :                 }
     263             : 
     264             :                 /// <summary>
     265             :                 /// Gets the Name of the method in <paramref name="expression"/>
     266             :                 /// </summary>
     267           1 :                 protected virtual string GetFunctionName<TParameter1, TParameter2, TParameter3>(Func<TParameter1, TParameter2, TParameter3, TQueryStrategy> expression)
     268             :                 {
     269             :                         return expression.Method.Name;
     270             :                 }
     271             : 
     272             :                 /// <summary>
     273             :                 /// Gets the Name of the method in <paramref name="expression"/>
     274             :                 /// </summary>
     275           1 :                 protected virtual string GetFunctionName<TParameter1, TParameter2, TParameter3, TParameter4>(Func<TParameter1, TParameter2, TParameter3, TParameter4, TQueryStrategy> expression)
     276             :                 {
     277             :                         return expression.Method.Name;
     278             :                 }
     279             : 
     280             :                 /// <summary>
     281             :                 /// Gets the Name of the method in <paramref name="expression"/>
     282             :                 /// </summary>
     283           1 :                 protected virtual string GetFunctionName<TParameter1, TParameter2, TParameter3, TParameter4, TParameter5>(Func<TParameter1, TParameter2, TParameter3, TParameter4, TParameter5, TQueryStrategy> expression)
     284             :                 {
     285             :                         return expression.Method.Name;
     286             :                 }
     287             : 
     288             :                 /// <summary>
     289             :                 /// Uses <see cref="Activator.CreateInstance{T}"/> to create a new instance of <typeparamref name="TQueryStrategy"/>.
     290             :                 /// </summary>
     291           1 :                 protected virtual TQueryStrategy GetNullQueryStrategy()
     292             :                 {
     293             :                         try
     294             :                         {
     295             :                                 return Activator.CreateInstance<TQueryStrategy>();
     296             :                         }
     297             :                         catch (MissingMethodException)
     298             :                         {
     299             :                                 return DependencyResolver.Resolve<TQueryStrategy>();
     300             :                         }
     301             :                 }
     302             : 
     303             :                 /// <summary>
     304             :                 /// Override to build or apply any sorting required to <paramref name="queryable"/>
     305             :                 /// </summary>
     306             :                 /// <param name="queryStrategy">The <typeparamref name="TQueryStrategy"/> with sorting information.</param>
     307             :                 /// <param name="queryable">The <see cref="IQueryable"/> to apply sorting to.</param>
     308           1 :                 protected virtual void ApplySorting(TQueryStrategy queryStrategy, ref IQueryable<TData> queryable)
     309             :                 {
     310             :                 }
     311             :         }
     312             : }

Generated by: LCOV version 1.12