diff --git a/AsbCloudApp/Requests/ParserOptions/IParserOptionsRequest.cs b/AsbCloudApp/Requests/ParserOptions/IParserOptionsRequest.cs
index dd8f8e4f..b3b12f51 100644
--- a/AsbCloudApp/Requests/ParserOptions/IParserOptionsRequest.cs
+++ b/AsbCloudApp/Requests/ParserOptions/IParserOptionsRequest.cs
@@ -1,8 +1,19 @@
namespace AsbCloudApp.Requests.ParserOptions;
///
-/// Интерфейс для параметров парсера
+/// Параметры парсинга
///
public interface IParserOptionsRequest
{
+ private static DummyOptions empty => new();
+
+ private class DummyOptions : IParserOptionsRequest
+ {
+ }
+
+ ///
+ /// Получение пустого объекта опций
+ ///
+ ///
+ public static IParserOptionsRequest Empty() => empty;
}
\ No newline at end of file
diff --git a/AsbCloudApp/Services/Parser/IParserServiceWithOptions.cs b/AsbCloudApp/Services/IParserService.cs
similarity index 50%
rename from AsbCloudApp/Services/Parser/IParserServiceWithOptions.cs
rename to AsbCloudApp/Services/IParserService.cs
index 83e54a27..2cfd8eb7 100644
--- a/AsbCloudApp/Services/Parser/IParserServiceWithOptions.cs
+++ b/AsbCloudApp/Services/IParserService.cs
@@ -1,15 +1,17 @@
using System.IO;
+using System.Threading;
+using System.Threading.Tasks;
using AsbCloudApp.Data;
using AsbCloudApp.Requests.ParserOptions;
-namespace AsbCloudApp.Services.Parser;
+namespace AsbCloudApp.Services;
///
-/// Сервис парсинга файлов с доп. параметрами
+/// Сервис парсинга
///
///
///
-public interface IParserServiceWithOptions
+public interface IParserService : IParserService
where TDto : class, IId
where TOptions : IParserOptionsRequest
{
@@ -20,4 +22,17 @@ public interface IParserServiceWithOptions
///
///
ParserResultDto Parse(Stream file, TOptions options);
+
+ ///
+ /// Получение шаблона для заполнения
+ ///
+ ///
+ Stream GetTemplateFile();
+}
+
+///
+/// Сервис парсинга(интерфейс маркер)
+///
+public interface IParserService
+{
}
\ No newline at end of file
diff --git a/AsbCloudApp/Services/Parser/IParserService.cs b/AsbCloudApp/Services/Parser/IParserService.cs
deleted file mode 100644
index 628859bb..00000000
--- a/AsbCloudApp/Services/Parser/IParserService.cs
+++ /dev/null
@@ -1,19 +0,0 @@
-using System.IO;
-using AsbCloudApp.Data;
-
-namespace AsbCloudApp.Services.Parser;
-
-///
-/// Сервис парсинга файлов
-///
-///
-public interface IParserService
- where TDto : class, IId
-{
- ///
- /// Распарсить файл
- ///
- ///
- ///
- ParserResultDto Parse(Stream file);
-}
\ No newline at end of file
diff --git a/AsbCloudInfrastructure/XLParserExtensions.cs b/AsbCloudInfrastructure/ParserServiceBase.cs
similarity index 69%
rename from AsbCloudInfrastructure/XLParserExtensions.cs
rename to AsbCloudInfrastructure/ParserServiceBase.cs
index 28ecb089..d98404e7 100644
--- a/AsbCloudInfrastructure/XLParserExtensions.cs
+++ b/AsbCloudInfrastructure/ParserServiceBase.cs
@@ -4,17 +4,30 @@ using System.ComponentModel.DataAnnotations;
using System.IO;
using System.Linq;
using AsbCloudApp.Data;
+using AsbCloudApp.Requests.ParserOptions;
+using AsbCloudApp.Services;
using ClosedXML.Excel;
namespace AsbCloudInfrastructure;
-public static class XLParserExtensions
+public abstract class ParserServiceBase : IParserService
+ where TDto : class, IId
+ where TOptions : IParserOptionsRequest
{
- public static ParserResultDto Parse(this IXLWorksheet sheet,
+ protected readonly IServiceProvider serviceProvider;
+
+ protected ParserServiceBase(IServiceProvider serviceProvider)
+ {
+ this.serviceProvider = serviceProvider;
+ }
+
+ public abstract ParserResultDto Parse(Stream file, TOptions options);
+ public abstract Stream GetTemplateFile();
+
+ protected virtual ParserResultDto ParseExcelSheet(IXLWorksheet sheet,
Func> parseRow,
int columnCount,
int headerRowsCount = 0)
- where TDto : class, IId
{
if (sheet.RangeUsed().RangeAddress.LastAddress.ColumnNumber < columnCount)
throw new FileFormatException($"Лист {sheet.Name} содержит меньшее количество столбцов.");
@@ -26,10 +39,10 @@ public static class XLParserExtensions
if (count <= 0)
return new ParserResultDto();
-
+
var dtos = new List>(count);
var warnings = new List();
-
+
for (var i = 0; i < count; i++)
{
var row = sheet.Row(1 + i + headerRowsCount);
@@ -45,7 +58,7 @@ public static class XLParserExtensions
warnings.Add(warning);
}
}
-
+
var parserResult = new ParserResultDto
{
Item = dtos
diff --git a/AsbCloudInfrastructure/Services/ParserServiceFactory.cs b/AsbCloudInfrastructure/Services/ParserServiceFactory.cs
index 7aeceb98..5b852a8e 100644
--- a/AsbCloudInfrastructure/Services/ParserServiceFactory.cs
+++ b/AsbCloudInfrastructure/Services/ParserServiceFactory.cs
@@ -2,7 +2,7 @@ using System;
using System.Collections.Generic;
using AsbCloudApp.Data;
using AsbCloudApp.Requests.ParserOptions;
-using AsbCloudApp.Services.Parser;
+using AsbCloudApp.Services;
using AsbCloudInfrastructure.Services.Trajectory.Parser;
namespace AsbCloudInfrastructure.Services;
@@ -12,30 +12,25 @@ public class ParserServiceFactory
public const int IdTrajectoryFactManualParserService = 1;
public const int IdTrajectoryPlanParserService = 2;
- private readonly IDictionary> parsers = new Dictionary>
- {
- { IdTrajectoryPlanParserService, () => new TrajectoryPlanParserService() },
- { IdTrajectoryFactManualParserService, () => new TrajectoryFactManualParserService() }
- };
+ private readonly IDictionary> parsers;
- public IParserService GetParser(int idParserService)
- where TDto : class, IId
+ public ParserServiceFactory(IServiceProvider serviceProvider)
{
- if (!parsers.TryGetValue(idParserService, out var parserService))
- throw new ArgumentNullException(nameof(idParserService), "Сервис не зарегистрирован");
-
- return parserService.Invoke() as IParserService
- ?? throw new ArgumentNullException(nameof(idParserService), "Ошибка приведения типа");
+ parsers = new Dictionary>
+ {
+ { IdTrajectoryPlanParserService, () => new TrajectoryPlanParserService(serviceProvider) },
+ { IdTrajectoryFactManualParserService, () => new TrajectoryFactManualParserService(serviceProvider) }
+ };
}
- public IParserServiceWithOptions GetParserWithOptions(int idParserService)
+ public IParserService Create(int idParserService)
where TDto : class, IId
where TOptions : IParserOptionsRequest
{
if (!parsers.TryGetValue(idParserService, out var parserService))
- throw new ArgumentNullException(nameof(idParserService), "Сервис не зарегистрирован");
+ throw new ArgumentNullException(nameof(idParserService), "Не правильный идентификатор парсера");
- return parserService.Invoke() as IParserServiceWithOptions
+ return parserService.Invoke() as IParserService
?? 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 d494c5b6..6e4034a5 100644
--- a/AsbCloudInfrastructure/Services/Trajectory/Parser/TrajectoryFactManualParserService.cs
+++ b/AsbCloudInfrastructure/Services/Trajectory/Parser/TrajectoryFactManualParserService.cs
@@ -1,4 +1,5 @@
-using AsbCloudApp.Data;
+using System;
+using AsbCloudApp.Data;
using AsbCloudApp.Data.Trajectory;
using ClosedXML.Excel;
@@ -7,7 +8,13 @@ namespace AsbCloudInfrastructure.Services.Trajectory.Parser;
public class TrajectoryFactManualParserService : TrajectoryParserService
{
protected override string SheetName => "Фактическая траектория";
+ protected override string TemplateFileName => "TrajectoryFactManualTemplate.xlsx";
+ public TrajectoryFactManualParserService(IServiceProvider serviceProvider)
+ : base(serviceProvider)
+ {
+ }
+
protected override ValidationResultDto ParseRow(IXLRow row)
{
var trajectoryRow = new TrajectoryGeoFactDto
@@ -22,9 +29,11 @@ public class TrajectoryFactManualParserService : TrajectoryParserService
+ var validationResult = new ValidationResultDto
{
Item = trajectoryRow
};
+
+ return validationResult;
}
}
\ No newline at end of file
diff --git a/AsbCloudInfrastructure/Services/Trajectory/Parser/TrajectoryParserService.cs b/AsbCloudInfrastructure/Services/Trajectory/Parser/TrajectoryParserService.cs
index 16dbf55d..d0afe513 100644
--- a/AsbCloudInfrastructure/Services/Trajectory/Parser/TrajectoryParserService.cs
+++ b/AsbCloudInfrastructure/Services/Trajectory/Parser/TrajectoryParserService.cs
@@ -1,23 +1,36 @@
-using AsbCloudApp.Data.Trajectory;
+using System;
+using AsbCloudApp.Data.Trajectory;
using ClosedXML.Excel;
using System.IO;
using System.Linq;
+using System.Reflection;
using AsbCloudApp.Data;
-using AsbCloudApp.Services.Parser;
+using AsbCloudApp.Requests.ParserOptions;
namespace AsbCloudInfrastructure.Services.Trajectory.Parser;
-public abstract class TrajectoryParserService : IParserService
+public abstract class TrajectoryParserService : ParserServiceBase
where T : TrajectoryGeoDto
{
private const int HeaderRowsCount = 2;
private const int ColumnCount = 6;
+ protected TrajectoryParserService(IServiceProvider serviceProvider)
+ : base(serviceProvider)
+ {
+ }
+
protected abstract string SheetName { get; }
+ protected abstract string TemplateFileName { get; }
+
protected abstract ValidationResultDto ParseRow(IXLRow row);
- public ParserResultDto Parse(Stream file)
+ public override Stream GetTemplateFile() =>
+ Assembly.GetExecutingAssembly().GetTemplateCopyStream(TemplateFileName)
+ ?? throw new ArgumentNullException($"Файл '{TemplateFileName}' не найден");
+
+ public override ParserResultDto Parse(Stream file, IParserOptionsRequest options)
{
using var workbook = new XLWorkbook(file, XLEventTracking.Disabled);
@@ -25,7 +38,7 @@ public abstract class TrajectoryParserService : IParserService
ws.Name.ToLower().Trim() == SheetName.ToLower().Trim())
?? throw new FileFormatException($"Книга excel не содержит листа {SheetName}.");
- var trajectoryRows = sheet.Parse(ParseRow, ColumnCount, HeaderRowsCount);
+ var trajectoryRows = ParseExcelSheet(sheet, ParseRow, ColumnCount, HeaderRowsCount);
return trajectoryRows;
}
}
\ No newline at end of file
diff --git a/AsbCloudInfrastructure/Services/Trajectory/Parser/TrajectoryPlanParserService.cs b/AsbCloudInfrastructure/Services/Trajectory/Parser/TrajectoryPlanParserService.cs
index 97d7ca29..fbf5a537 100644
--- a/AsbCloudInfrastructure/Services/Trajectory/Parser/TrajectoryPlanParserService.cs
+++ b/AsbCloudInfrastructure/Services/Trajectory/Parser/TrajectoryPlanParserService.cs
@@ -1,4 +1,5 @@
-using AsbCloudApp.Data;
+using System;
+using AsbCloudApp.Data;
using AsbCloudApp.Data.Trajectory;
using ClosedXML.Excel;
@@ -7,7 +8,13 @@ namespace AsbCloudInfrastructure.Services.Trajectory.Parser;
public class TrajectoryPlanParserService : TrajectoryParserService
{
protected override string SheetName => "Плановая траектория";
+ protected override string TemplateFileName => "TrajectoryPlanTemplate.xlsx";
+ public TrajectoryPlanParserService(IServiceProvider serviceProvider)
+ : base(serviceProvider)
+ {
+ }
+
protected override ValidationResultDto ParseRow(IXLRow row)
{
var trajectoryRow = new TrajectoryGeoPlanDto
@@ -23,9 +30,11 @@ public class TrajectoryPlanParserService : TrajectoryParserService
+ var validationResult = new ValidationResultDto
{
Item = trajectoryRow
};
+
+ return validationResult;
}
}
\ No newline at end of file
diff --git a/AsbCloudInfrastructure/XLExtentions.cs b/AsbCloudInfrastructure/XLExtentions.cs
index 401e2423..e633a875 100644
--- a/AsbCloudInfrastructure/XLExtentions.cs
+++ b/AsbCloudInfrastructure/XLExtentions.cs
@@ -90,7 +90,7 @@ internal static class XLExtentions
catch
{
throw new FileFormatException(
- $"Лист '{cell.Worksheet.Name}'. Ячейка: ({cell.Address.RowNumber},{cell.Address.ColumnNumber}) содержит некорректное значение");
+ $"Лист '{cell.Worksheet.Name}'. {cell.Address.RowNumber} строка содержит некорректное значение в {cell.Address.ColumnNumber} столбце");
}
}
}
\ No newline at end of file
diff --git a/AsbCloudWebApi.Tests/Services/Trajectory/TrajectoryParserTest.cs b/AsbCloudWebApi.Tests/Services/Trajectory/TrajectoryParserTest.cs
index b5c722b4..1fddd56d 100644
--- a/AsbCloudWebApi.Tests/Services/Trajectory/TrajectoryParserTest.cs
+++ b/AsbCloudWebApi.Tests/Services/Trajectory/TrajectoryParserTest.cs
@@ -1,6 +1,10 @@
-using System.Linq;
+using System;
+using System.Linq;
using AsbCloudApp.Data.Trajectory;
+using AsbCloudApp.Requests.ParserOptions;
using AsbCloudInfrastructure.Services;
+using Microsoft.Extensions.DependencyInjection;
+using NSubstitute;
using Xunit;
namespace AsbCloudWebApi.Tests.Services.Trajectory;
@@ -8,8 +12,20 @@ namespace AsbCloudWebApi.Tests.Services.Trajectory;
public class TrajectoryParserTest
{
private const string UsingTemplateFile = "AsbCloudWebApi.Tests.Services.Trajectory.Templates";
+
+ private readonly IServiceProvider serviceProviderMock = Substitute.For();
+ private readonly IServiceScope serviceScopeMock = Substitute.For();
+ private readonly IServiceScopeFactory serviceScopeFactoryMock = Substitute.For();
- private static readonly ParserServiceFactory parserServiceFactory = new();
+ private readonly ParserServiceFactory parserServiceFactory;
+
+ public TrajectoryParserTest()
+ {
+ serviceScopeFactoryMock.CreateScope().Returns(serviceScopeMock);
+ ((ISupportRequiredService)serviceProviderMock).GetRequiredService(typeof(IServiceScopeFactory)).Returns(serviceScopeFactoryMock);
+
+ parserServiceFactory = new ParserServiceFactory(serviceProviderMock);
+ }
[Fact]
public void Parse_trajectory_plan()
@@ -20,8 +36,10 @@ public class TrajectoryParserTest
if (stream is null)
Assert.Fail("Файла для импорта не существует");
- var parserService = parserServiceFactory.GetParser(ParserServiceFactory.IdTrajectoryPlanParserService);
- var trajectoryRows = parserService.Parse(stream);
+ var parserService = parserServiceFactory.Create(
+ ParserServiceFactory.IdTrajectoryPlanParserService);
+
+ var trajectoryRows = parserService.Parse(stream, IParserOptionsRequest.Empty());
Assert.Equal(3, trajectoryRows.Item.Count());
}
@@ -35,8 +53,10 @@ public class TrajectoryParserTest
if (stream is null)
Assert.Fail("Файла для импорта не существует");
- var parserService = parserServiceFactory.GetParser(ParserServiceFactory.IdTrajectoryFactManualParserService);
- var trajectoryRows = parserService.Parse(stream);
+ var parserService = parserServiceFactory.Create(
+ ParserServiceFactory.IdTrajectoryFactManualParserService);
+
+ var trajectoryRows = parserService.Parse(stream, IParserOptionsRequest.Empty());
Assert.Equal(4, trajectoryRows.Item.Count());
}