using System.Collections.Generic; using System.Linq; #if NET40_OR_GREATER || NETCOREAPP using System.Threading.Tasks; #endif using SabreTools.Core; using SabreTools.Core.Tools; using SabreTools.DatItems; using SabreTools.DatItems.Formats; namespace SabreTools.DatFiles { public partial class DatFile { #region Removal /// /// Remove fields indicated by the three input lists /// public void ApplyRemovals(List headerFieldNames, List machineFieldNames, Dictionary> itemFieldNames) { // Remove DatHeader fields if (headerFieldNames.Count > 0) RemoveHeaderFields(headerFieldNames); // Remove DatItem and Machine fields if (machineFieldNames.Count > 0 || itemFieldNames.Count > 0) { ApplyRemovalsItemDictionary(machineFieldNames, itemFieldNames); ApplyRemovalsItemDictionaryDB(machineFieldNames, itemFieldNames); } } /// /// Apply removals to the item dictionary /// private void ApplyRemovalsItemDictionary(List machineFieldNames, Dictionary> itemFieldNames) { #if NET452_OR_GREATER || NETCOREAPP Parallel.ForEach(Items.Keys, Core.Globals.ParallelOptions, key => #elif NET40_OR_GREATER Parallel.ForEach(Items.Keys, key => #else foreach (var key in Items.Keys) #endif { ConcurrentList? items = Items[key]; if (items == null) #if NET40_OR_GREATER || NETCOREAPP return; #else continue; #endif for (int j = 0; j < items.Count; j++) { RemoveFields(items[j], machineFieldNames, itemFieldNames); } #if NET40_OR_GREATER || NETCOREAPP }); #else } #endif } /// /// Apply removals to the item dictionary /// private void ApplyRemovalsItemDictionaryDB(List machineFieldNames, Dictionary> itemFieldNames) { #if NET452_OR_GREATER || NETCOREAPP Parallel.ForEach(ItemsDB.SortedKeys, Core.Globals.ParallelOptions, key => #elif NET40_OR_GREATER Parallel.ForEach(ItemsDB.SortedKeys, key => #else foreach (var key in ItemsDB.SortedKeys) #endif { var items = ItemsDB.GetItemsForBucket(key); if (items == null) #if NET40_OR_GREATER || NETCOREAPP return; #else continue; #endif for (int j = 0; j < items.Length; j++) { RemoveFields(items[j].Item2, machineFieldNames, itemFieldNames); } #if NET40_OR_GREATER || NETCOREAPP }); #else } #endif } /// /// Remove fields with given values /// private void RemoveHeaderFields(List headerFieldNames) { // If we have an invalid input, return if (Header == null || headerFieldNames.Count == 0) return; foreach (var fieldName in headerFieldNames) { Header.RemoveField(fieldName); } } /// /// Remove fields with given values /// private static void RemoveFields(Machine? machine, List machineFieldNames) { // If we have an invalid input, return if (machine == null || machineFieldNames.Count == 0) return; foreach (var fieldName in machineFieldNames) { machine.RemoveField(fieldName); } } /// /// Remove fields with given values /// /// DatItem to remove fields from private static void RemoveFields(DatItem? datItem, List machineFieldNames, Dictionary> itemFieldNames) { if (datItem == null) return; #region Common // Handle Machine fields var machine = datItem.GetFieldValue(DatItem.MachineKey); if (machineFieldNames.Count > 0 && machine != null) RemoveFields(machine, machineFieldNames); // If there are no field names, return if (itemFieldNames == null || itemFieldNames.Count == 0) return; // If there are no field names for this type or generic, return string? itemType = datItem.GetStringFieldValue(Models.Metadata.DatItem.TypeKey).AsEnumValue().AsStringValue(); if (itemType == null || (!itemFieldNames.ContainsKey(itemType) && !itemFieldNames.ContainsKey("item"))) return; // Get the combined list of fields to remove var fieldNames = new List(); if (itemFieldNames.ContainsKey(itemType)) fieldNames.AddRange(itemFieldNames[itemType]); if (itemFieldNames.ContainsKey("item")) fieldNames.AddRange(itemFieldNames["item"]); fieldNames = fieldNames.Distinct().ToList(); // If the field specifically contains Name, set it separately if (fieldNames.Contains(Models.Metadata.Rom.NameKey)) datItem.SetName(null); #endregion #region Item-Specific // Handle unnested removals first foreach (var datItemField in fieldNames) { datItem.RemoveField(datItemField); } // Handle nested removals switch (datItem) { case Adjuster adjuster: RemoveFields(adjuster, itemFieldNames); break; case Configuration configuration: RemoveFields(configuration, itemFieldNames); break; case ConfSetting confSetting: RemoveFields(confSetting, itemFieldNames); break; case Device device: RemoveFields(device, itemFieldNames); break; case DipSwitch dipSwitch: RemoveFields(dipSwitch, itemFieldNames); break; case DipValue dipValue: RemoveFields(dipValue, itemFieldNames); break; case Disk disk: RemoveFields(disk, itemFieldNames); break; case Input input: RemoveFields(input, itemFieldNames); break; case Part part: RemoveFields(part, itemFieldNames); break; case Port port: RemoveFields(port, itemFieldNames); break; case Rom rom: RemoveFields(rom, itemFieldNames); break; case Slot slot: RemoveFields(slot, itemFieldNames); break; } #endregion } /// /// Remove fields with given values /// /// Adjuster to remove fields from private static void RemoveFields(Adjuster adjuster, Dictionary> itemFieldNames) { var conditions = adjuster.GetFieldValue(Models.Metadata.Adjuster.ConditionKey) ?? []; foreach (Condition subCondition in conditions) { RemoveFields(subCondition, [], itemFieldNames); } } /// /// Remove fields with given values /// /// Configuration to remove fields from private static void RemoveFields(Configuration configuration, Dictionary> itemFieldNames) { var conditions = configuration.GetFieldValue(Models.Metadata.Configuration.ConditionKey) ?? []; foreach (Condition subCondition in conditions) { RemoveFields(subCondition, [], itemFieldNames); } var locations = configuration.GetFieldValue(Models.Metadata.Configuration.ConfLocationKey) ?? []; foreach (ConfLocation subLocation in locations) { RemoveFields(subLocation, [], itemFieldNames); } var settings = configuration.GetFieldValue(Models.Metadata.Configuration.ConfSettingKey) ?? []; foreach (ConfSetting subSetting in settings) { RemoveFields(subSetting as DatItem, [], itemFieldNames); } } /// /// Remove fields with given values /// /// ConfSetting to remove fields from private static void RemoveFields(ConfSetting confsetting, Dictionary> itemFieldNames) { var conditions = confsetting.GetFieldValue(Models.Metadata.ConfSetting.ConditionKey) ?? []; foreach (Condition subCondition in conditions) { RemoveFields(subCondition, [], itemFieldNames); } } /// /// Remove fields with given values /// /// Device to remove fields from private static void RemoveFields(Device device, Dictionary> itemFieldNames) { var extensions = device.GetFieldValue(Models.Metadata.Device.ExtensionKey) ?? []; foreach (Extension subExtension in extensions) { RemoveFields(subExtension, [], itemFieldNames); } var instances = device.GetFieldValue(Models.Metadata.Device.InstanceKey) ?? []; foreach (Instance subInstance in instances) { RemoveFields(subInstance, [], itemFieldNames); } } /// /// Remove fields with given values /// /// DipSwitch to remove fields from private static void RemoveFields(DipSwitch dipSwitch, Dictionary> itemFieldNames) { var conditions = dipSwitch.GetFieldValue(Models.Metadata.DipSwitch.ConditionKey) ?? []; foreach (Condition subCondition in conditions) { RemoveFields(subCondition, [], itemFieldNames); } var locations = dipSwitch.GetFieldValue(Models.Metadata.DipSwitch.DipLocationKey) ?? []; foreach (DipLocation subLocation in locations) { RemoveFields(subLocation, [], itemFieldNames); } var dipValues = dipSwitch.GetFieldValue(Models.Metadata.DipSwitch.DipValueKey) ?? []; foreach (DipValue subValue in dipValues) { RemoveFields(subValue as DatItem, [], itemFieldNames); } var part = dipSwitch.GetFieldValue(DipSwitch.PartKey); if (part != null) RemoveFields(part as DatItem, [], itemFieldNames); } /// /// Remove fields with given values /// /// DipValue to remove fields from private static void RemoveFields(DipValue dipValue, Dictionary> itemFieldNames) { var conditions = dipValue.GetFieldValue(Models.Metadata.DipValue.ConditionKey) ?? []; foreach (Condition subCondition in conditions) { RemoveFields(subCondition, [], itemFieldNames); } } /// /// Remove fields with given values /// /// Disk to remove fields from private static void RemoveFields(Disk disk, Dictionary> itemFieldNames) { var diskArea = disk.GetFieldValue(Disk.DiskAreaKey); if (diskArea != null) RemoveFields(diskArea as DatItem, [], itemFieldNames); var part = disk.GetFieldValue(Disk.PartKey); if (part != null) RemoveFields(part as DatItem, [], itemFieldNames); } /// /// Remove fields with given values /// /// Input to remove fields from private static void RemoveFields(Input input, Dictionary> itemFieldNames) { var controls = input.GetFieldValue(Models.Metadata.Input.ControlKey) ?? []; foreach (Control subControl in controls) { RemoveFields(subControl, [], itemFieldNames); } } /// /// Remove fields with given values /// /// Part to remove fields from private static void RemoveFields(Part part, Dictionary> itemFieldNames) { var features = part.GetFieldValue(Models.Metadata.Part.FeatureKey) ?? []; foreach (PartFeature subPartFeature in features) { RemoveFields(subPartFeature, [], itemFieldNames); } } /// /// Remove fields with given values /// /// Port to remove fields from private static void RemoveFields(Port port, Dictionary> itemFieldNames) { var analogs = port.GetFieldValue(Models.Metadata.Port.AnalogKey) ?? []; foreach (Analog subAnalog in analogs) { RemoveFields(subAnalog, [], itemFieldNames); } } /// /// Remove fields with given values /// /// Rom to remove fields from private static void RemoveFields(Rom rom, Dictionary> itemFieldNames) { var dataArea = rom.GetFieldValue(Rom.DataAreaKey); if (dataArea != null) RemoveFields(dataArea as DatItem, [], itemFieldNames); var part = rom.GetFieldValue(Rom.PartKey); if (part != null) RemoveFields(part as DatItem, [], itemFieldNames); } /// /// Remove fields with given values /// /// Slot to remove fields from private static void RemoveFields(Slot slot, Dictionary> itemFieldNames) { var slotOptions = slot.GetFieldValue(Models.Metadata.Slot.SlotOptionKey) ?? []; foreach (SlotOption subSlotOption in slotOptions) { RemoveFields(subSlotOption, [], itemFieldNames); } } #endregion } }