Ejemplo n.º 1
0
        /// <summary>
        /// Gets the expression.
        /// </summary>
        /// <param name="dataViewEntityTypeType">Type of the data view entity type.</param>
        /// <param name="serviceInstance">The service instance.</param>
        /// <param name="parameter">The parameter.</param>
        /// <param name="dataViewFilterOverrides">The data view filter overrides.</param>
        /// <returns></returns>
        /// <exception cref="Rock.Reporting.RockReportingException">
        /// EntityTypeId not defined for {this}
        /// or
        /// Unable to determine EntityType not defined for EntityTypeId {EntityTypeId}
        /// or
        /// Unable to determine Component for EntityType {entityType.Name}
        /// or
        /// unable to determine expression for {filter}
        /// or
        /// Unexpected FilterExpressionType {ExpressionType}
        /// </exception>
        public Expression GetExpression(Type dataViewEntityTypeType, IService serviceInstance, ParameterExpression parameter, DataViewFilterOverrides dataViewFilterOverrides)
        {
            switch (ExpressionType)
            {
            case FilterExpressionType.Filter:

                if (!this.EntityTypeId.HasValue)
                {
                    // if this happens, we want to throw an exception to prevent incorrect results
                    throw new RockDataViewFilterExpressionException(this, $"EntityTypeId not defined for {this}");
                }

                var entityType = EntityTypeCache.Get(this.EntityTypeId.Value);
                if (entityType == null)
                {
                    // if this happens, we want to throw an exception to prevent incorrect results
                    throw new RockDataViewFilterExpressionException(this, $"Unable to determine EntityType not defined for EntityTypeId {EntityTypeId}");
                }

                var component = Rock.Reporting.DataFilterContainer.GetComponent(entityType.Name);
                if (component == null)
                {
                    // if this happens, we want to throw an exception to prevent incorrect results
                    throw new RockDataViewFilterExpressionException(this, $"Unable to determine Component for EntityType {entityType.Name}");
                }

                string selection;     // A formatted string representing the filter settings: FieldName, <see cref="ComparisonType">Comparison Type</see>, (optional) Comparison Value(s)
                var    dataViewFilterOverride = dataViewFilterOverrides?.GetOverride(this.Guid);
                if (dataViewFilterOverride != null)
                {
                    if (dataViewFilterOverride.IncludeFilter == false)
                    {
                        /*
                         * 1/15/2021 - Shaun
                         * This should not assume that returning Expression.Constant( true ) is equivalent to not filtering as this predicate
                         * may be joined to other predicates and the AND/OR logic may result in an inappropriate filter.  Instead, we simply
                         * return null and allow the caller to handle this in a manner appropriate to the given filter.
                         */

                        // If the dataview filter should not be included, don't have this filter filter anything.
                        return(null);
                    }
                    else
                    {
                        selection = dataViewFilterOverride.Selection;
                    }
                }
                else
                {
                    selection = this.Selection;
                }

                Expression expression;

                try
                {
                    if (component is IDataFilterWithOverrides)
                    {
                        expression = (component as IDataFilterWithOverrides).GetExpressionWithOverrides(dataViewEntityTypeType, serviceInstance, parameter, dataViewFilterOverrides, selection);
                    }
                    else
                    {
                        expression = component.GetExpression(dataViewEntityTypeType, serviceInstance, parameter, selection);
                    }
                }
                catch (RockDataViewFilterExpressionException dex)
                {
                    // components don't know which DataView/DataFilter they are working with, so if there was a RockDataViewFilterExpressionException, let's tell it what DataViewFilter/DataView it was using
                    dex.SetDataFilterIfNotSet(this);
                    throw;
                }

                if (expression == null)
                {
                    // If a DataFilter component returned a null expression, that probably means that it decided not to filter anything. So, we'll interpret that as "Don't Filter"
                    expression = Expression.Constant(true);
                }

                return(expression);

            case FilterExpressionType.GroupAll:
            case FilterExpressionType.GroupAnyFalse:

                Expression andExp = null;
                foreach (var filter in this.ChildFilters)
                {
                    Expression exp = filter.GetExpression(dataViewEntityTypeType, serviceInstance, parameter, dataViewFilterOverrides);
                    if (exp == null)
                    {
                        // If a DataFilter component returned a null expression, that probably means that it decided not to filter anything. So, we'll interpret that as "Don't Filter"
                        exp = Expression.Constant(true);
                    }

                    if (andExp == null)
                    {
                        andExp = exp;
                    }
                    else
                    {
                        andExp = Expression.AndAlso(andExp, exp);
                    }
                }

                if (ExpressionType == FilterExpressionType.GroupAnyFalse &&
                    andExp != null)
                {
                    // If only one of the conditions must be false, invert the expression so that it becomes the logical equivalent of "NOT ALL".
                    andExp = Expression.Not(andExp);
                }

                if (andExp == null)
                {
                    // If there aren't any child filters for a GroupAll/GroupAnyFalse. That is OK, so just don't filter anything.
                    return(Expression.Constant(true));
                }

                return(andExp);

            case FilterExpressionType.GroupAny:
            case FilterExpressionType.GroupAllFalse:

                Expression orExp = null;
                foreach (DataViewFilter filter in this.ChildFilters)
                {
                    Expression exp = filter.GetExpression(dataViewEntityTypeType, serviceInstance, parameter, dataViewFilterOverrides);
                    if (exp == null)
                    {
                        /*
                         * 1/15/2021 - Shaun
                         * Filter expressions of these types (GroupAny/GroupAllFalse) are joined with an OR clause,
                         * so they must either be defaulted to false or excluded from the where expression altogether
                         * (otherwise they will return every Person record in the database, because a "True OrElse
                         * <anything>" predicate will always be true).
                         *
                         * Therefore, if this child filter is null, we can simply ignore it and move on to the next one.
                         *
                         * Reason: Correcting behavior of dynamic reports where a group is deselected at run time.
                         */

                        continue;
                    }

                    if (orExp == null)
                    {
                        orExp = exp;
                    }
                    else
                    {
                        orExp = Expression.OrElse(orExp, exp);
                    }
                }

                if (ExpressionType == FilterExpressionType.GroupAllFalse &&
                    orExp != null)
                {
                    // If all of the conditions must be false, invert the expression so that it becomes the logical equivalent of "NOT ANY".
                    orExp = Expression.Not(orExp);
                }

                if (orExp == null)
                {
                    // If there aren't any child filters for a GroupAny/GroupAllFalse. That is OK, so just don't filter anything.
                    return(Expression.Constant(true));
                }

                return(orExp);

            default:
                throw new RockDataViewFilterExpressionException(this, $"Unexpected FilterExpressionType {ExpressionType} ");
            }
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Gets the Linq expression for the DataViewFilter.
        /// </summary>
        /// <param name="filteredEntityType">Type of the filtered entity.</param>
        /// <param name="serviceInstance">The service instance.</param>
        /// <param name="parameter">The parameter.</param>
        /// <param name="dataViewFilterOverrides">The data view filter overrides.</param>
        /// <param name="errorMessages">The error messages.</param>
        /// <returns></returns>
        public virtual Expression GetExpression(Type filteredEntityType, IService serviceInstance, ParameterExpression parameter, DataViewFilterOverrides dataViewFilterOverrides, List <string> errorMessages)
        {
            switch (ExpressionType)
            {
            case FilterExpressionType.Filter:

                if (this.EntityTypeId.HasValue)
                {
                    var entityType = EntityTypeCache.Get(this.EntityTypeId.Value);
                    if (entityType != null)
                    {
                        var component = Rock.Reporting.DataFilterContainer.GetComponent(entityType.Name);
                        if (component != null)
                        {
                            try
                            {
                                string selection;     // A formatted string representing the filter settings: FieldName, <see cref="ComparisonType">Comparison Type</see>, (optional) Comparison Value(s)
                                var    dataViewFilterOverride = dataViewFilterOverrides?.GetOverride(this.Guid);
                                if (dataViewFilterOverride != null)
                                {
                                    if (dataViewFilterOverride.IncludeFilter == false)
                                    {
                                        return(null);
                                    }
                                    else
                                    {
                                        selection = dataViewFilterOverride.Selection;
                                    }
                                }
                                else
                                {
                                    selection = this.Selection;
                                }

                                if (component is IDataFilterWithOverrides)
                                {
                                    return((component as IDataFilterWithOverrides).GetExpressionWithOverrides(filteredEntityType, serviceInstance, parameter, dataViewFilterOverrides, selection));
                                }
                                else
                                {
                                    return(component.GetExpression(filteredEntityType, serviceInstance, parameter, selection));
                                }
                            }
                            catch (SystemException ex)
                            {
                                ExceptionLogService.LogException(ex, System.Web.HttpContext.Current);
                                errorMessages.Add(string.Format("{0}: {1}", component.FormatSelection(filteredEntityType, this.Selection), ex.Message));
                            }
                        }
                    }
                }
                return(null);

            case FilterExpressionType.GroupAll:
            case FilterExpressionType.GroupAnyFalse:

                Expression andExp = null;
                foreach (var filter in this.ChildFilters)
                {
                    Expression exp = filter.GetExpression(filteredEntityType, serviceInstance, parameter, dataViewFilterOverrides, errorMessages);
                    if (exp != null)
                    {
                        if (andExp == null)
                        {
                            andExp = exp;
                        }
                        else
                        {
                            andExp = Expression.AndAlso(andExp, exp);
                        }
                    }
                }

                if (ExpressionType == FilterExpressionType.GroupAnyFalse &&
                    andExp != null)
                {
                    // If only one of the conditions must be false, invert the expression so that it becomes the logical equivalent of "NOT ALL".
                    andExp = Expression.Not(andExp);
                }

                return(andExp);

            case FilterExpressionType.GroupAny:
            case FilterExpressionType.GroupAllFalse:

                Expression orExp = null;
                foreach (var filter in this.ChildFilters)
                {
                    Expression exp = filter.GetExpression(filteredEntityType, serviceInstance, parameter, dataViewFilterOverrides, errorMessages);
                    if (exp != null)
                    {
                        if (orExp == null)
                        {
                            orExp = exp;
                        }
                        else
                        {
                            orExp = Expression.OrElse(orExp, exp);
                        }
                    }
                }

                if (ExpressionType == FilterExpressionType.GroupAllFalse &&
                    orExp != null)
                {
                    // If all of the conditions must be false, invert the expression so that it becomes the logical equivalent of "NOT ANY".
                    orExp = Expression.Not(orExp);
                }

                return(orExp);
            }

            return(null);
        }