using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; 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, 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, Globals.ParallelOptions, key => #elif NET40_OR_GREATER Parallel.ForEach(ItemsDB.SortedKeys, key => #else foreach (var key in ItemsDB.SortedKeys) #endif { var items = ItemsDB.GetDatItemsForBucket(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.Any()) 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.Any()) 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 if (machineFieldNames.Any() && datItem.GetFieldValue(DatItem.MachineKey) != null) RemoveFields(datItem.GetFieldValue(DatItem.MachineKey), machineFieldNames); // If there are no field names, return if (itemFieldNames == null || !itemFieldNames.Any()) 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) { if (!adjuster.ConditionsSpecified) return; foreach (Condition subCondition in adjuster.GetFieldValue(Models.Metadata.Adjuster.ConditionKey)!) { RemoveFields(subCondition, [], itemFieldNames); } } /// /// Remove fields with given values /// /// Configuration to remove fields from private static void RemoveFields(Configuration configuration, Dictionary> itemFieldNames) { if (configuration.ConditionsSpecified) { foreach (Condition subCondition in configuration.GetFieldValue(Models.Metadata.Configuration.ConditionKey)!) { RemoveFields(subCondition, [], itemFieldNames); } } if (configuration.LocationsSpecified) { foreach (ConfLocation subLocation in configuration.GetFieldValue(Models.Metadata.Configuration.ConfLocationKey)!) { RemoveFields(subLocation, [], itemFieldNames); } } if (configuration.SettingsSpecified) { foreach (ConfSetting subSetting in configuration.GetFieldValue(Models.Metadata.Configuration.ConfSettingKey)!) { RemoveFields(subSetting as DatItem, [], itemFieldNames); } } } /// /// Remove fields with given values /// /// ConfSetting to remove fields from private static void RemoveFields(ConfSetting confsetting, Dictionary> itemFieldNames) { if (confsetting.ConditionsSpecified) { foreach (Condition subCondition in confsetting.GetFieldValue(Models.Metadata.ConfSetting.ConditionKey)!) { RemoveFields(subCondition, [], itemFieldNames); } } } /// /// Remove fields with given values /// /// Device to remove fields from private static void RemoveFields(Device device, Dictionary> itemFieldNames) { if (device.ExtensionsSpecified) { foreach (Extension subExtension in device.GetFieldValue(Models.Metadata.Device.ExtensionKey)!) { RemoveFields(subExtension, [], itemFieldNames); } } if (device.InstancesSpecified) { foreach (Instance subInstance in device.GetFieldValue(Models.Metadata.Device.InstanceKey)!) { RemoveFields(subInstance, [], itemFieldNames); } } } /// /// Remove fields with given values /// /// DipSwitch to remove fields from private static void RemoveFields(DipSwitch dipSwitch, Dictionary> itemFieldNames) { if (dipSwitch.ConditionsSpecified) { foreach (Condition subCondition in dipSwitch.GetFieldValue(Models.Metadata.DipSwitch.ConditionKey)!) { RemoveFields(subCondition, [], itemFieldNames); } } if (dipSwitch.LocationsSpecified) { foreach (DipLocation subLocation in dipSwitch.GetFieldValue(Models.Metadata.DipSwitch.DipLocationKey)!) { RemoveFields(subLocation, [], itemFieldNames); } } if (dipSwitch.ValuesSpecified) { foreach (DipValue subValue in dipSwitch.GetFieldValue(Models.Metadata.DipSwitch.DipValueKey)!) { RemoveFields(subValue as DatItem, [], itemFieldNames); } } if (dipSwitch.PartSpecified) RemoveFields(dipSwitch.GetFieldValue(DipSwitch.PartKey)! as DatItem, [], itemFieldNames); } /// /// Remove fields with given values /// /// DipValue to remove fields from private static void RemoveFields(DipValue dipValue, Dictionary> itemFieldNames) { if (dipValue.ConditionsSpecified) { foreach (Condition subCondition in dipValue.GetFieldValue(Models.Metadata.DipValue.ConditionKey)!) { RemoveFields(subCondition, [], itemFieldNames); } } } /// /// Remove fields with given values /// /// Disk to remove fields from private static void RemoveFields(Disk disk, Dictionary> itemFieldNames) { if (disk.DiskAreaSpecified) RemoveFields(disk.GetFieldValue(Disk.DiskAreaKey)! as DatItem, [], itemFieldNames); if (disk.PartSpecified) RemoveFields(disk.GetFieldValue(Disk.PartKey)! as DatItem, [], itemFieldNames); } /// /// Remove fields with given values /// /// Input to remove fields from private static void RemoveFields(Input input, Dictionary> itemFieldNames) { if (input.ControlsSpecified) { foreach (Control subControl in input.GetFieldValue(Models.Metadata.Input.ControlKey)!) { RemoveFields(subControl, [], itemFieldNames); } } } /// /// Remove fields with given values /// /// Part to remove fields from private static void RemoveFields(Part part, Dictionary> itemFieldNames) { if (part.FeaturesSpecified) { foreach (PartFeature subPartFeature in part.GetFieldValue(Models.Metadata.Part.FeatureKey)!) { RemoveFields(subPartFeature, [], itemFieldNames); } } } /// /// Remove fields with given values /// /// Port to remove fields from private static void RemoveFields(Port port, Dictionary> itemFieldNames) { if (port.AnalogsSpecified) { foreach (Analog subAnalog in port.GetFieldValue(Models.Metadata.Port.AnalogKey)!) { RemoveFields(subAnalog, [], itemFieldNames); } } } /// /// Remove fields with given values /// /// Rom to remove fields from private static void RemoveFields(Rom rom, Dictionary> itemFieldNames) { if (rom.DataAreaSpecified) RemoveFields(rom.GetFieldValue(Rom.DataAreaKey)!, [], itemFieldNames); if (rom.PartSpecified) RemoveFields(rom.GetFieldValue(Rom.PartKey)! as DatItem, [], itemFieldNames); } /// /// Remove fields with given values /// /// Slot to remove fields from private static void RemoveFields(Slot slot, Dictionary> itemFieldNames) { if (slot.SlotOptionsSpecified) { foreach (SlotOption subSlotOption in slot.GetFieldValue(Models.Metadata.Slot.SlotOptionKey)!) { RemoveFields(subSlotOption, [], itemFieldNames); } } } #endregion } }