diff --git a/AsbCloudInfrastructure/Services/ParserServiceFactory.cs b/AsbCloudInfrastructure/Services/ParserServiceFactory.cs index 17f3ed23..7aeceb98 100644 --- a/AsbCloudInfrastructure/Services/ParserServiceFactory.cs +++ b/AsbCloudInfrastructure/Services/ParserServiceFactory.cs @@ -1,8 +1,8 @@ using System; using System.Collections.Generic; using AsbCloudApp.Data; -using AsbCloudApp.Requests.Import; -using AsbCloudApp.Services; +using AsbCloudApp.Requests.ParserOptions; +using AsbCloudApp.Services.Parser; using AsbCloudInfrastructure.Services.Trajectory.Parser; namespace AsbCloudInfrastructure.Services; @@ -12,19 +12,30 @@ public class ParserServiceFactory public const int IdTrajectoryFactManualParserService = 1; public const int IdTrajectoryPlanParserService = 2; - private readonly IDictionary> parsers = new Dictionary> + private readonly IDictionary> parsers = new Dictionary> { { IdTrajectoryPlanParserService, () => new TrajectoryPlanParserService() }, { IdTrajectoryFactManualParserService, () => new TrajectoryFactManualParserService() } }; - public IParserService Create(int idImportService) + public IParserService GetParser(int idParserService) where TDto : class, IId - where TOptions : ParserOptionsRequestBase { - var parser = parsers[idImportService].Invoke(); + if (!parsers.TryGetValue(idParserService, out var parserService)) + throw new ArgumentNullException(nameof(idParserService), "Сервис не зарегистрирован"); - return parser as IParserService - ?? throw new ArgumentNullException(nameof(idImportService), "Не удалось распознать файл"); + return parserService.Invoke() as IParserService + ?? throw new ArgumentNullException(nameof(idParserService), "Ошибка приведения типа"); + } + + public IParserServiceWithOptions GetParserWithOptions(int idParserService) + where TDto : class, IId + where TOptions : IParserOptionsRequest + { + if (!parsers.TryGetValue(idParserService, out var parserService)) + throw new ArgumentNullException(nameof(idParserService), "Сервис не зарегистрирован"); + + return parserService.Invoke() as IParserServiceWithOptions + ?? throw new ArgumentNullException(nameof(idParserService), "Ошибка приведения типа"); } } \ No newline at end of file diff --git a/AsbCloudInfrastructure/Services/Trajectory/Parser/TrajectoryFactManualParserService.cs b/AsbCloudInfrastructure/Services/Trajectory/Parser/TrajectoryFactManualParserService.cs index 6a3a89cc..d494c5b6 100644 --- a/AsbCloudInfrastructure/Services/Trajectory/Parser/TrajectoryFactManualParserService.cs +++ b/AsbCloudInfrastructure/Services/Trajectory/Parser/TrajectoryFactManualParserService.cs @@ -6,6 +6,8 @@ namespace AsbCloudInfrastructure.Services.Trajectory.Parser; public class TrajectoryFactManualParserService : TrajectoryParserService { + protected override string SheetName => "Фактическая траектория"; + protected override ValidationResultDto ParseRow(IXLRow row) { var trajectoryRow = new TrajectoryGeoFactDto diff --git a/AsbCloudInfrastructure/Services/Trajectory/Parser/TrajectoryParserService.cs b/AsbCloudInfrastructure/Services/Trajectory/Parser/TrajectoryParserService.cs index 6b5177fe..16dbf55d 100644 --- a/AsbCloudInfrastructure/Services/Trajectory/Parser/TrajectoryParserService.cs +++ b/AsbCloudInfrastructure/Services/Trajectory/Parser/TrajectoryParserService.cs @@ -1,78 +1,31 @@ using AsbCloudApp.Data.Trajectory; using ClosedXML.Excel; -using System.Collections.Generic; using System.IO; using System.Linq; using AsbCloudApp.Data; -using AsbCloudApp.Requests.Import; -using AsbCloudApp.Services; +using AsbCloudApp.Services.Parser; namespace AsbCloudInfrastructure.Services.Trajectory.Parser; -public abstract class TrajectoryParserService : IParserService +public abstract class TrajectoryParserService : IParserService where T : TrajectoryGeoDto { + private const int HeaderRowsCount = 2; + private const int ColumnCount = 6; + + protected abstract string SheetName { get; } + protected abstract ValidationResultDto ParseRow(IXLRow row); - public ParserResultDto Parse(Stream file, TrajectoryParserRequest options) + public ParserResultDto Parse(Stream file) { using var workbook = new XLWorkbook(file, XLEventTracking.Disabled); - var trajectoryRows = ParseFileStream(file, options); + var sheet = workbook.Worksheets.FirstOrDefault(ws => + ws.Name.ToLower().Trim() == SheetName.ToLower().Trim()) + ?? throw new FileFormatException($"Книга excel не содержит листа {SheetName}."); + + var trajectoryRows = sheet.Parse(ParseRow, ColumnCount, HeaderRowsCount); return trajectoryRows; } - - private ParserResultDto ParseFileStream(Stream stream, TrajectoryParserRequest options) - { - using var workbook = new XLWorkbook(stream, XLEventTracking.Disabled); - return ParseWorkbook(workbook, options); - } - - private ParserResultDto ParseWorkbook(IXLWorkbook workbook, TrajectoryParserRequest options) - { - var sheetTrajectory = workbook.Worksheets.FirstOrDefault(ws => - ws.Name.ToLower().Trim() == options.SheetName.ToLower().Trim()); - if (sheetTrajectory is null) - throw new FileFormatException($"Книга excel не содержит листа {options.SheetName}."); - var trajectoryRows = ParseSheet(sheetTrajectory, options); - return trajectoryRows; - } - - private ParserResultDto ParseSheet(IXLWorksheet sheet, TrajectoryParserRequest options) - { - if (sheet.RangeUsed().RangeAddress.LastAddress.ColumnNumber < 6) - throw new FileFormatException($"Лист {sheet.Name} содержит меньшее количество столбцов."); - - var count = sheet.RowsUsed().Count() - options.HeaderRowsCount; - - if (count > 1024) - throw new FileFormatException($"Лист {sheet.Name} содержит слишком большое количество строк."); - - if (count <= 0) - throw new FileFormatException($"Лист {sheet.Name} некорректного формата либо пустой"); - - var trajectoryRows = new List>(count); - var parseErrors = new List(); - for (int i = 0; i < count; i++) - { - var row = sheet.Row(1 + i + options.HeaderRowsCount); - try - { - var trajectoryRow = ParseRow(row); - trajectoryRows.Add(trajectoryRow); - } - catch (FileFormatException ex) - { - parseErrors.Add(ex.Message); - } - } - - if (parseErrors.Any()) - throw new FileFormatException(string.Join("\r\n", parseErrors)); - - return new ParserResultDto - { - Item = trajectoryRows - }; - } } \ No newline at end of file diff --git a/AsbCloudInfrastructure/Services/Trajectory/Parser/TrajectoryPlanParserService.cs b/AsbCloudInfrastructure/Services/Trajectory/Parser/TrajectoryPlanParserService.cs index 6b4654fd..97d7ca29 100644 --- a/AsbCloudInfrastructure/Services/Trajectory/Parser/TrajectoryPlanParserService.cs +++ b/AsbCloudInfrastructure/Services/Trajectory/Parser/TrajectoryPlanParserService.cs @@ -6,6 +6,8 @@ namespace AsbCloudInfrastructure.Services.Trajectory.Parser; public class TrajectoryPlanParserService : TrajectoryParserService { + protected override string SheetName => "Плановая траектория"; + protected override ValidationResultDto ParseRow(IXLRow row) { var trajectoryRow = new TrajectoryGeoPlanDto diff --git a/AsbCloudWebApi.Tests/Services/Trajectory/TrajectoryParserTest.cs b/AsbCloudWebApi.Tests/Services/Trajectory/TrajectoryParserTest.cs index 0da13a71..b5c722b4 100644 --- a/AsbCloudWebApi.Tests/Services/Trajectory/TrajectoryParserTest.cs +++ b/AsbCloudWebApi.Tests/Services/Trajectory/TrajectoryParserTest.cs @@ -1,6 +1,5 @@ using System.Linq; using AsbCloudApp.Data.Trajectory; -using AsbCloudApp.Requests.Import; using AsbCloudInfrastructure.Services; using Xunit; @@ -10,20 +9,6 @@ public class TrajectoryParserTest { private const string UsingTemplateFile = "AsbCloudWebApi.Tests.Services.Trajectory.Templates"; - private readonly TrajectoryParserRequest planTrajectoryParserOptions = new() - { - IdParserService = ParserServiceFactory.IdTrajectoryPlanParserService, - SheetName = "Плановая траектория", - HeaderRowsCount = 2 - }; - - private readonly TrajectoryParserRequest factTrajectoryParserOptions = new() - { - IdParserService = ParserServiceFactory.IdTrajectoryFactManualParserService, - SheetName = "Фактическая траектория", - HeaderRowsCount = 2 - }; - private static readonly ParserServiceFactory parserServiceFactory = new(); [Fact] @@ -35,9 +20,8 @@ public class TrajectoryParserTest if (stream is null) Assert.Fail("Файла для импорта не существует"); - var parserService = parserServiceFactory.Create( - planTrajectoryParserOptions.IdParserService); - var trajectoryRows = parserService.Parse(stream, planTrajectoryParserOptions); + var parserService = parserServiceFactory.GetParser(ParserServiceFactory.IdTrajectoryPlanParserService); + var trajectoryRows = parserService.Parse(stream); Assert.Equal(3, trajectoryRows.Item.Count()); } @@ -51,9 +35,8 @@ public class TrajectoryParserTest if (stream is null) Assert.Fail("Файла для импорта не существует"); - var parserService = parserServiceFactory.Create( - factTrajectoryParserOptions.IdParserService); - var trajectoryRows = parserService.Parse(stream, factTrajectoryParserOptions); + var parserService = parserServiceFactory.GetParser(ParserServiceFactory.IdTrajectoryFactManualParserService); + var trajectoryRows = parserService.Parse(stream); Assert.Equal(4, trajectoryRows.Item.Count()); }