diff --git a/SabreTools.Data.Extensions/MetadataExtensions.cs b/SabreTools.Data.Extensions/MetadataExtensions.cs index d4bfdab6..64f17a16 100644 --- a/SabreTools.Data.Extensions/MetadataExtensions.cs +++ b/SabreTools.Data.Extensions/MetadataExtensions.cs @@ -165,6 +165,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 DataArea dataArea) + return dataArea.Clone() as DataArea; else if (self is Device device) return device.Clone() as Device; else if (self is DeviceRef deviceRef) @@ -177,15 +179,16 @@ namespace SabreTools.Data.Extensions return dipValue.Clone() as DipValue; else if (self is Disk disk) return disk.Clone() as Disk; + else if (self is DiskArea diskArea) + return diskArea.Clone() as DiskArea; else if (self is Display display) return display.Clone() as Display; else if (self is Driver driver) return driver.Clone() as Driver; else if (self is Extension extension) return extension.Clone() as Extension; - // TODO: Reenable when PartFeature no longer needs nesting - // else if (self is Feature feature) - // return feature.Clone() as Feature; + else if (self is Feature feature) + return feature.Clone() as Feature; else if (self is Info info) return info.Clone() as Info; else if (self is Input input) @@ -196,6 +199,8 @@ namespace SabreTools.Data.Extensions return media.Clone() as Media; else if (self is Original original) return original.Clone() as Original; + else if (self is Part part) + return part.Clone() as Part; else if (self is Port port) return port.Clone() as Port; else if (self is RamOption ramOption) @@ -204,6 +209,8 @@ namespace SabreTools.Data.Extensions return release.Clone() as Release; else if (self is ReleaseDetails releaseDetails) return releaseDetails.Clone() as ReleaseDetails; + else if (self is Rom rom) + return rom.Clone() as Rom; else if (self is Serials serials) return serials.Clone() as Serials; else if (self is SharedFeat sharedFeat) @@ -226,22 +233,7 @@ namespace SabreTools.Data.Extensions return null; // Handle individual type properties - if (self is DataArea selfDataArea && clone is DataArea cloneDataArea) - { - cloneDataArea.Endianness = selfDataArea.Endianness; - cloneDataArea.Size = selfDataArea.Size; - cloneDataArea.Width = selfDataArea.Width; - } - else if (self is Feature selfFeature && clone is Feature cloneFeature) - { - // TODO: Remove when PartFeature no longer needs nesting - cloneFeature.FeatureType = selfFeature.FeatureType; - cloneFeature.Name = selfFeature.Name; - cloneFeature.Overall = selfFeature.Overall; - cloneFeature.Status = selfFeature.Status; - cloneFeature.Value = selfFeature.Value; - } - else if (self is Header selfHeader && clone is Header cloneHeader) + if (self is Header selfHeader && clone is Header cloneHeader) { cloneHeader.Author = selfHeader.Author; cloneHeader.BiosMode = selfHeader.BiosMode; @@ -329,25 +321,6 @@ namespace SabreTools.Data.Extensions cloneMachine.Url = selfMachine.Url; cloneMachine.Year = selfMachine.Year; } - else if (self is Part selfPart && clone is Part clonePart) - { - clonePart.Interface = selfPart.Interface; - } - else if (self is Rom selfRom && clone is Rom cloneRom) - { - cloneRom.Dispose = selfRom.Dispose; - cloneRom.FileCount = selfRom.FileCount; - cloneRom.FileIsAvailable = selfRom.FileIsAvailable; - cloneRom.Inverted = selfRom.Inverted; - cloneRom.LoadFlag = selfRom.LoadFlag; - cloneRom.MIA = selfRom.MIA; - cloneRom.OpenMSXMediaType = selfRom.OpenMSXMediaType; - cloneRom.Optional = selfRom.Optional; - cloneRom.Size = selfRom.Size; - cloneRom.SoundOnly = selfRom.SoundOnly; - cloneRom.Status = selfRom.Status; - cloneRom.Value = selfRom.Value; - } // Handle known properties clone.SetName(self.GetName()); diff --git a/SabreTools.Data.Models/Metadata/DataArea.cs b/SabreTools.Data.Models/Metadata/DataArea.cs index be3f714c..cbbb9944 100644 --- a/SabreTools.Data.Models/Metadata/DataArea.cs +++ b/SabreTools.Data.Models/Metadata/DataArea.cs @@ -1,10 +1,11 @@ +using System; using System.Xml.Serialization; using Newtonsoft.Json; namespace SabreTools.Data.Models.Metadata { [JsonObject("dataarea"), XmlRoot("dataarea")] - public class DataArea : DatItem + public class DataArea : DatItem, ICloneable, IEquatable { #region Properties @@ -13,6 +14,8 @@ namespace SabreTools.Data.Models.Metadata public string? Name { get; set; } + public Rom[]? Rom { get; set; } + public long? Size { get; set; } /// (8|16|32|64) "8" @@ -20,14 +23,49 @@ namespace SabreTools.Data.Models.Metadata #endregion - #region Keys - - /// Rom[] - [NoFilter] - public const string RomKey = "rom"; - - #endregion - public DataArea() => ItemType = ItemType.DataArea; + + /// + public object Clone() + { + var obj = new DataArea(); + + obj.Endianness = Endianness; + obj.Name = Name; + if (Rom is not null) + obj.Rom = Array.ConvertAll(Rom, i => (Rom)i.Clone()); + obj.Size = Size; + obj.Width = Width; + + return obj; + } + + /// + public bool Equals(DataArea? other) + { + // Null never matches + if (other is null) + return false; + + // Properties + if (Endianness != other.Endianness) + return false; + + if ((Name is null) ^ (other.Name is null)) + return false; + else if (Name is not null && !Name.Equals(other.Name, StringComparison.OrdinalIgnoreCase)) + return false; + + if (Size != other.Size) + return false; + + if (Width != other.Width) + return false; + + // Sub-items + // TODO: Figure out how to properly check arrays + + return true; + } } } diff --git a/SabreTools.Data.Models/Metadata/DiskArea.cs b/SabreTools.Data.Models/Metadata/DiskArea.cs index 87e68a86..b82b168a 100644 --- a/SabreTools.Data.Models/Metadata/DiskArea.cs +++ b/SabreTools.Data.Models/Metadata/DiskArea.cs @@ -1,25 +1,51 @@ +using System; using System.Xml.Serialization; using Newtonsoft.Json; namespace SabreTools.Data.Models.Metadata { [JsonObject("diskarea"), XmlRoot("diskarea")] - public class DiskArea : DatItem + public class DiskArea : DatItem, ICloneable, IEquatable { #region Properties + public Disk[]? Disk { get; set; } + public string? Name { get; set; } #endregion - #region Keys - - /// Disk[] - [NoFilter] - public const string DiskKey = "disk"; - - #endregion - public DiskArea() => ItemType = ItemType.DiskArea; + + /// + public object Clone() + { + var obj = new DiskArea(); + + if (Disk is not null) + obj.Disk = Array.ConvertAll(Disk, i => (Disk)i.Clone()); + obj.Name = Name; + + return obj; + } + + /// + public bool Equals(DiskArea? other) + { + // Null never matches + if (other is null) + return false; + + // Properties + if ((Name is null) ^ (other.Name is null)) + return false; + else if (Name is not null && !Name.Equals(other.Name, StringComparison.OrdinalIgnoreCase)) + return false; + + // Sub-items + // TODO: Figure out how to properly check arrays + + return true; + } } } diff --git a/SabreTools.Data.Models/Metadata/Part.cs b/SabreTools.Data.Models/Metadata/Part.cs index eb093999..1be988b9 100644 --- a/SabreTools.Data.Models/Metadata/Part.cs +++ b/SabreTools.Data.Models/Metadata/Part.cs @@ -1,39 +1,71 @@ +using System; using System.Xml.Serialization; using Newtonsoft.Json; namespace SabreTools.Data.Models.Metadata { [JsonObject("part"), XmlRoot("part")] - public class Part : DatItem + public class Part : DatItem, ICloneable, IEquatable { #region Properties + public DataArea[]? DataArea { get; set; } + + public DiskArea[]? DiskArea { get; set; } + + public DipSwitch[]? DipSwitch { get; set; } + + public Feature[]? Feature { get; set; } + public string? Interface { get; set; } public string? Name { get; set; } #endregion - #region Keys - - /// DataArea[] - [NoFilter] - public const string DataAreaKey = "dataarea"; - - /// DiskArea[] - [NoFilter] - public const string DiskAreaKey = "diskarea"; - - /// DipSwitch[] - [NoFilter] - public const string DipSwitchKey = "dipswitch"; - - /// Feature[] - [NoFilter] - public const string FeatureKey = "feature"; - - #endregion - public Part() => ItemType = ItemType.Part; + + /// + public object Clone() + { + var obj = new Part(); + + if (DataArea is not null) + obj.DataArea = Array.ConvertAll(DataArea, i => (DataArea)i.Clone()); + if (DiskArea is not null) + obj.DiskArea = Array.ConvertAll(DiskArea, i => (DiskArea)i.Clone()); + if (DipSwitch is not null) + obj.DipSwitch = Array.ConvertAll(DipSwitch, i => (DipSwitch)i.Clone()); + if (Feature is not null) + obj.Feature = Array.ConvertAll(Feature, i => (Feature)i.Clone()); + obj.Interface = Interface; + obj.Name = Name; + + return obj; + } + + /// + public bool Equals(Part? other) + { + // Null never matches + if (other is null) + return false; + + // Properties + 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 ((Name is null) ^ (other.Name is null)) + return false; + else if (Name is not null && !Name.Equals(other.Name, StringComparison.OrdinalIgnoreCase)) + return false; + + // Sub-items + // TODO: Figure out how to properly check arrays + + return true; + } } } diff --git a/SabreTools.Data.Models/Metadata/Rom.cs b/SabreTools.Data.Models/Metadata/Rom.cs index 190e65dd..a5ca4991 100644 --- a/SabreTools.Data.Models/Metadata/Rom.cs +++ b/SabreTools.Data.Models/Metadata/Rom.cs @@ -1,10 +1,12 @@ +using System; using System.Xml.Serialization; using Newtonsoft.Json; namespace SabreTools.Data.Models.Metadata { + // TODO: IEquatable [JsonObject("rom"), XmlRoot("rom")] - public class Rom : DatItem + public class Rom : DatItem, ICloneable { #region Properties @@ -300,5 +302,195 @@ namespace SabreTools.Data.Models.Metadata #endregion public Rom() => ItemType = ItemType.Rom; + + /// + public object Clone() + { + var obj = new Rom(); + + obj.Dispose = Dispose; + obj.FileCount = FileCount; + obj.FileIsAvailable = FileIsAvailable; + obj.Inverted = Inverted; + obj.LoadFlag = LoadFlag; + obj.MIA = MIA; + obj.Name = Name; + obj.OpenMSXMediaType = OpenMSXMediaType; + obj.Optional = Optional; + obj.Size = Size; + obj.SoundOnly = SoundOnly; + obj.Status = Status; + obj.Value = Value; + + // TODO: Replace these when moving away from keys + if (TryGetValue(AlbumKey, out var Album)) + obj[AlbumKey] = Album; + if (TryGetValue(AltRomnameKey, out var AltRomname)) + obj[AltRomnameKey] = AltRomname; + if (TryGetValue(AltTitleKey, out var AltTitle)) + obj[AltTitleKey] = AltTitle; + if (TryGetValue(ArtistKey, out var Artist)) + obj[ArtistKey] = Artist; + if (TryGetValue(ASRDetectedLangKey, out var ASRDetectedLang)) + obj[ASRDetectedLangKey] = ASRDetectedLang; + if (TryGetValue(ASRDetectedLangConfKey, out var ASRDetectedLangConf)) + obj[ASRDetectedLangConfKey] = ASRDetectedLangConf; + if (TryGetValue(ASRTranscribedLangKey, out var ASRTranscribedLang)) + obj[ASRTranscribedLangKey] = ASRTranscribedLang; + if (TryGetValue(BiosKey, out var Bios)) + obj[BiosKey] = Bios; + if (TryGetValue(BitrateKey, out var Bitrate)) + obj[BitrateKey] = Bitrate; + if (TryGetValue(BitTorrentMagnetHashKey, out var BitTorrentMagnetHash)) + obj[BitTorrentMagnetHashKey] = BitTorrentMagnetHash; + if (TryGetValue(ClothCoverDetectionModuleVersionKey, out var ClothCoverDetectionModuleVersion)) + obj[ClothCoverDetectionModuleVersionKey] = ClothCoverDetectionModuleVersion; + if (TryGetValue(CollectionCatalogNumberKey, out var CollectionCatalogNumber)) + obj[CollectionCatalogNumberKey] = CollectionCatalogNumber; + if (TryGetValue(CommentKey, out var Comment)) + obj[CommentKey] = Comment; + if (TryGetValue(CRCKey, out var CRC)) + obj[CRCKey] = CRC; + if (TryGetValue(CRC16Key, out var CRC16)) + obj[CRC16Key] = CRC16; + if (TryGetValue(CRC64Key, out var CRC64)) + obj[CRC64Key] = CRC64; + if (TryGetValue(CreatorKey, out var Creator)) + obj[CreatorKey] = Creator; + if (TryGetValue(DateKey, out var Date)) + obj[DateKey] = Date; + if (TryGetValue(ExtensionKey, out var Extension)) + obj[ExtensionKey] = Extension; + if (TryGetValue(FlagsKey, out var Flags)) + obj[FlagsKey] = Flags; + if (TryGetValue(FormatKey, out var Format)) + obj[FormatKey] = Format; + if (TryGetValue(HeaderKey, out var Header)) + obj[HeaderKey] = Header; + if (TryGetValue(HeightKey, out var Height)) + obj[HeightKey] = Height; + if (TryGetValue(hOCRCharToWordhOCRVersionKey, out var hOCRCharToWordhOCRVersion)) + obj[hOCRCharToWordhOCRVersionKey] = hOCRCharToWordhOCRVersion; + if (TryGetValue(hOCRCharToWordModuleVersionKey, out var hOCRCharToWordModuleVersion)) + obj[hOCRCharToWordModuleVersionKey] = hOCRCharToWordModuleVersion; + if (TryGetValue(hOCRFtsTexthOCRVersionKey, out var hOCRFtsTexthOCRVersion)) + obj[hOCRFtsTexthOCRVersionKey] = hOCRFtsTexthOCRVersion; + if (TryGetValue(hOCRFtsTextModuleVersionKey, out var hOCRFtsTextModuleVersion)) + obj[hOCRFtsTextModuleVersionKey] = hOCRFtsTextModuleVersion; + if (TryGetValue(hOCRPageIndexhOCRVersionKey, out var hOCRPageIndexhOCRVersion)) + obj[hOCRPageIndexhOCRVersionKey] = hOCRPageIndexhOCRVersion; + if (TryGetValue(hOCRPageIndexModuleVersionKey, out var hOCRPageIndexModuleVersion)) + obj[hOCRPageIndexModuleVersionKey] = hOCRPageIndexModuleVersion; + if (TryGetValue(LastModifiedTimeKey, out var LastModifiedTime)) + obj[LastModifiedTimeKey] = LastModifiedTime; + if (TryGetValue(LengthKey, out var Length)) + obj[LengthKey] = Length; + if (TryGetValue(MatrixNumberKey, out var MatrixNumber)) + obj[MatrixNumberKey] = MatrixNumber; + if (TryGetValue(MD2Key, out var MD2)) + obj[MD2Key] = MD2; + if (TryGetValue(MD4Key, out var MD4)) + obj[MD4Key] = MD4; + if (TryGetValue(MD5Key, out var MD5)) + obj[MD5Key] = MD5; + if (TryGetValue(MergeKey, out var Merge)) + obj[MergeKey] = Merge; + if (TryGetValue(TesseractOCRKey, out var TesseractOCR)) + obj[TesseractOCRKey] = TesseractOCR; + if (TryGetValue(TesseractOCRConvertedKey, out var TesseractOCRConverted)) + obj[TesseractOCRConvertedKey] = TesseractOCRConverted; + if (TryGetValue(TesseractOCRDetectedLangKey, out var TesseractOCRDetectedLang)) + obj[TesseractOCRDetectedLangKey] = TesseractOCRDetectedLang; + if (TryGetValue(TesseractOCRDetectedLangConfKey, out var TesseractOCRDetectedLangConf)) + obj[TesseractOCRDetectedLangConfKey] = TesseractOCRDetectedLangConf; + if (TryGetValue(TesseractOCRDetectedScriptKey, out var TesseractOCRDetectedScript)) + obj[TesseractOCRDetectedScriptKey] = TesseractOCRDetectedScript; + if (TryGetValue(TesseractOCRDetectedScriptConfKey, out var TesseractOCRDetectedScriptConf)) + obj[TesseractOCRDetectedScriptConfKey] = TesseractOCRDetectedScriptConf; + if (TryGetValue(TesseractOCRModuleVersionKey, out var TesseractOCRModuleVersion)) + obj[TesseractOCRModuleVersionKey] = TesseractOCRModuleVersion; + if (TryGetValue(TesseractOCRParametersKey, out var TesseractOCRParameters)) + obj[TesseractOCRParametersKey] = TesseractOCRParameters; + if (TryGetValue(OffsetKey, out var Offset)) + obj[OffsetKey] = Offset; + if (TryGetValue(OriginalKey, out var Original)) + obj[OriginalKey] = Original; + if (TryGetValue(PDFModuleVersionKey, out var PDFModuleVersion)) + obj[PDFModuleVersionKey] = PDFModuleVersion; + if (TryGetValue(PreviewImageKey, out var PreviewImage)) + obj[PreviewImageKey] = PreviewImage; + if (TryGetValue(PublisherKey, out var Publisher)) + obj[PublisherKey] = Publisher; + if (TryGetValue(RegionKey, out var Region)) + obj[RegionKey] = Region; + if (TryGetValue(RemarkKey, out var Remark)) + obj[RemarkKey] = Remark; + if (TryGetValue(RIPEMD128Key, out var RIPEMD128)) + obj[RIPEMD128Key] = RIPEMD128; + if (TryGetValue(RIPEMD160Key, out var RIPEMD160)) + obj[RIPEMD160Key] = RIPEMD160; + if (TryGetValue(RotationKey, out var Rotation)) + obj[RotationKey] = Rotation; + if (TryGetValue(SerialKey, out var Serial)) + obj[SerialKey] = Serial; + if (TryGetValue(SHA1Key, out var SHA1)) + obj[SHA1Key] = SHA1; + if (TryGetValue(SHA256Key, out var SHA256)) + obj[SHA256Key] = SHA256; + if (TryGetValue(SHA384Key, out var SHA384)) + obj[SHA384Key] = SHA384; + if (TryGetValue(SHA512Key, out var SHA512)) + obj[SHA512Key] = SHA512; + if (TryGetValue(SourceKey, out var Source)) + obj[SourceKey] = Source; + if (TryGetValue(SpamSumKey, out var SpamSum)) + obj[SpamSumKey] = SpamSum; + if (TryGetValue(StartKey, out var Start)) + obj[StartKey] = Start; + if (TryGetValue(SummationKey, out var Summation)) + obj[SummationKey] = Summation; + if (TryGetValue(TitleKey, out var Title)) + obj[TitleKey] = Title; + if (TryGetValue(TrackKey, out var Track)) + obj[TrackKey] = Track; + if (TryGetValue(OpenMSXType, out var OpenMSXTypeValue)) + obj[OpenMSXType] = OpenMSXTypeValue; + if (TryGetValue(WhisperASRModuleVersionKey, out var WhisperASRModuleVersion)) + obj[WhisperASRModuleVersionKey] = WhisperASRModuleVersion; + if (TryGetValue(WhisperModelHashKey, out var WhisperModelHash)) + obj[WhisperModelHashKey] = WhisperModelHash; + if (TryGetValue(WhisperModelNameKey, out var WhisperModelName)) + obj[WhisperModelNameKey] = WhisperModelName; + if (TryGetValue(WhisperVersionKey, out var WhisperVersion)) + obj[WhisperVersionKey] = WhisperVersion; + if (TryGetValue(WidthKey, out var Width)) + obj[WidthKey] = Width; + if (TryGetValue(WordConfidenceInterval0To10Key, out var WordConfidenceInterval0To10)) + obj[WordConfidenceInterval0To10Key] = WordConfidenceInterval0To10; + if (TryGetValue(WordConfidenceInterval11To20Key, out var WordConfidenceInterval11To20)) + obj[WordConfidenceInterval11To20Key] = WordConfidenceInterval11To20; + if (TryGetValue(WordConfidenceInterval21To30Key, out var WordConfidenceInterval21To30)) + obj[WordConfidenceInterval21To30Key] = WordConfidenceInterval21To30; + if (TryGetValue(WordConfidenceInterval31To40Key, out var WordConfidenceInterval31To40)) + obj[WordConfidenceInterval31To40Key] = WordConfidenceInterval31To40; + if (TryGetValue(WordConfidenceInterval41To50Key, out var WordConfidenceInterval41To50)) + obj[WordConfidenceInterval41To50Key] = WordConfidenceInterval41To50; + if (TryGetValue(WordConfidenceInterval51To60Key, out var WordConfidenceInterval51To60)) + obj[WordConfidenceInterval51To60Key] = WordConfidenceInterval51To60; + if (TryGetValue(WordConfidenceInterval61To70Key, out var WordConfidenceInterval61To70)) + obj[WordConfidenceInterval61To70Key] = WordConfidenceInterval61To70; + if (TryGetValue(WordConfidenceInterval71To80Key, out var WordConfidenceInterval71To80)) + obj[WordConfidenceInterval71To80Key] = WordConfidenceInterval71To80; + if (TryGetValue(WordConfidenceInterval81To90Key, out var WordConfidenceInterval81To90)) + obj[WordConfidenceInterval81To90Key] = WordConfidenceInterval81To90; + if (TryGetValue(WordConfidenceInterval91To100Key, out var WordConfidenceInterval91To100)) + obj[WordConfidenceInterval91To100Key] = WordConfidenceInterval91To100; + if (TryGetValue(xxHash364Key, out var xxHash364)) + obj[xxHash364Key] = xxHash364; + if (TryGetValue(xxHash3128Key, out var xxHash3128)) + obj[xxHash3128Key] = xxHash3128; + + return obj; + } } } diff --git a/SabreTools.Metadata.DatFiles.Test/DatFileTests.FromMetadata.cs b/SabreTools.Metadata.DatFiles.Test/DatFileTests.FromMetadata.cs index f71b1e8a..629050b8 100644 --- a/SabreTools.Metadata.DatFiles.Test/DatFileTests.FromMetadata.cs +++ b/SabreTools.Metadata.DatFiles.Test/DatFileTests.FromMetadata.cs @@ -142,9 +142,9 @@ namespace SabreTools.Metadata.DatFiles.Test // All other fields are tested separately Rom? partRom = Array.Find(datItems, item => item is Rom rom && rom.DataAreaSpecified && rom.PartSpecified) as Rom; Assert.NotNull(partRom); - DataArea? romDataArea = partRom.Read(Rom.DataAreaKey); + DataArea? romDataArea = partRom.DataArea; ValidateDataArea(romDataArea); - Part? romPart = partRom.Read(Rom.PartKey); + Part? romPart = partRom.Part; ValidatePart(romPart); Port? port = Array.Find(datItems, item => item is Port) as Port; @@ -539,7 +539,7 @@ namespace SabreTools.Metadata.DatFiles.Test { Endianness = Data.Models.Metadata.Endianness.Big, Name = "name", - [Data.Models.Metadata.DataArea.RomKey] = new Data.Models.Metadata.Rom[] { [] }, + Rom = [[]], Size = 12345, Width = Data.Models.Metadata.Width.Long, }; @@ -565,7 +565,7 @@ namespace SabreTools.Metadata.DatFiles.Test { return new Data.Models.Metadata.DiskArea { - [Data.Models.Metadata.DiskArea.DiskKey] = new Data.Models.Metadata.Disk[] { [] }, + Disk = [[]], Name = "name", }; } @@ -704,10 +704,10 @@ namespace SabreTools.Metadata.DatFiles.Test { return new Data.Models.Metadata.Part { - [Data.Models.Metadata.Part.DataAreaKey] = new Data.Models.Metadata.DataArea[] { CreateMetadataDataArea() }, - [Data.Models.Metadata.Part.DiskAreaKey] = new Data.Models.Metadata.DiskArea[] { CreateMetadataDiskArea() }, - [Data.Models.Metadata.Part.DipSwitchKey] = new Data.Models.Metadata.DipSwitch[] { [] }, - [Data.Models.Metadata.Part.FeatureKey] = new Data.Models.Metadata.Feature[] { CreateMetadataFeature() }, + DataArea = [CreateMetadataDataArea()], + DiskArea = [CreateMetadataDiskArea()], + DipSwitch = [[]], + Feature = [CreateMetadataFeature()], Interface = "interface", Name = "name", }; @@ -1432,7 +1432,7 @@ namespace SabreTools.Metadata.DatFiles.Test Assert.Equal(Data.Models.Metadata.FeatureType.Protection, partFeature.FeatureType); Assert.Equal("value", partFeature.Value); - Part? part = partFeature.Read(PartFeature.PartKey); + Part? part = partFeature.Part; ValidatePart(part); } diff --git a/SabreTools.Metadata.DatFiles.Test/DatFileTests.ToMetadata.cs b/SabreTools.Metadata.DatFiles.Test/DatFileTests.ToMetadata.cs index 22f60775..33a92aa2 100644 --- a/SabreTools.Metadata.DatFiles.Test/DatFileTests.ToMetadata.cs +++ b/SabreTools.Metadata.DatFiles.Test/DatFileTests.ToMetadata.cs @@ -261,7 +261,7 @@ namespace SabreTools.Metadata.DatFiles.Test { PartFeature item = new PartFeature(CreateMetadataFeature()); item.CopyMachineInformation(machine); - item.Write(PartFeature.PartKey, CreatePart(machine)); + item.Part = CreatePart(machine); return item; } @@ -298,8 +298,8 @@ namespace SabreTools.Metadata.DatFiles.Test { Rom item = new Rom(CreateMetadataRom()); item.CopyMachineInformation(machine); - item.Write(Rom.DataAreaKey, CreateDataArea(machine)); - item.Write(Rom.PartKey, CreatePart(machine)); + item.DataArea = CreateDataArea(machine); + item.Part = CreatePart(machine); return item; } @@ -761,7 +761,7 @@ namespace SabreTools.Metadata.DatFiles.Test Assert.Equal(12345, dataArea.Size); Assert.Equal(Data.Models.Metadata.Width.Long, dataArea.Width); - Data.Models.Metadata.Rom[]? roms = dataArea.ReadArray(Data.Models.Metadata.DataArea.RomKey); + Data.Models.Metadata.Rom[]? roms = dataArea.Rom; Assert.NotNull(roms); Data.Models.Metadata.Rom? rom = Assert.Single(roms); ValidateMetadataRom(rom); @@ -853,7 +853,7 @@ namespace SabreTools.Metadata.DatFiles.Test Assert.NotNull(diskArea); Assert.Equal("name", diskArea.Name); - Data.Models.Metadata.Disk[]? disks = diskArea.ReadArray(Data.Models.Metadata.DiskArea.DiskKey); + Data.Models.Metadata.Disk[]? disks = diskArea.Disk; Assert.NotNull(disks); Data.Models.Metadata.Disk? disk = Assert.Single(disks); ValidateMetadataDisk(disk); @@ -959,22 +959,22 @@ namespace SabreTools.Metadata.DatFiles.Test Assert.Equal("interface", part.Interface); Assert.Equal("name", part.Name); - Data.Models.Metadata.DataArea[]? dataAreas = part.ReadArray(Data.Models.Metadata.Part.DataAreaKey); + Data.Models.Metadata.DataArea[]? dataAreas = part.DataArea; Assert.NotNull(dataAreas); Data.Models.Metadata.DataArea? dataArea = Assert.Single(dataAreas); ValidateMetadataDataArea(dataArea); - Data.Models.Metadata.DiskArea[]? diskAreas = part.ReadArray(Data.Models.Metadata.Part.DiskAreaKey); + Data.Models.Metadata.DiskArea[]? diskAreas = part.DiskArea; Assert.NotNull(diskAreas); Data.Models.Metadata.DiskArea? diskArea = Assert.Single(diskAreas); ValidateMetadataDiskArea(diskArea); - Data.Models.Metadata.DipSwitch[]? dipSwitches = part.ReadArray(Data.Models.Metadata.Part.DipSwitchKey); + Data.Models.Metadata.DipSwitch[]? dipSwitches = part.DipSwitch; Assert.NotNull(dipSwitches); Data.Models.Metadata.DipSwitch? dipSwitch = Assert.Single(dipSwitches); ValidateMetadataDipSwitch(dipSwitch); - Data.Models.Metadata.Feature[]? features = part.ReadArray(Data.Models.Metadata.Part.FeatureKey); + Data.Models.Metadata.Feature[]? features = part.Feature; Assert.NotNull(features); Data.Models.Metadata.Feature? feature = Assert.Single(features); ValidateMetadataFeature(feature); diff --git a/SabreTools.Metadata.DatFiles/DatFile.FromMetadata.cs b/SabreTools.Metadata.DatFiles/DatFile.FromMetadata.cs index 4b04c48d..02320b1c 100644 --- a/SabreTools.Metadata.DatFiles/DatFile.FromMetadata.cs +++ b/SabreTools.Metadata.DatFiles/DatFile.FromMetadata.cs @@ -589,13 +589,13 @@ namespace SabreTools.Metadata.DatFiles var partItem = new Part(item, machine, source); // Handle subitems - var dataAreas = item.ReadArray(Data.Models.Metadata.Part.DataAreaKey); + var dataAreas = item.DataArea; if (dataAreas is not null) { foreach (var dataArea in dataAreas) { var dataAreaItem = new DataArea(dataArea, machine, source); - var roms = dataArea.ReadArray(Data.Models.Metadata.DataArea.RomKey); + var roms = dataArea.Rom; if (roms is null) continue; @@ -623,8 +623,8 @@ namespace SabreTools.Metadata.DatFiles continue; } - romItem.Write(Rom.DataAreaKey, dataAreaItem); - romItem.Write(Rom.PartKey, partItem); + romItem.DataArea = dataAreaItem; + romItem.Part = partItem; addRoms.Add(romItem); } @@ -638,13 +638,13 @@ namespace SabreTools.Metadata.DatFiles } } - var diskAreas = item.ReadArray(Data.Models.Metadata.Part.DiskAreaKey); + var diskAreas = item.DiskArea; if (diskAreas is not null) { foreach (var diskArea in diskAreas) { var diskAreaitem = new DiskArea(diskArea, machine, source); - var disks = diskArea.ReadArray(Data.Models.Metadata.DiskArea.DiskKey); + var disks = diskArea.Disk; if (disks is null) continue; @@ -666,7 +666,7 @@ namespace SabreTools.Metadata.DatFiles } } - var dipSwitches = item.ReadArray(Data.Models.Metadata.Part.DipSwitchKey); + var dipSwitches = item.DipSwitch; if (dipSwitches is not null) { foreach (var dipSwitch in dipSwitches) @@ -682,7 +682,7 @@ namespace SabreTools.Metadata.DatFiles } } - var partFeatures = item.ReadArray(Data.Models.Metadata.Part.FeatureKey); + var partFeatures = item.Feature; if (partFeatures is not null) { foreach (var partFeature in partFeatures) @@ -691,9 +691,11 @@ namespace SabreTools.Metadata.DatFiles if (filterRunner is not null && !filterRunner.Run(partFeature)) continue; - var partFeatureItem = new PartFeature(partFeature); - partFeatureItem.Write(PartFeature.PartKey, partItem); - partFeatureItem.Source = source; + var partFeatureItem = new PartFeature(partFeature) + { + Part = partItem, + Source = source, + }; partFeatureItem.CopyMachineInformation(machine); AddItem(partFeatureItem, statsOnly); diff --git a/SabreTools.Metadata.DatFiles/DatFile.ToMetadata.cs b/SabreTools.Metadata.DatFiles/DatFile.ToMetadata.cs index 2b9ee580..e60bb099 100644 --- a/SabreTools.Metadata.DatFiles/DatFile.ToMetadata.cs +++ b/SabreTools.Metadata.DatFiles/DatFile.ToMetadata.cs @@ -164,20 +164,11 @@ namespace SabreTools.Metadata.DatFiles AppendToMachineKey(machine, Data.Models.Metadata.Machine.DiskKey, diskItem); // Add Part and DiskArea mappings - bool diskContainsPart = disk.Part is not null; - bool diskContainsDiskArea = disk.DiskArea is not null; - if (diskContainsPart && diskContainsDiskArea) + if (disk.Part is not null && disk.DiskArea is not null) { - var partItem = disk.Part; - if (partItem is not null) - { - var partItemInternal = partItem.GetInternalClone(); - partMappings[partItemInternal] = diskItem; - - var diskAreaItem = disk.DiskArea; - if (diskAreaItem is not null) - diskAreaMappings[partItemInternal] = (diskAreaItem.GetInternalClone(), diskItem); - } + var partItemInternal = disk.Part.GetInternalClone(); + partMappings[partItemInternal] = diskItem; + diskAreaMappings[partItemInternal] = (disk.DiskArea.GetInternalClone(), diskItem); } break; @@ -217,13 +208,8 @@ namespace SabreTools.Metadata.DatFiles AppendToMachineKey(machine, Data.Models.Metadata.Machine.FeatureKey, partFeatureItem); // Add Part mapping - bool partFeatureContainsPart = partFeatureItem.ContainsKey(DatItems.Formats.PartFeature.PartKey); - if (partFeatureContainsPart) - { - var partItem = partFeatureItem.Read(DatItems.Formats.PartFeature.PartKey); - if (partItem is not null) - partMappings[partItem.GetInternalClone()] = partFeatureItem; - } + if (partFeature.Part is not null) + partMappings[partFeature.Part.GetInternalClone()] = partFeatureItem; break; case DatItems.Formats.Port port: @@ -247,20 +233,11 @@ namespace SabreTools.Metadata.DatFiles AppendToMachineKey(machine, Data.Models.Metadata.Machine.RomKey, romItem); // Add Part and DataArea mappings - bool romContainsPart = romItem.ContainsKey(DatItems.Formats.Rom.PartKey); - bool romContainsDataArea = romItem.ContainsKey(DatItems.Formats.Rom.DataAreaKey); - if (romContainsPart && romContainsDataArea) + if (rom.Part is not null && rom.DataArea is not null) { - var partItem = romItem.Read(DatItems.Formats.Rom.PartKey); - if (partItem is not null) - { - var partItemInternal = partItem.GetInternalClone(); - partMappings[partItemInternal] = romItem; - - var dataAreaItem = romItem.Read(DatItems.Formats.Rom.DataAreaKey); - if (dataAreaItem is not null) - dataAreaMappings[partItemInternal] = (dataAreaItem.GetInternalClone(), romItem); - } + var partItemInternal = rom.Part.GetInternalClone(); + partMappings[partItemInternal] = romItem; + dataAreaMappings[partItemInternal] = (rom.DataArea.GetInternalClone(), romItem); } break; @@ -339,7 +316,7 @@ namespace SabreTools.Metadata.DatFiles if (dataAreaName is not null) { // Get existing data areas as a list - var dataAreasArr = partItems[partName].Read(Data.Models.Metadata.Part.DataAreaKey) ?? []; + var dataAreasArr = partItems[partName].DataArea ?? []; List dataAreas = [.. dataAreasArr]; // Find the existing disk area to append to, otherwise create a new disk area @@ -362,14 +339,14 @@ namespace SabreTools.Metadata.DatFiles ClearEmptyKeys(aggregateDataArea); // Get existing roms as a list - var romsArr = aggregateDataArea.Read(Data.Models.Metadata.DataArea.RomKey) ?? []; + var romsArr = aggregateDataArea.Rom ?? []; List roms = [.. romsArr]; // Add the rom to the data area roms.Add(romItem); // Assign back the roms - aggregateDataArea[Data.Models.Metadata.DataArea.RomKey] = roms.ToArray(); + aggregateDataArea.Rom = roms.ToArray(); // Assign back the data area if (dataAreaIndex > -1) @@ -378,7 +355,7 @@ namespace SabreTools.Metadata.DatFiles dataAreas.Add(aggregateDataArea); // Assign back the data areas array - partItems[partName][Data.Models.Metadata.Part.DataAreaKey] = dataAreas.ToArray(); + partItems[partName].DataArea = dataAreas.ToArray(); } } @@ -396,7 +373,7 @@ namespace SabreTools.Metadata.DatFiles if (diskAreaName is not null) { // Get existing disk areas as a list - var diskAreasArr = partItems[partName].Read(Data.Models.Metadata.Part.DiskAreaKey) ?? []; + var diskAreasArr = partItems[partName].DiskArea ?? []; List diskAreas = [.. diskAreasArr]; // Find the existing disk area to append to, otherwise create a new disk area @@ -416,14 +393,14 @@ namespace SabreTools.Metadata.DatFiles ClearEmptyKeys(aggregateDiskArea); // Get existing disks as a list - var disksArr = aggregateDiskArea.Read(Data.Models.Metadata.DiskArea.DiskKey) ?? []; + var disksArr = aggregateDiskArea.Disk ?? []; List disks = [.. disksArr]; // Add the disk to the data area disks.Add(diskItem); // Assign back the disks - aggregateDiskArea[Data.Models.Metadata.DiskArea.DiskKey] = disks.ToArray(); + aggregateDiskArea.Disk = disks.ToArray(); // Assign back the disk area if (diskAreaIndex > -1) @@ -432,7 +409,7 @@ namespace SabreTools.Metadata.DatFiles diskAreas.Add(aggregateDiskArea); // Assign back the disk areas array - partItems[partName][Data.Models.Metadata.Part.DiskAreaKey] = diskAreas.ToArray(); + partItems[partName].DiskArea = diskAreas.ToArray(); } } @@ -440,7 +417,7 @@ namespace SabreTools.Metadata.DatFiles if (datItem is Data.Models.Metadata.DipSwitch dipSwitchItem) { // Get existing dipswitches as a list - var dipSwitchesArr = partItems[partName].Read(Data.Models.Metadata.Part.DipSwitchKey) ?? []; + var dipSwitchesArr = partItems[partName].DipSwitch ?? []; List dipSwitches = [.. dipSwitchesArr]; // Clear any empty fields @@ -450,14 +427,14 @@ namespace SabreTools.Metadata.DatFiles dipSwitches.Add(dipSwitchItem); // Assign back the dipswitches - partItems[partName][Data.Models.Metadata.Part.DipSwitchKey] = dipSwitches.ToArray(); + partItems[partName].DipSwitch = dipSwitches.ToArray(); } // If the item is a Feature else if (datItem is Data.Models.Metadata.Feature featureItem) { // Get existing features as a list - var featuresArr = partItems[partName].Read(Data.Models.Metadata.Part.FeatureKey) ?? []; + var featuresArr = partItems[partName].Feature ?? []; List features = [.. featuresArr]; // Clear any empty fields @@ -467,7 +444,7 @@ namespace SabreTools.Metadata.DatFiles features.Add(featureItem); // Assign back the features - partItems[partName][Data.Models.Metadata.Part.FeatureKey] = features.ToArray(); + partItems[partName].Feature = features.ToArray(); } } @@ -585,20 +562,11 @@ namespace SabreTools.Metadata.DatFiles AppendToMachineKey(machine, Data.Models.Metadata.Machine.DiskKey, diskItem); // Add Part and DiskArea mappings - bool diskContainsPart = disk.Part is not null; - bool diskContainsDiskArea = disk.DiskArea is not null; - if (diskContainsPart && diskContainsDiskArea) + if (disk.Part is not null && disk.DiskArea is not null) { - var partItem = disk.Part; - if (partItem is not null) - { - var partItemInternal = partItem.GetInternalClone(); - partMappings[partItemInternal] = diskItem; - - var diskAreaItem = disk.DiskArea; - if (diskAreaItem is not null) - diskAreaMappings[partItemInternal] = (diskAreaItem.GetInternalClone(), diskItem); - } + var partItemInternal = disk.Part.GetInternalClone(); + partMappings[partItemInternal] = diskItem; + diskAreaMappings[partItemInternal] = (disk.DiskArea.GetInternalClone(), diskItem); } break; @@ -638,13 +606,8 @@ namespace SabreTools.Metadata.DatFiles AppendToMachineKey(machine, Data.Models.Metadata.Machine.FeatureKey, partFeatureItem); // Add Part mapping - bool partFeatureContainsPart = partFeatureItem.ContainsKey(DatItems.Formats.PartFeature.PartKey); - if (partFeatureContainsPart) - { - var partItem = partFeatureItem.Read(DatItems.Formats.PartFeature.PartKey); - if (partItem is not null) - partMappings[partItem.GetInternalClone()] = partFeatureItem; - } + if (partFeature.Part is not null) + partMappings[partFeature.Part.GetInternalClone()] = partFeatureItem; break; case DatItems.Formats.Port port: @@ -668,20 +631,11 @@ namespace SabreTools.Metadata.DatFiles AppendToMachineKey(machine, Data.Models.Metadata.Machine.RomKey, romItem); // Add Part and DataArea mappings - bool romContainsPart = romItem.ContainsKey(DatItems.Formats.Rom.PartKey); - bool romContainsDataArea = romItem.ContainsKey(DatItems.Formats.Rom.DataAreaKey); - if (romContainsPart && romContainsDataArea) + if (rom.Part is not null && rom.DataArea is not null) { - var partItem = romItem.Read(DatItems.Formats.Rom.PartKey); - if (partItem is not null) - { - var partItemInternal = partItem.GetInternalClone(); - partMappings[partItemInternal] = romItem; - - var dataAreaItem = romItem.Read(DatItems.Formats.Rom.DataAreaKey); - if (dataAreaItem is not null) - dataAreaMappings[partItemInternal] = (dataAreaItem.GetInternalClone(), romItem); - } + var partItemInternal = rom.Part.GetInternalClone(); + partMappings[partItemInternal] = romItem; + dataAreaMappings[partItemInternal] = (rom.DataArea.GetInternalClone(), romItem); } break; @@ -760,7 +714,7 @@ namespace SabreTools.Metadata.DatFiles if (dataAreaName is not null) { // Get existing data areas as a list - var dataAreasArr = partItems[partName].Read(Data.Models.Metadata.Part.DataAreaKey) ?? []; + var dataAreasArr = partItems[partName].DataArea ?? []; List dataAreas = [.. dataAreasArr]; // Find the existing disk area to append to, otherwise create a new disk area @@ -783,14 +737,14 @@ namespace SabreTools.Metadata.DatFiles ClearEmptyKeys(aggregateDataArea); // Get existing roms as a list - var romsArr = aggregateDataArea.Read(Data.Models.Metadata.DataArea.RomKey) ?? []; + var romsArr = aggregateDataArea.Rom ?? []; List roms = [.. romsArr]; // Add the rom to the data area roms.Add(romItem); // Assign back the roms - aggregateDataArea[Data.Models.Metadata.DataArea.RomKey] = roms.ToArray(); + aggregateDataArea.Rom = roms.ToArray(); // Assign back the data area if (dataAreaIndex > -1) @@ -799,7 +753,7 @@ namespace SabreTools.Metadata.DatFiles dataAreas.Add(aggregateDataArea); // Assign back the data areas array - partItems[partName][Data.Models.Metadata.Part.DataAreaKey] = dataAreas.ToArray(); + partItems[partName].DataArea = dataAreas.ToArray(); } } @@ -817,7 +771,7 @@ namespace SabreTools.Metadata.DatFiles if (diskAreaName is not null) { // Get existing disk areas as a list - var diskAreasArr = partItems[partName].Read(Data.Models.Metadata.Part.DiskAreaKey) ?? []; + var diskAreasArr = partItems[partName].DiskArea ?? []; List diskAreas = [.. diskAreasArr]; // Find the existing disk area to append to, otherwise create a new disk area @@ -837,14 +791,14 @@ namespace SabreTools.Metadata.DatFiles ClearEmptyKeys(aggregateDiskArea); // Get existing disks as a list - var disksArr = aggregateDiskArea.Read(Data.Models.Metadata.DiskArea.DiskKey) ?? []; + var disksArr = aggregateDiskArea.Disk ?? []; List disks = [.. disksArr]; // Add the disk to the data area disks.Add(diskItem); // Assign back the disks - aggregateDiskArea[Data.Models.Metadata.DiskArea.DiskKey] = disks.ToArray(); + aggregateDiskArea.Disk = disks.ToArray(); // Assign back the disk area if (diskAreaIndex > -1) @@ -853,7 +807,7 @@ namespace SabreTools.Metadata.DatFiles diskAreas.Add(aggregateDiskArea); // Assign back the disk areas array - partItems[partName][Data.Models.Metadata.Part.DiskAreaKey] = diskAreas.ToArray(); + partItems[partName].DiskArea = diskAreas.ToArray(); } } @@ -861,7 +815,7 @@ namespace SabreTools.Metadata.DatFiles if (datItem is Data.Models.Metadata.DipSwitch dipSwitchItem) { // Get existing dipswitches as a list - var dipSwitchesArr = partItems[partName].Read(Data.Models.Metadata.Part.DipSwitchKey) ?? []; + var dipSwitchesArr = partItems[partName].DipSwitch ?? []; List dipSwitches = [.. dipSwitchesArr]; // Clear any empty fields @@ -871,14 +825,14 @@ namespace SabreTools.Metadata.DatFiles dipSwitches.Add(dipSwitchItem); // Assign back the dipswitches - partItems[partName][Data.Models.Metadata.Part.DipSwitchKey] = dipSwitches.ToArray(); + partItems[partName].DipSwitch = dipSwitches.ToArray(); } // If the item is a Feature else if (datItem is Data.Models.Metadata.Feature featureItem) { // Get existing features as a list - var featuresArr = partItems[partName].Read(Data.Models.Metadata.Part.FeatureKey) ?? []; + var featuresArr = partItems[partName].Feature ?? []; List features = [.. featuresArr]; // Clear any empty fields @@ -888,7 +842,7 @@ namespace SabreTools.Metadata.DatFiles features.Add(featureItem); // Assign back the features - partItems[partName][Data.Models.Metadata.Part.FeatureKey] = features.ToArray(); + partItems[partName].Feature = features.ToArray(); } } diff --git a/SabreTools.Metadata.DatFiles/Formats/SoftwareList.cs b/SabreTools.Metadata.DatFiles/Formats/SoftwareList.cs index 871dce80..058422c7 100644 --- a/SabreTools.Metadata.DatFiles/Formats/SoftwareList.cs +++ b/SabreTools.Metadata.DatFiles/Formats/SoftwareList.cs @@ -178,9 +178,9 @@ namespace SabreTools.Metadata.DatFiles.Formats } else { - if (string.IsNullOrEmpty(rom.Read(Rom.PartKey)!.Name)) + if (string.IsNullOrEmpty(rom.Part!.Name)) missingFields.Add(nameof(Data.Models.Metadata.Part.Name)); - if (string.IsNullOrEmpty(rom.Read(Rom.PartKey)!.Interface)) + if (string.IsNullOrEmpty(rom.Part!.Interface)) missingFields.Add(nameof(Data.Models.Metadata.Part.Interface)); } @@ -191,9 +191,9 @@ namespace SabreTools.Metadata.DatFiles.Formats } else { - if (string.IsNullOrEmpty(rom.Read(Rom.DataAreaKey)!.Name)) + if (string.IsNullOrEmpty(rom.DataArea!.Name)) missingFields.Add(nameof(Data.Models.Metadata.DataArea.Name)); - if (rom.Read(Rom.DataAreaKey)!.Size is null) + if (rom.DataArea!.Size is null) missingFields.Add(nameof(Data.Models.Metadata.DataArea.Size)); } diff --git a/SabreTools.Metadata.DatItems.Test/Formats/DiskTests.cs b/SabreTools.Metadata.DatItems.Test/Formats/DiskTests.cs index ecaddbed..c12dd141 100644 --- a/SabreTools.Metadata.DatItems.Test/Formats/DiskTests.cs +++ b/SabreTools.Metadata.DatItems.Test/Formats/DiskTests.cs @@ -46,7 +46,7 @@ namespace SabreTools.Metadata.DatItems.Formats.Test Assert.Equal(HashType.SHA1.ZeroString, actual.ReadString(Data.Models.Metadata.Rom.SHA1Key)); Assert.Equal(DupeType.All | DupeType.External, actual.DupeType); - DataArea? actualDataArea = actual.Read(Rom.DataAreaKey); + DataArea? actualDataArea = actual.DataArea; Assert.NotNull(actualDataArea); Assert.Equal("name", actualDataArea.Name); @@ -56,7 +56,7 @@ namespace SabreTools.Metadata.DatItems.Formats.Test Assert.False(actual.RemoveFlag); - Part? actualPart = actual.Read(Rom.PartKey); + Part? actualPart = actual.Part; Assert.NotNull(actualPart); Assert.Equal("name", actualPart.Name); diff --git a/SabreTools.Metadata.DatItems/Formats/DataArea.cs b/SabreTools.Metadata.DatItems/Formats/DataArea.cs index 50af1f05..e37ced8e 100644 --- a/SabreTools.Metadata.DatItems/Formats/DataArea.cs +++ b/SabreTools.Metadata.DatItems/Formats/DataArea.cs @@ -1,4 +1,5 @@ -using System.Xml.Serialization; +using System; +using System.Xml.Serialization; using Newtonsoft.Json; using SabreTools.Data.Extensions; @@ -29,6 +30,11 @@ namespace SabreTools.Metadata.DatItems.Formats set => (_internal as Data.Models.Metadata.DataArea)?.Name = value; } + public Rom[]? Rom { get; set; } + + [JsonIgnore] + public bool RomSpecified => Rom is not null && Rom.Length > 0; + public long? Size { get => (_internal as Data.Models.Metadata.DataArea)?.Size; @@ -47,7 +53,12 @@ namespace SabreTools.Metadata.DatItems.Formats public DataArea() : base() { } - public DataArea(Data.Models.Metadata.DataArea item) : base(item) { } + public DataArea(Data.Models.Metadata.DataArea item) : base(item) + { + // Handle subitems + if (item.Rom is not null) + Rom = Array.ConvertAll(item.Rom, rom => new Rom(rom)); + } public DataArea(Data.Models.Metadata.DataArea item, Machine machine, Source source) : this(item) { @@ -72,6 +83,16 @@ namespace SabreTools.Metadata.DatItems.Formats /// public override object Clone() => new DataArea(_internal.DeepClone() as Data.Models.Metadata.DataArea ?? []); + public override Data.Models.Metadata.DataArea GetInternalClone() + { + var partItem = base.GetInternalClone(); + + if (Rom is not null) + partItem.Rom = Array.ConvertAll(Rom, rom => rom.GetInternalClone()); + + return partItem; + } + #endregion } } diff --git a/SabreTools.Metadata.DatItems/Formats/Disk.cs b/SabreTools.Metadata.DatItems/Formats/Disk.cs index a85914a4..3816d277 100644 --- a/SabreTools.Metadata.DatItems/Formats/Disk.cs +++ b/SabreTools.Metadata.DatItems/Formats/Disk.cs @@ -153,12 +153,12 @@ namespace SabreTools.Metadata.DatItems.Formats if (DiskArea is not null) { var dataArea = new DataArea { Name = DiskArea.Name }; - rom.Write(Rom.DataAreaKey, dataArea); + rom.DataArea = dataArea; } rom.DupeType = DupeType; rom.Machine = Machine?.Clone() as Machine; - rom.Write(Rom.PartKey, Part?.Clone() as Part); + rom.Part = Part?.Clone() as Part; rom.RemoveFlag = RemoveFlag; rom.Source = Source?.Clone() as Source; diff --git a/SabreTools.Metadata.DatItems/Formats/DiskArea.cs b/SabreTools.Metadata.DatItems/Formats/DiskArea.cs index d02ccb47..bfeffe2d 100644 --- a/SabreTools.Metadata.DatItems/Formats/DiskArea.cs +++ b/SabreTools.Metadata.DatItems/Formats/DiskArea.cs @@ -1,4 +1,5 @@ -using System.Xml.Serialization; +using System; +using System.Xml.Serialization; using Newtonsoft.Json; using SabreTools.Data.Extensions; @@ -13,6 +14,11 @@ namespace SabreTools.Metadata.DatItems.Formats { #region Fields + public Disk[]? Disk { get; set; } + + [JsonIgnore] + public bool DiskSpecified => Disk is not null && Disk.Length > 0; + /// /> public override Data.Models.Metadata.ItemType ItemType => Data.Models.Metadata.ItemType.DiskArea; @@ -29,7 +35,12 @@ namespace SabreTools.Metadata.DatItems.Formats public DiskArea() : base() { } - public DiskArea(Data.Models.Metadata.DiskArea item) : base(item) { } + public DiskArea(Data.Models.Metadata.DiskArea item) : base(item) + { + // Handle subitems + if (item.Disk is not null) + Disk = Array.ConvertAll(item.Disk, rom => new Disk(rom)); + } public DiskArea(Data.Models.Metadata.DiskArea item, Machine machine, Source source) : this(item) { @@ -54,6 +65,16 @@ namespace SabreTools.Metadata.DatItems.Formats /// public override object Clone() => new DiskArea(_internal.DeepClone() as Data.Models.Metadata.DiskArea ?? []); + public override Data.Models.Metadata.DiskArea GetInternalClone() + { + var partItem = base.GetInternalClone(); + + if (Disk is not null) + partItem.Disk = Array.ConvertAll(Disk, rom => rom.GetInternalClone()); + + return partItem; + } + #endregion } } diff --git a/SabreTools.Metadata.DatItems/Formats/Part.cs b/SabreTools.Metadata.DatItems/Formats/Part.cs index dd6f3dbc..f2253d6a 100644 --- a/SabreTools.Metadata.DatItems/Formats/Part.cs +++ b/SabreTools.Metadata.DatItems/Formats/Part.cs @@ -14,15 +14,25 @@ namespace SabreTools.Metadata.DatItems.Formats { #region Fields + public DataArea[]? DataArea { get; set; } + [JsonIgnore] - public bool FeaturesSpecified - { - get - { - var features = Read(Data.Models.Metadata.Part.FeatureKey); - return features is not null && features.Length > 0; - } - } + public bool DataAreaSpecified => DataArea is not null && DataArea.Length > 0; + + public DiskArea[]? DiskArea { get; set; } + + [JsonIgnore] + public bool DiskAreaSpecified => DiskArea is not null && DiskArea.Length > 0; + + public DipSwitch[]? DipSwitch { get; set; } + + [JsonIgnore] + public bool DipSwitchSpecified => DipSwitch is not null && DipSwitch.Length > 0; + + public PartFeature[]? Feature { get; set; } + + [JsonIgnore] + public bool FeatureSpecified => Feature is not null && Feature.Length > 0; public string? Interface { @@ -46,7 +56,21 @@ namespace SabreTools.Metadata.DatItems.Formats public Part() : base() { } - public Part(Data.Models.Metadata.Part item) : base(item) { } + public Part(Data.Models.Metadata.Part item) : base(item) + { + // Handle subitems + if (item.DataArea is not null) + DataArea = Array.ConvertAll(item.DataArea, dataArea => new DataArea(dataArea)); + + if (item.DiskArea is not null) + DiskArea = Array.ConvertAll(item.DiskArea, diskArea => new DiskArea(diskArea)); + + if (item.DipSwitch is not null) + DipSwitch = Array.ConvertAll(item.DipSwitch, dipSwitch => new DipSwitch(dipSwitch)); + + if (item.Feature is not null) + Feature = Array.ConvertAll(item.Feature, feature => new PartFeature(feature)); + } public Part(Data.Models.Metadata.Part item, Machine machine, Source source) : this(item) { @@ -76,33 +100,17 @@ namespace SabreTools.Metadata.DatItems.Formats { var partItem = base.GetInternalClone(); - var dataAreas = Read(Data.Models.Metadata.Part.DataAreaKey); - if (dataAreas is not null) - { - Data.Models.Metadata.DataArea[] dataAreaItems = Array.ConvertAll(dataAreas, dataArea => dataArea.GetInternalClone()); - partItem[Data.Models.Metadata.Part.DataAreaKey] = dataAreaItems; - } + if (DataArea is not null) + partItem.DataArea = Array.ConvertAll(DataArea, dataArea => dataArea.GetInternalClone()); - var diskAreas = Read(Data.Models.Metadata.Part.DiskAreaKey); - if (diskAreas is not null) - { - Data.Models.Metadata.DiskArea[] diskAreaItems = Array.ConvertAll(diskAreas, diskArea => diskArea.GetInternalClone()); - partItem[Data.Models.Metadata.Part.DiskAreaKey] = diskAreaItems; - } + if (DiskArea is not null) + partItem.DiskArea = Array.ConvertAll(DiskArea, diskArea => diskArea.GetInternalClone()); - var dipSwitches = Read(Data.Models.Metadata.Part.DipSwitchKey); - if (dipSwitches is not null) - { - Data.Models.Metadata.DipSwitch[] dipSwitchItems = Array.ConvertAll(dipSwitches, dipSwitch => dipSwitch.GetInternalClone()); - partItem[Data.Models.Metadata.Part.DipSwitchKey] = dipSwitchItems; - } + if (DipSwitch is not null) + partItem.DipSwitch = Array.ConvertAll(DipSwitch, dipSwitch => dipSwitch.GetInternalClone()); - var features = Read(Data.Models.Metadata.Part.FeatureKey); - if (features is not null) - { - Data.Models.Metadata.Feature[] featureItems = Array.ConvertAll(features, feature => feature.GetInternalClone()); - partItem[Data.Models.Metadata.Part.FeatureKey] = featureItems; - } + if (Feature is not null) + partItem.Feature = Array.ConvertAll(Feature, feature => feature.GetInternalClone()); return partItem; } diff --git a/SabreTools.Metadata.DatItems/Formats/PartFeature.cs b/SabreTools.Metadata.DatItems/Formats/PartFeature.cs index ca8a6f6d..10972be5 100644 --- a/SabreTools.Metadata.DatItems/Formats/PartFeature.cs +++ b/SabreTools.Metadata.DatItems/Formats/PartFeature.cs @@ -10,15 +10,6 @@ namespace SabreTools.Metadata.DatItems.Formats [JsonObject("part_feature"), XmlRoot("part_feature")] public sealed class PartFeature : DatItem { - #region Constants - - /// - /// Non-standard key for inverted logic - /// - public const string PartKey = "PART"; - - #endregion - #region Fields public Data.Models.Metadata.FeatureType? FeatureType @@ -43,6 +34,11 @@ namespace SabreTools.Metadata.DatItems.Formats set => (_internal as Data.Models.Metadata.Feature)?.Overall = value; } + public Part? Part { get; set; } + + [JsonIgnore] + public bool PartSpecified => Part is not null; + public Data.Models.Metadata.FeatureStatus? Status { get => (_internal as Data.Models.Metadata.Feature)?.Status; diff --git a/SabreTools.Metadata.DatItems/Formats/Rom.cs b/SabreTools.Metadata.DatItems/Formats/Rom.cs index abe3d841..beb4ed44 100644 --- a/SabreTools.Metadata.DatItems/Formats/Rom.cs +++ b/SabreTools.Metadata.DatItems/Formats/Rom.cs @@ -12,33 +12,20 @@ namespace SabreTools.Metadata.DatItems.Formats [JsonObject("rom"), XmlRoot("rom")] public sealed class Rom : DatItem { - #region Constants - - /// - /// Non-standard key for inverted logic - /// - public const string DataAreaKey = "DATAAREA"; - - /// - /// Non-standard key for inverted logic - /// - public const string PartKey = "PART"; - - #endregion - #region Fields + public DataArea? DataArea { get; set; } + [JsonIgnore] public bool DataAreaSpecified { get { - var dataArea = Read(DataAreaKey); - return dataArea is not null - && (!string.IsNullOrEmpty(dataArea.Name) - || dataArea.Size is not null - || dataArea.Width is not null - || dataArea.Endianness is not null); + return DataArea is not null + && (!string.IsNullOrEmpty(DataArea.Name) + || DataArea.Size is not null + || DataArea.Width is not null + || DataArea.Endianness is not null); } } @@ -109,15 +96,16 @@ namespace SabreTools.Metadata.DatItems.Formats } } + public Part? Part { get; set; } + [JsonIgnore] public bool PartSpecified { get { - var part = Read(PartKey); - return part is not null - && (!string.IsNullOrEmpty(part.Name) - || !string.IsNullOrEmpty(part.Interface)); + return Part is not null + && (!string.IsNullOrEmpty(Part.Name) + || !string.IsNullOrEmpty(Part.Interface)); } } diff --git a/SabreTools.Metadata/DictionaryBaseExtensions.cs b/SabreTools.Metadata/DictionaryBaseExtensions.cs index 865469c7..47900bdd 100644 --- a/SabreTools.Metadata/DictionaryBaseExtensions.cs +++ b/SabreTools.Metadata/DictionaryBaseExtensions.cs @@ -114,11 +114,7 @@ namespace SabreTools.Metadata } else if (self is DataArea selfDataArea && other is DataArea otherDataArea) { - if (selfDataArea.Endianness != otherDataArea.Endianness) - return false; - if (selfDataArea.Size != otherDataArea.Size) - return false; - if (selfDataArea.Width != otherDataArea.Width) + if (!selfDataArea.Equals(otherDataArea)) return false; } else if (self is Device selfDevice && other is Device otherDevice) @@ -145,6 +141,11 @@ namespace SabreTools.Metadata { // Intentionally skipped here } + else if (self is DiskArea selfDiskArea && other is DiskArea otherDiskArea) + { + if (!selfDiskArea.Equals(otherDiskArea)) + return false; + } else if (self is Display selfDisplay && other is Display otherDisplay) { if (!selfDisplay.Equals(otherDisplay)) @@ -356,7 +357,7 @@ namespace SabreTools.Metadata } else if (self is Part selfPart && other is Part otherPart) { - if (selfPart.Interface != otherPart.Interface) + if (!selfPart.Equals(otherPart)) return false; } else if (self is Port selfPort && other is Port otherPort) diff --git a/SabreTools.Serialization.CrossModel/SoftwareList.Deserializer.cs b/SabreTools.Serialization.CrossModel/SoftwareList.Deserializer.cs index 864ea791..b024f6ef 100644 --- a/SabreTools.Serialization.CrossModel/SoftwareList.Deserializer.cs +++ b/SabreTools.Serialization.CrossModel/SoftwareList.Deserializer.cs @@ -79,7 +79,7 @@ namespace SabreTools.Serialization.CrossModel Endianness = item.Endianness, }; - var roms = item.Read(Data.Models.Metadata.DataArea.RomKey); + var roms = item.Rom; if (roms is not null && roms.Length > 0) dataArea.Rom = Array.ConvertAll(roms, ConvertFromInternalModel); @@ -145,7 +145,7 @@ namespace SabreTools.Serialization.CrossModel Name = item.Name, }; - var disks = item.Read(Data.Models.Metadata.DiskArea.DiskKey); + var disks = item.Disk; if (disks is not null && disks.Length > 0) diskArea.Disk = Array.ConvertAll(disks, ConvertFromInternalModel); @@ -189,19 +189,19 @@ namespace SabreTools.Serialization.CrossModel Interface = item.Interface, }; - var features = item.Read(Data.Models.Metadata.Part.FeatureKey); + var features = item.Feature; if (features is not null && features.Length > 0) part.Feature = Array.ConvertAll(features, ConvertFromInternalModel); - var dataAreas = item.Read(Data.Models.Metadata.Part.DataAreaKey); + var dataAreas = item.DataArea; if (dataAreas is not null && dataAreas.Length > 0) part.DataArea = Array.ConvertAll(dataAreas, ConvertFromInternalModel); - var diskAreas = item.Read(Data.Models.Metadata.Part.DiskAreaKey); + var diskAreas = item.DiskArea; if (diskAreas is not null && diskAreas.Length > 0) part.DiskArea = Array.ConvertAll(diskAreas, ConvertFromInternalModel); - var dipSwitches = item.Read(Data.Models.Metadata.Part.DipSwitchKey); + var dipSwitches = item.DipSwitch; if (dipSwitches is not null && dipSwitches.Length > 0) part.DipSwitch = Array.ConvertAll(dipSwitches, ConvertFromInternalModel); diff --git a/SabreTools.Serialization.CrossModel/SoftwareList.Serializer.cs b/SabreTools.Serialization.CrossModel/SoftwareList.Serializer.cs index ab8d821a..dc526522 100644 --- a/SabreTools.Serialization.CrossModel/SoftwareList.Serializer.cs +++ b/SabreTools.Serialization.CrossModel/SoftwareList.Serializer.cs @@ -81,7 +81,7 @@ namespace SabreTools.Serialization.CrossModel }; if (item.Rom is not null && item.Rom.Length > 0) - dataArea[Data.Models.Metadata.DataArea.RomKey] = Array.ConvertAll(item.Rom, ConvertToInternalModel); + dataArea.Rom = Array.ConvertAll(item.Rom, ConvertToInternalModel); return dataArea; } @@ -145,7 +145,7 @@ namespace SabreTools.Serialization.CrossModel }; if (item.Disk is not null && item.Disk.Length > 0) - diskArea[Data.Models.Metadata.DiskArea.DiskKey] = Array.ConvertAll(item.Disk, ConvertToInternalModel); + diskArea.Disk = Array.ConvertAll(item.Disk, ConvertToInternalModel); return diskArea; } @@ -188,16 +188,16 @@ namespace SabreTools.Serialization.CrossModel }; if (item.Feature is not null && item.Feature.Length > 0) - part[Data.Models.Metadata.Part.FeatureKey] = Array.ConvertAll(item.Feature, ConvertToInternalModel); + part.Feature = Array.ConvertAll(item.Feature, ConvertToInternalModel); if (item.DataArea is not null && item.DataArea.Length > 0) - part[Data.Models.Metadata.Part.DataAreaKey] = Array.ConvertAll(item.DataArea, ConvertToInternalModel); + part.DataArea = Array.ConvertAll(item.DataArea, ConvertToInternalModel); if (item.DiskArea is not null && item.DiskArea.Length > 0) - part[Data.Models.Metadata.Part.DiskAreaKey] = Array.ConvertAll(item.DiskArea, ConvertToInternalModel); + part.DiskArea = Array.ConvertAll(item.DiskArea, ConvertToInternalModel); if (item.DipSwitch is not null && item.DipSwitch.Length > 0) - part[Data.Models.Metadata.Part.DipSwitchKey] = Array.ConvertAll(item.DipSwitch, ConvertToInternalModel); + part.DipSwitch = Array.ConvertAll(item.DipSwitch, ConvertToInternalModel); return part; }