/// <summary> /// Builds a predicate that examines the raw data (as its native .Net type) to determine if /// it passes the specified filter. /// </summary> /// <remarks> /// This overload assumes that the values will not be null. /// </remarks> /// <param name="condition">The condition to be applied.</param> /// <param name="gridResultColumn">The grid result column.</param> /// <param name="conditionalFormatter">The conditional formatter.</param> /// <returns>A predicate that accepts a data value and returns true if the value is acceptable on the basis of the filter.</returns> private static Predicate <object> BuildValueFilterPredicateNoNulls(Condition condition, ResultColumn gridResultColumn, ConditionalFormatter conditionalFormatter) { // Get and check argument TypedValue argument = condition.Argument; string sArgument = null; IComparable cArgument = null; // Handle null strings. TODO: Improve this hack if (argument != null && argument.Value == null && argument.Type is StringType) { argument.Value = ""; } if (argument == null || argument.Value == null) { if (ConditionTypeHelper.GetArgumentCount(condition.Operator) != 0) { throw new ArgumentException(@"Condition has no (or null) argument.", "condition"); } } else { sArgument = argument.Value as string; cArgument = argument.Value as IComparable; } bool isDate = condition.ColumnType is DateType; bool isCurrency = condition.ColumnType is CurrencyType; // Return lambda to evaluate test // 'cell' is statically type object switch (condition.Operator) { case ConditionType.Unspecified: return(cell => true); // assert false - predicates should not be built from filters with unspecified operators. Silently ignore. case ConditionType.Equal: if (argument.Type is StringType) { return(cell => ((string)cell).Equals(argument.ValueString, StringComparison.CurrentCultureIgnoreCase)); } return(cell => argument != null && argument.Value.Equals(isCurrency ? ConvertCurrencyCell(cell, condition.ColumnType) : cell)); case ConditionType.NotEqual: if (argument.Type is StringType) { return(cell => !((string)cell).Equals(argument.ValueString, StringComparison.CurrentCultureIgnoreCase)); } return(cell => argument != null && !argument.Value.Equals(isCurrency ? ConvertCurrencyCell(cell, condition.ColumnType) : cell)); case ConditionType.GreaterThan: return(cell => cArgument != null && cArgument.CompareTo(isCurrency ? ConvertCurrencyCell(cell, condition.ColumnType) : cell) < 0); case ConditionType.GreaterThanOrEqual: return(cell => cArgument != null && cArgument.CompareTo(isCurrency ? ConvertCurrencyCell(cell, condition.ColumnType) : cell) <= 0); case ConditionType.LessThan: return(cell => cArgument != null && cArgument.CompareTo(isCurrency ? ConvertCurrencyCell(cell, condition.ColumnType) : cell) > 0); case ConditionType.LessThanOrEqual: return(cell => cArgument != null && cArgument.CompareTo(isCurrency ? ConvertCurrencyCell(cell, condition.ColumnType) : cell) >= 0); case ConditionType.Contains: return(cell => ((string)cell).IndexOf(sArgument, StringComparison.CurrentCultureIgnoreCase) >= 0); case ConditionType.StartsWith: return(cell => ((string)cell).StartsWith(sArgument, StringComparison.CurrentCultureIgnoreCase)); case ConditionType.EndsWith: return(cell => ((string)cell).EndsWith(sArgument, StringComparison.CurrentCultureIgnoreCase)); case ConditionType.AnyOf: return(cell => AnyOf((long)cell, condition.Arguments)); case ConditionType.AnyExcept: return(cell => AnyExcept((long)cell, condition.Arguments)); case ConditionType.Today: case ConditionType.ThisMonth: case ConditionType.ThisQuarter: case ConditionType.ThisYear: case ConditionType.CurrentFinancialYear: case ConditionType.LastNDays: case ConditionType.NextNDays: case ConditionType.LastNMonths: case ConditionType.NextNMonths: case ConditionType.LastNQuarters: case ConditionType.NextNQuarters: case ConditionType.LastNYears: case ConditionType.NextNYears: case ConditionType.LastNFinancialYears: case ConditionType.NextNFinancialYears: case ConditionType.LastNDaysTillNow: case ConditionType.NextNDaysFromNow: case ConditionType.ThisWeek: case ConditionType.LastNWeeks: case ConditionType.NextNWeeks: return(cell => { DateTime minDate, maxDate; var cellAsDateTime = isDate ? (DateTime)cell : UtcToLocal((DateTime)cell); const int startMonthOfFinancialYear = 7; //TODO: this comes from old code. Reported as a bug to Diana to improve to respect tenant FY configuration. PeriodConditionHelper.GetPeriodFromConditionType(condition.Operator, DateTime.Today, cArgument != null ? cArgument as int?: null, startMonthOfFinancialYear, isDate, out minDate, out maxDate); return cellAsDateTime >= minDate && cellAsDateTime < maxDate; }); case ConditionType.DateEquals: { if (argument != null && argument.Value != null) { DateTime today = ((DateTime)argument.Value).Date; DateTime threshold = today.AddDays(1); return(cell => { DateTime dCell = isDate ? (DateTime)cell : UtcToLocal((DateTime)cell); return threshold.CompareTo(dCell) > 0 && today.CompareTo(dCell) <= 0; }); } } break; case ConditionType.IsTrue: return(cell => ((bool)cell)); case ConditionType.IsFalse: return(cell => !((bool)cell)); case ConditionType.IsNull: return(cell => string.Empty.Equals(cell)); // this method does not get called if it is truly null case ConditionType.IsNotNull: return(cell => !string.Empty.Equals(cell)); // this method does not get called if it is truly null case ConditionType.CurrentUser: return(IsCurrentUser); case ConditionType.AnyBelowStructureLevel: case ConditionType.AnyAboveStructureLevel: case ConditionType.AnyAtOrAboveStructureLevel: case ConditionType.AnyAtOrBelowStructureLevel: return(cell => ApplyStructureViewCondition((string)cell, condition, gridResultColumn, conditionalFormatter)); default: throw new Exception("Unknown filter operator."); } return(null); }
/// <summary> /// Apply the specified structure level condition to the given cell. /// </summary> /// <param name="cellValue">The cell value.</param> /// <param name="condition">The condition.</param> /// <param name="gridResultColumn">The grid result column.</param> /// <param name="conditionalFormatter">The current conditional formatter.</param> /// <returns>True if the operator and arguments apply, false otherwuse</returns> private static bool ApplyStructureViewCondition(string cellValue, Condition condition, ResultColumn gridResultColumn, ConditionalFormatter conditionalFormatter) { IList <TypedValue> arguments = condition.Arguments; ConditionType conditionOperator = condition.Operator; // Sanity check if (arguments == null || arguments.Count <= 0 || string.IsNullOrEmpty(cellValue) || gridResultColumn == null) { return(false); } var structureViewExpression = gridResultColumn.RequestColumn.Expression as StructureViewExpression; if (structureViewExpression == null) { return(false); } // Get the structure levels for this structure view. Dictionary <long, StructureViewLevelsValue> structureViewLevels; if (!conditionalFormatter._structureViewLevelsCache.TryGetValue(structureViewExpression.StructureViewId.Id, out structureViewLevels)) { structureViewLevels = GetStructureViewLevels(structureViewExpression); conditionalFormatter._structureViewLevelsCache[structureViewExpression.StructureViewId.Id] = structureViewLevels; } int colonIndex = cellValue.IndexOf(':'); if (colonIndex <= 0) { return(false); } // Parse the entity id of the current structure level from the cell value string idString = cellValue.Substring(0, colonIndex); long cellEntityId; if (!long.TryParse(idString, out cellEntityId)) { return(false); } // Get all the levels to/from this structure level StructureViewLevelsValue levelsValue; if (!structureViewLevels.TryGetValue(cellEntityId, out levelsValue)) { return(false); } // Check the arguments foreach (var argValueAsString in arguments.Select(argument => argument.Value.ToString())) { // Check for equality if (argValueAsString == idString && (conditionOperator == ConditionType.AnyAtOrAboveStructureLevel || conditionOperator == ConditionType.AnyAtOrBelowStructureLevel)) { return(true); } long argValueAsLong; if (!long.TryParse(argValueAsString, out argValueAsLong)) { continue; } // Check hierarchy switch (conditionOperator) { case ConditionType.AnyAboveStructureLevel: case ConditionType.AnyAtOrAboveStructureLevel: if (levelsValue.ToLevelIds.Contains(argValueAsLong)) { return(true); } break; case ConditionType.AnyAtOrBelowStructureLevel: case ConditionType.AnyBelowStructureLevel: if (levelsValue.FromLevelIds.Contains(argValueAsLong)) { return(true); } break; } } return(false); }
/// <summary> /// Predicates for rule. /// </summary> /// <param name="condition">The condition.</param> /// <param name="isResourceCondition">if set to <c>true</c> [is resource condition].</param> /// <param name="gridResultColumn">The result column.</param> /// <param name="conditionalFormatter">The conditional formatter column.</param> /// <returns>Predicate{System.Object}.</returns> private static Predicate <object> PredicateForRule(Condition condition, bool isResourceCondition, ResultColumn gridResultColumn, ConditionalFormatter conditionalFormatter) { try { Predicate <object> valueFilterPredicate = BuildValueFilterPredicateNoNulls(condition, gridResultColumn, conditionalFormatter); return(value => { try { // Handle nulls // for now ANY type of filter on a column will reject null values if (value == null || value is DBNull) { switch (condition.Operator) { case ConditionType.NotEqual: value = ""; break; case ConditionType.IsNull: return true; case ConditionType.IsNotNull: return false; case ConditionType.AnyExcept: return true; default: return false; } } // Handle transforms if (isResourceCondition) { var xml = (string)value; if (condition.Operator == ConditionType.AnyExcept || condition.Operator == ConditionType.AnyOf || condition.Operator == ConditionType.CurrentUser) { value = DatabaseTypeHelper.GetEntityXmlId(xml); } else { value = DatabaseTypeHelper.GetEntityXmlName(xml); } } // Evaluate the specific predicate return valueFilterPredicate(value); } catch { return false; //throw new Exception( string.Format( "Predicate failed. Data={0} {1}. Expected={2}", value == null ? "null" : value.GetType( ).Name, value, condition.ColumnType ), ex ); } }); } catch (ArgumentException) { return(null); // argument does not exist .. return null } }