/// <summary> /// Handles the recurring element filters. /// </summary> /// <param name="propertyPath">The property path.</param> /// <param name="isRecurringCriteria">if set to <c>true</c> is recurring criteria.</param> protected virtual void HandleRecurringElementFilters(string propertyPath, bool isRecurringCriteria = false) { // Pull the current filter off the stack var filter = Context.RecurringFilterStack.Pop(); // Peek at the next filter in the stack, if any var next = Context.RecurringFilterStack.Any() ? Context.RecurringFilterStack.Peek() : null; if (Context.CurrentRecurringFilters.Any()) { var filters = Context.CurrentRecurringFilters.ToArray(); // Recurring criteria are joined with OR if (isRecurringCriteria) { var recurringFilter = new RecurringElementFilter(propertyPath, filters); filter.Filters.Add(recurringFilter); } else // Otherwise join with AND { filter.Filters.AddRange(filters); } } // Reset the reference for the previous list of filters Context.CurrentRecurringFilters = filter.PreviousFilters; filter.PreviousFilters = null; // Stop processing if no filters were included if (!filter.Filters.Any()) { return; } // Check if this filter should be combined with the next filter in the stack if (filter.PropertyPath == next?.PropertyPath) { Context.CurrentRecurringFilters.Add(filter); } else // Otherwise add as root level filters { Context.RecurringElementFilters.Add(filter); // Stop processing if not handling a nested recurring element if (next == null) { return; } // Add filter for parent recurring element when nested recurring elements are filtered Context.CurrentRecurringFilters.Add(new RecurringElementFilter(GetNestedPath(filter.PropertyPath), "Any()", (dataObject, instance, recurringFilter) => recurringFilter.GetPropertyValue <IList>(instance)?.Count > 0)); } }
/// <summary> /// Initializes the recurring element filters. /// </summary> /// <param name="propertyPath">The property path.</param> protected virtual void InitializeRecurringElementFilter(string propertyPath) { var filter = new RecurringElementFilter(propertyPath) { // Keep a reference to the previous list of filters PreviousFilters = Context.CurrentRecurringFilters }; // Put the new filter on the stack Context.RecurringFilterStack.Push(filter); // Initialize the list of filters for the current recurring element Context.CurrentRecurringFilters = new List <RecurringElementFilter>(); }
/// <summary> /// Filters the recurring elements. /// </summary> /// <param name="dataObject">The data object.</param> /// <param name="instance">The instance.</param> /// <param name="filter">The filter.</param> /// <param name="propertyPath">The property path.</param> protected virtual bool FilterRecurringElements(object dataObject, object instance, RecurringElementFilter filter, string propertyPath) { var propertyNames = propertyPath.Split('.'); IList recurringElementList = null; // Find recurring element list(s) in property path for (var i = 0; i < propertyNames.Length; i++) { // Stop processing if the object instance is null if (instance == null) { return(false); } // Process nested recurring elements if (recurringElementList != null) { var nestedPath = string.Join(".", propertyNames.Skip(i)); return(recurringElementList.Cast <object>() .Aggregate(true, (current, recurringItem) => FilterRecurringElements(dataObject, recurringItem, filter, nestedPath) && current)); } var propertyType = instance.GetType(); var propertyName = propertyNames[i]; var propertyInfo = propertyType.GetProperty(propertyName); // Stop processing if the property was not found if (propertyInfo == null) { return(false); } // Get the current property value instance = propertyInfo.GetValue(instance); recurringElementList = instance as IList; } // Stop processing if the list is null if (recurringElementList == null) { return(false); } // Process recurring elements var filteredItems = new ArrayList(); foreach (var recurringItem in recurringElementList) { // Check if recurring element doesn't meet criteria if (!filter.Predicate(dataObject, recurringItem, filter)) { filteredItems.Add(recurringItem); } } // Remove filtered items from original list foreach (var item in filteredItems) { recurringElementList.Remove(item); } return(recurringElementList.Count <= 0); }