using System; using System.Collections.Generic; using SabreTools.Data.Models.Metadata; namespace SabreTools.Metadata.Filter { /// /// Represents a set of filters that can be run against an object /// public class FilterRunner { /// /// Set of filters to be run against an object /// public readonly Dictionary Filters = []; /// /// Cached item type names for filter selection /// #if NET5_0_OR_GREATER private static readonly string[] _datItemTypeNames = Enum.GetNames(); #else private static readonly string[] _datItemTypeNames = Enum.GetNames(typeof(ItemType)); #endif public FilterRunner(FilterObject[] filters) { Array.ForEach(filters, AddFilter); } public FilterRunner(string[] filterStrings) { Array.ForEach(filterStrings, AddFilter); } /// /// Run filtering on an item /// public bool Run(object obj) { string? itemName = obj switch { Header => "header", Machine => "machine", DatItem datItem => datItem.ItemType.ToString(), _ => null, }; // Null is invalid if (itemName is null) return false; // Loop through and run each filter in order foreach (var filterKey in Filters.Keys) { // Skip filters not applicable to the item if (filterKey.StartsWith("item.") && Array.IndexOf(_datItemTypeNames, itemName) == -1) continue; else if (!filterKey.StartsWith("item.") && !filterKey.StartsWith(itemName, StringComparison.OrdinalIgnoreCase)) continue; // If we don't get a match, it's a failure bool matchOne = Filters[filterKey].Matches(obj); if (!matchOne) return false; } return true; } /// /// Add a single filter to the runner in a group by key /// private void AddFilter(FilterObject filter) { // Get the key as a string string key = filter.Key.ToString(); // Set the expected group type GroupType groupType = GroupType.OR; // Special case for size if (filter.Key.ItemName == "item" && filter.Key.FieldName == "size") groupType = GroupType.AND; else if (filter.Key.ItemName == "dataarea" && filter.Key.FieldName == "size") groupType = GroupType.AND; else if (filter.Key.ItemName == "rom" && filter.Key.FieldName == "size") groupType = GroupType.AND; // Ensure the key exists if (!Filters.ContainsKey(key)) Filters[key] = new FilterGroup(groupType); // Add the filter to the set Filters[key].AddFilter(filter); } /// /// Add a single filter to the runner in a group by key /// private void AddFilter(string filterString) { try { var filter = new FilterObject(filterString); AddFilter(filter); } catch { } } } }