diff --git a/SabreTools.Data.Extensions/MetadataExtensions.cs b/SabreTools.Data.Extensions/MetadataExtensions.cs index 21a2ed31..19a14578 100644 --- a/SabreTools.Data.Extensions/MetadataExtensions.cs +++ b/SabreTools.Data.Extensions/MetadataExtensions.cs @@ -163,6 +163,8 @@ namespace SabreTools.Data.Extensions return confSetting.Clone() as ConfSetting; else if (self is Control control) return control.Clone() as Control; + else if (self is Device device) + return device.Clone() as Device; else if (self is DeviceRef deviceRef) return deviceRef.Clone() as DeviceRef; else if (self is DipLocation dipLocation) @@ -222,14 +224,6 @@ namespace SabreTools.Data.Extensions cloneDataArea.Size = selfDataArea.Size; cloneDataArea.Width = selfDataArea.Width; } - else if (self is Device selfDevice && clone is Device cloneDevice) - { - cloneDevice.DeviceType = selfDevice.DeviceType; - cloneDevice.FixedImage = selfDevice.FixedImage; - cloneDevice.Interface = selfDevice.Interface; - cloneDevice.Mandatory = selfDevice.Mandatory; - cloneDevice.Tag = selfDevice.Tag; - } else if (self is Disk selfDisk && clone is Disk cloneDisk) { cloneDisk.Optional = selfDisk.Optional; diff --git a/SabreTools.Data.Models/Metadata/Device.cs b/SabreTools.Data.Models/Metadata/Device.cs index 6bcc0ce0..8e44cd27 100644 --- a/SabreTools.Data.Models/Metadata/Device.cs +++ b/SabreTools.Data.Models/Metadata/Device.cs @@ -1,18 +1,23 @@ +using System; using System.Xml.Serialization; using Newtonsoft.Json; namespace SabreTools.Data.Models.Metadata { [JsonObject("device"), XmlRoot("device")] - public class Device : DatItem + public class Device : DatItem, ICloneable, IEquatable { #region Properties /// (unknown|cartridge|floppydisk|harddisk|cylinder|cassette|punchcard|punchtape|printout|serial|parallel|snapshot|quickload|memcard|cdrom|magtape|romimage|midiin|midiout|picture|vidfile) public DeviceType? DeviceType { get; set; } + public Extension[]? Extension { get; set; } + public string? FixedImage { get; set; } + public Instance? Instance { get; set; } + public string? Interface { get; set; } /// (0|1) "0" @@ -22,18 +27,63 @@ namespace SabreTools.Data.Models.Metadata #endregion - #region Keys - - /// Extension[] - [NoFilter] - public const string ExtensionKey = "extension"; - - /// Instance - [NoFilter] - public const string InstanceKey = "instance"; - - #endregion - public Device() => ItemType = ItemType.Device; + + /// + public object Clone() + { + var obj = new Device(); + + obj.DeviceType = DeviceType; + if (Extension is not null) + obj.Extension = Array.ConvertAll(Extension, i => (Extension)i.Clone()); + obj.FixedImage = FixedImage; + obj.Instance = Instance?.Clone() as Instance; + obj.Interface = Interface; + obj.Mandatory = Mandatory; + obj.Tag = Tag; + + return obj; + } + + /// + public bool Equals(Device? other) + { + // Null never matches + if (other is null) + return false; + + // Properties + if (DeviceType != other.DeviceType) + return false; + + if ((FixedImage is null) ^ (other.FixedImage is null)) + return false; + else if (FixedImage is not null && !FixedImage.Equals(other.FixedImage, StringComparison.OrdinalIgnoreCase)) + return false; + + if ((Interface is null) ^ (other.Interface is null)) + return false; + else if (Interface is not null && !Interface.Equals(other.Interface, StringComparison.OrdinalIgnoreCase)) + return false; + + if (Mandatory != other.Mandatory) + return false; + + if ((Tag is null) ^ (other.Tag is null)) + return false; + else if (Tag is not null && !Tag.Equals(other.Tag, StringComparison.OrdinalIgnoreCase)) + return false; + + // Sub-items + if ((Instance is null) ^ (other.Instance is null)) + return false; + else if (Instance is not null && other.Instance is not null && Instance.Equals(other.Instance)) + return false; + + // TODO: Figure out how to properly check arrays + + return true; + } } } diff --git a/SabreTools.Metadata.DatFiles.Test/DatFileTests.FromMetadata.cs b/SabreTools.Metadata.DatFiles.Test/DatFileTests.FromMetadata.cs index f654b858..fa348f4b 100644 --- a/SabreTools.Metadata.DatFiles.Test/DatFileTests.FromMetadata.cs +++ b/SabreTools.Metadata.DatFiles.Test/DatFileTests.FromMetadata.cs @@ -481,9 +481,9 @@ namespace SabreTools.Metadata.DatFiles.Test { return new Data.Models.Metadata.Device { - [Data.Models.Metadata.Device.ExtensionKey] = new Data.Models.Metadata.Extension[] { CreateMetadataExtension() }, + Extension = [CreateMetadataExtension()], FixedImage = "fixedimage", - [Data.Models.Metadata.Device.InstanceKey] = CreateMetadataInstance(), + Instance = CreateMetadataInstance(), Interface = "interface", Mandatory = true, Tag = "tag", @@ -1246,13 +1246,12 @@ namespace SabreTools.Metadata.DatFiles.Test Assert.Equal("tag", device.Tag); Assert.Equal(Data.Models.Metadata.DeviceType.PunchTape, device.DeviceType); - Extension[]? extensions = device.Read(Data.Models.Metadata.Device.ExtensionKey); + Extension[]? extensions = device.Extension; Assert.NotNull(extensions); Extension? extension = Assert.Single(extensions); ValidateExtension(extension); - Instance? instance = device.Read(Data.Models.Metadata.Device.InstanceKey); - ValidateInstance(instance); + ValidateInstance(device.Instance); } private static void ValidateDeviceRef(DeviceRef? deviceRef) diff --git a/SabreTools.Metadata.DatFiles.Test/DatFileTests.ToMetadata.cs b/SabreTools.Metadata.DatFiles.Test/DatFileTests.ToMetadata.cs index db69cdf0..9b8a24cd 100644 --- a/SabreTools.Metadata.DatFiles.Test/DatFileTests.ToMetadata.cs +++ b/SabreTools.Metadata.DatFiles.Test/DatFileTests.ToMetadata.cs @@ -776,13 +776,12 @@ namespace SabreTools.Metadata.DatFiles.Test Assert.Equal("tag", device.Tag); Assert.Equal(Data.Models.Metadata.DeviceType.PunchTape, device.DeviceType); - Data.Models.Metadata.Extension[]? extensions = device.ReadArray(Data.Models.Metadata.Device.ExtensionKey); + Data.Models.Metadata.Extension[]? extensions = device.Extension; Assert.NotNull(extensions); Data.Models.Metadata.Extension? extension = Assert.Single(extensions); ValidateMetadataExtension(extension); - Data.Models.Metadata.Instance? instance = device.Read(Data.Models.Metadata.Device.InstanceKey); - ValidateMetadataInstance(instance); + ValidateMetadataInstance(device.Instance); } private static void ValidateMetadataDeviceRef(Data.Models.Metadata.DeviceRef? deviceRef) diff --git a/SabreTools.Metadata.DatItems/Formats/Device.cs b/SabreTools.Metadata.DatItems/Formats/Device.cs index 6cac1b9d..5acefc14 100644 --- a/SabreTools.Metadata.DatItems/Formats/Device.cs +++ b/SabreTools.Metadata.DatItems/Formats/Device.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Xml.Serialization; using Newtonsoft.Json; using SabreTools.Data.Extensions; @@ -19,15 +19,10 @@ namespace SabreTools.Metadata.DatItems.Formats set => (_internal as Data.Models.Metadata.Device)?.DeviceType = value; } + public Extension[]? Extension { get; set; } + [JsonIgnore] - public bool ExtensionsSpecified - { - get - { - var extensions = Read(Data.Models.Metadata.Device.ExtensionKey); - return extensions is not null && extensions.Length > 0; - } - } + public bool ExtensionSpecified => Extension is not null && Extension.Length > 0; public string? FixedImage { @@ -35,15 +30,10 @@ namespace SabreTools.Metadata.DatItems.Formats set => (_internal as Data.Models.Metadata.Device)?.FixedImage = value; } + public Instance? Instance { get; set; } + [JsonIgnore] - public bool InstancesSpecified - { - get - { - var instances = Read(Data.Models.Metadata.Device.InstanceKey); - return instances is not null && instances.Length > 0; - } - } + public bool InstanceSpecified => Instance is not null; public string? Interface { @@ -76,16 +66,11 @@ namespace SabreTools.Metadata.DatItems.Formats public Device(Data.Models.Metadata.Device item) : base(item) { // Handle subitems - var instance = item.Read(Data.Models.Metadata.Device.InstanceKey); - if (instance is not null) - Write(Data.Models.Metadata.Device.InstanceKey, new Instance(instance)); + if (item.Extension is not null) + Extension = Array.ConvertAll(item.Extension, extension => new Extension(extension)); ; - var extensions = item.ReadArray(Data.Models.Metadata.Device.ExtensionKey); - if (extensions is not null) - { - Extension[] extensionItems = Array.ConvertAll(extensions, extension => new Extension(extension)); - Write(Data.Models.Metadata.Device.ExtensionKey, extensionItems); - } + if (item.Instance is not null) + Instance = new Instance(item.Instance); } public Device(Data.Models.Metadata.Device item, Machine machine, Source source) : this(item) @@ -112,16 +97,11 @@ namespace SabreTools.Metadata.DatItems.Formats deviceItem.Mandatory = Mandatory; deviceItem.Tag = Tag; - var instance = Read(Data.Models.Metadata.Device.InstanceKey); - if (instance is not null) - deviceItem[Data.Models.Metadata.Device.InstanceKey] = instance.GetInternalClone(); + if (Instance is not null) + deviceItem.Instance = Instance.GetInternalClone(); - var extensions = Read(Data.Models.Metadata.Device.ExtensionKey); - if (extensions is not null) - { - Data.Models.Metadata.Extension[] extensionItems = Array.ConvertAll(extensions, extension => extension.GetInternalClone()); - deviceItem[Data.Models.Metadata.Device.ExtensionKey] = extensionItems; - } + if (Extension is not null) + deviceItem.Extension = Array.ConvertAll(Extension, extension => extension.GetInternalClone()); ; return deviceItem; } diff --git a/SabreTools.Metadata/DictionaryBaseExtensions.cs b/SabreTools.Metadata/DictionaryBaseExtensions.cs index d4e541c0..940a913c 100644 --- a/SabreTools.Metadata/DictionaryBaseExtensions.cs +++ b/SabreTools.Metadata/DictionaryBaseExtensions.cs @@ -123,15 +123,7 @@ namespace SabreTools.Metadata } else if (self is Device selfDevice && other is Device otherDevice) { - if (selfDevice.DeviceType != otherDevice.DeviceType) - return false; - if (selfDevice.FixedImage != otherDevice.FixedImage) - return false; - if (selfDevice.Interface != otherDevice.Interface) - return false; - if (selfDevice.Mandatory != otherDevice.Mandatory) - return false; - if (selfDevice.Tag != otherDevice.Tag) + if (!selfDevice.Equals(otherDevice)) return false; } else if (self is DipLocation selfDipLocation && other is DipLocation otherDipLocation) @@ -141,23 +133,8 @@ namespace SabreTools.Metadata } else if (self is DipSwitch selfDipSwitch && other is DipSwitch otherDipSwitch) { - if (selfDipSwitch.Default != otherDipSwitch.Default) + if (!selfDipSwitch.Equals(otherDipSwitch)) return false; - if (selfDipSwitch.Mask != otherDipSwitch.Mask) - return false; - if (selfDipSwitch.Tag != otherDipSwitch.Tag) - return false; - - if ((selfDipSwitch.Condition is null) ^ (otherDipSwitch.Condition is null)) - { - return false; - } - else if (selfDipSwitch.Condition is not null - && otherDipSwitch.Condition is not null - && selfDipSwitch.Condition.EqualTo(otherDipSwitch.Condition)) - { - return false; - } } else if (self is DipValue selfDipValue && other is DipValue otherDipValue) { diff --git a/SabreTools.Serialization.CrossModel/Listxml.Deserializer.cs b/SabreTools.Serialization.CrossModel/Listxml.Deserializer.cs index 801b684c..095d4997 100644 --- a/SabreTools.Serialization.CrossModel/Listxml.Deserializer.cs +++ b/SabreTools.Serialization.CrossModel/Listxml.Deserializer.cs @@ -313,11 +313,11 @@ namespace SabreTools.Serialization.CrossModel Interface = item.Interface, }; - var instance = item.Read(Data.Models.Metadata.Device.InstanceKey); + var instance = item.Instance; if (instance is not null) device.Instance = ConvertFromInternalModel(instance); - var extensions = item.Read(Data.Models.Metadata.Device.ExtensionKey); + var extensions = item.Extension; if (extensions is not null && extensions.Length > 0) device.Extension = Array.ConvertAll(extensions, ConvertFromInternalModel); diff --git a/SabreTools.Serialization.CrossModel/Listxml.Serializer.cs b/SabreTools.Serialization.CrossModel/Listxml.Serializer.cs index af59f7d1..b810bfd2 100644 --- a/SabreTools.Serialization.CrossModel/Listxml.Serializer.cs +++ b/SabreTools.Serialization.CrossModel/Listxml.Serializer.cs @@ -343,13 +343,10 @@ namespace SabreTools.Serialization.CrossModel }; if (item.Instance is not null) - device[Data.Models.Metadata.Device.InstanceKey] = ConvertToInternalModel(item.Instance); + device.Instance = ConvertToInternalModel(item.Instance); if (item.Extension is not null && item.Extension.Length > 0) - { - device[Data.Models.Metadata.Device.ExtensionKey] - = Array.ConvertAll(item.Extension, ConvertToInternalModel); - } + device.Extension = Array.ConvertAll(item.Extension, ConvertToInternalModel); return device; }