private static List <SelectedProperty> GetValidProperties <TModel>(
            IWrapRequest <TModel> source,
            Type type,
            List <string> requestProperties,
            string rootName       = null,
            bool isFromCollection = false)
            where TModel : class
        {
            var properties = new List <SelectedProperty>();

            type.GetProperties()
            .Where(property =>
                   !source.IsPropertySuppressedResponse(string.Join(".", TermsHelper.GetTerms(rootName, ".").Union(new List <string> {
                property.Name
            }).Where(term => !string.IsNullOrWhiteSpace(term)))) &&
                   (
                       (requestProperties.Count == 0 && IsToLoadComplexPropertyWhenNotRequested(TypesHelper.TypeIsComplex(property.PropertyType), ConfigurationService.GetConfiguration().ByDefaultLoadComplexProperties, string.IsNullOrWhiteSpace(rootName))) ||
                       (requestProperties.Any(requested => TermsHelper.GetTerms(requested, ".").FirstOrDefault().ToLower().Equals(property.Name.ToLower())))
                   )
                   )
            .ToList()
            .ForEach(property =>
            {
                if (!TypesHelper.TypeIsComplex(property.PropertyType))
                {
                    properties.Add(new SelectedProperty
                    {
                        RequestedPropertyName = string.Join(".", TermsHelper.GetTerms(rootName, ".").Union(new List <string> {
                            property.Name
                        }).Where(term => !string.IsNullOrWhiteSpace(term))),
                        PropertyName     = property.Name,
                        RootPropertyName = rootName,
                        PropertyType     = property.PropertyType,
                        PropertyInfo     = property
                    });
                }
                else if (ConfigurationService.GetConfiguration().ByDefaultLoadComplexProperties)
                {
                    properties.AddRange(
                        GetValidProperties(
                            source,
                            TypesHelper.TypeIsCollection(property.PropertyType) ? property.PropertyType.GetGenericArguments()[0] : property.PropertyType,
                            requestProperties
                            .Where(requested => TermsHelper.GetTerms(requested, ".").FirstOrDefault().ToLower().Equals(property.Name.ToLower()))
                            .Select(requested => string.Join(".", TermsHelper.GetTerms(requested, ".").Skip(1)))
                            .Where(requested => !string.IsNullOrWhiteSpace(requested))
                            .ToList(),
                            string.Join(".", TermsHelper.GetTerms(rootName, ".").Union(new List <string> {
                        property.Name
                    }).Where(term => !string.IsNullOrWhiteSpace(term))),
                            TypesHelper.TypeIsCollection(property.PropertyType)
                            )
                        );
                }
            });

            return(properties);
        }
        /// <summary>
        /// Method that extends IQueryable<T> allowing to search query with request properties
        /// </summary>
        /// <typeparam name="TSource">Generic type of the entity</typeparam>
        /// <param name="source">Self IQueryable<T> instance</param>
        /// <param name="request">Self IWrapRequest<T> instance</param>
        /// <returns>Returns IQueryable instance with with the configuration for search</returns>
        public static IQueryable <TSource> Search <TSource>(
            this IQueryable <TSource> source,
            IWrapRequest <TSource> request
            ) where TSource : class
        {
            var search = request.Search();

            var query       = search.Query;
            var queryStrict = search.Strict;
            var queryPhrase = search.Phrase;

            if (string.IsNullOrWhiteSpace(query))
            {
                return(source);
            }

            var queryTokens = TermsHelper.GetSearchTerms(query, queryPhrase);

            query = string.Join("+", queryTokens.ToArray());

            if (queryTokens.Count == 0)
            {
                return(source);
            }

            List <string> searchableProperties = new List <string>();

            searchableProperties = typeof(TSource).GetProperties().Where(x =>
                                                                         !request.IsPropertySuppressed(x.Name) && !TypesHelper.TypeIsComplex(x.PropertyType)
                                                                         ).Select(x => x.Name).ToList();

            var criteriaExp = LambdasHelper.GenerateSearchCriteriaExpression <TSource>(searchableProperties, queryTokens, queryStrict);

            return(source.Where(criteriaExp));
        }