From 618ab6f94d7382ac304981deef1f1e982682ad99 Mon Sep 17 00:00:00 2001 From: ArtroxGabriel Date: Thu, 5 Jun 2025 19:45:05 -0300 Subject: [PATCH] feat(parser): extract commum logic to csv parser --- SubMerge/Models/CountryRecord.cs | 12 ++++++------ SubMerge/Models/GrapeRecord.cs | 15 +++++++-------- SubMerge/Models/WineRecord.cs | 17 ++++++++--------- SubMerge/Parsers/CsvParser.cs | 20 ++++++++++++++++++++ 4 files changed, 41 insertions(+), 23 deletions(-) create mode 100644 SubMerge/Parsers/CsvParser.cs diff --git a/SubMerge/Models/CountryRecord.cs b/SubMerge/Models/CountryRecord.cs index e388215..9108b03 100644 --- a/SubMerge/Models/CountryRecord.cs +++ b/SubMerge/Models/CountryRecord.cs @@ -1,4 +1,5 @@ using System.Diagnostics.CodeAnalysis; +using SubMerge.Parsers; namespace SubMerge.Models; @@ -16,18 +17,17 @@ public CountryRecord(int countryId, string name, string code) Code = code; } - public int CountryId { get; set; } - public string Name { get; set; } - public string Code { get; set; } + public int CountryId { get; init; } + public string Name { get; init; } + public string Code { get; init; } public static CountryRecord Parse(string s, IFormatProvider? provider) { if (string.IsNullOrWhiteSpace(s)) throw new ArgumentException("Input cannot be null or empty", nameof(s)); - var parts = s.Split(','); - if (parts.Length != 3) - throw new FormatException("Input string must contain exactly 3 comma-separated values."); + + var parts = CsvParser.SplitAndValidateCsv(s, 3).Select(p => p.Trim()).ToArray(); return new CountryRecord( int.Parse(parts[0]), diff --git a/SubMerge/Models/GrapeRecord.cs b/SubMerge/Models/GrapeRecord.cs index 0adf593..7cc63a1 100644 --- a/SubMerge/Models/GrapeRecord.cs +++ b/SubMerge/Models/GrapeRecord.cs @@ -1,4 +1,5 @@ using System.Diagnostics.CodeAnalysis; +using SubMerge.Parsers; namespace SubMerge.Models; @@ -18,19 +19,17 @@ public GrapeRecord(int grapeId, string name, GrapeType type, int harvestYear, in CountrySourceId = countrySourceId; } - public int GrapeID { get; set; } - public string Name { get; set; } - public GrapeType Type { get; set; } - public int HarvestYear { get; set; } - public int CountrySourceId { get; set; } + public int GrapeID { get; init; } + public string Name { get; init; } + public GrapeType Type { get; init; } + public int HarvestYear { get; init; } + public int CountrySourceId { get; init; } public static GrapeRecord Parse(string s, IFormatProvider? provider) { if (string.IsNullOrWhiteSpace(s)) throw new ArgumentException("Input cannot be null or empty", nameof(s)); - var parts = s.Split(','); - if (parts.Length != 5) - throw new FormatException("Input string must contain exactly 5 comma-separated values."); + var parts = CsvParser.SplitAndValidateCsv(s, 5).Select(p => p.Trim()).ToArray(); return new GrapeRecord( int.Parse(parts[0]), diff --git a/SubMerge/Models/WineRecord.cs b/SubMerge/Models/WineRecord.cs index 727e3d4..b1b1cbc 100644 --- a/SubMerge/Models/WineRecord.cs +++ b/SubMerge/Models/WineRecord.cs @@ -1,4 +1,5 @@ using System.Diagnostics.CodeAnalysis; +using SubMerge.Parsers; namespace SubMerge.Models; @@ -9,7 +10,7 @@ public WineRecord(int wineId, string label, int productionYear, int grapeId, int if (string.IsNullOrWhiteSpace(label)) throw new ArgumentException("Label cannot be empty", nameof(label)); if (productionYear <= 0) - throw new ArgumentException("Harvest year must be positive", nameof(productionYear)); + throw new ArgumentException("Production year must be positive", nameof(productionYear)); WineId = wineId; Label = label; @@ -18,19 +19,17 @@ public WineRecord(int wineId, string label, int productionYear, int grapeId, int CountryProductionId = countryProductionId; } - public int WineId { get; set; } - public string Label { get; set; } - public int ProductionYear { get; set; } - public int GrapeId { get; set; } - public int CountryProductionId { get; set; } + public int WineId { get; init; } + public string Label { get; init; } + public int ProductionYear { get; init; } + public int GrapeId { get; init; } + public int CountryProductionId { get; init; } public static WineRecord Parse(string s, IFormatProvider? provider) { if (string.IsNullOrWhiteSpace(s)) throw new ArgumentException("Input cannot be null or empty", nameof(s)); - var parts = s.Split(','); - if (parts.Length != 5) - throw new FormatException("Input string must contain exactly 5 comma-separated values."); + var parts = CsvParser.SplitAndValidateCsv(s, 5).Select(p => p.Trim()).ToArray(); return new WineRecord( int.Parse(parts[0]), diff --git a/SubMerge/Parsers/CsvParser.cs b/SubMerge/Parsers/CsvParser.cs new file mode 100644 index 0000000..e5ead4b --- /dev/null +++ b/SubMerge/Parsers/CsvParser.cs @@ -0,0 +1,20 @@ +namespace SubMerge.Parsers; + +public static class CsvParser +{ + /// + /// Splits a comma-separated string and validates that it contains exactly N parts. + /// + /// The input string to parse. + /// The total N of expected parts of csv + /// An array of strings representing the parsed parts. + /// Thrown if the input string does not contain exactly N comma-separated values. + public static string[] SplitAndValidateCsv(string s, int n) + { + var parts = s.Split(','); + if (parts.Length != n) + throw new FormatException($"Input string must contain exactly {n} comma-separated values."); + + return parts; + } +}