-
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathEntityParseValidateReport.cs
More file actions
165 lines (136 loc) · 5.57 KB
/
EntityParseValidateReport.cs
File metadata and controls
165 lines (136 loc) · 5.57 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using DocumentFormat.OpenXml.Packaging;
using FluentAssertions;
using MicroElements.Diagnostics;
using MicroElements.Metadata.OpenXml.Excel.Parsing;
using MicroElements.Metadata.OpenXml.Excel.Reporting;
using MicroElements.Metadata.Parsing;
using MicroElements.Validation;
using MicroElements.Validation.Rules;
using Xunit;
namespace MicroElements.Metadata.Tests.examples
{
public class EntityParseValidateReport
{
public class Entity
{
public DateTime CreatedAt { get; }
public string Name { get; }
public Entity(DateTime createdAt, string name)
{
CreatedAt = createdAt;
Name = name;
}
/// <inheritdoc />
public override string ToString()
{
return $"{nameof(CreatedAt)}: {CreatedAt:yyyy-MM-ddTHH:mm:ss.FFFFFFF}, {nameof(Name)}: {Name}";
}
}
public class EntityMeta : IPropertySet, IModelMapper<Entity>
{
public static readonly EntityMeta Instance = new EntityMeta();
public static readonly IProperty<DateTime> CreatedAt = new Property<DateTime>("CreatedAt");
public static readonly IProperty<string> Name = new Property<string>("Name");
/// <inheritdoc />
public IEnumerable<IProperty> GetProperties()
{
yield return CreatedAt;
yield return Name;
}
/// <inheritdoc />
public IPropertyContainer ToContainer(Entity model)
{
return new MutablePropertyContainer()
.WithValue(CreatedAt, model.CreatedAt)
.WithValue(Name, model.Name);
}
/// <inheritdoc />
public Entity ToModel(IPropertyContainer container)
{
return new Entity(
createdAt: container.GetValue(CreatedAt),
name: container.GetValue(Name));
}
}
public class EntityParser : ParserProvider
{
protected ParseResult<DateTime> ParseDate(string? value) => Parser.ParseDateTime(value);
/// <inheritdoc />
public EntityParser()
{
Discriminator = EntityMeta.Name;
Source("CreatedAt", ParseDate).Target(EntityMeta.CreatedAt);
Source("Name").Target(EntityMeta.Name);
Source("Name").Target(EntityMeta.Name).Discriminator("Admin");
Source("Name").SkipNull().Target(EntityMeta.Name).Condition(context => context.IsValueExistsAndNotNull() && context.PropertyContainer.GetValue(EntityMeta.Name) == "Admin");
}
}
public class EntityValidator : IValidator
{
/// <inheritdoc />
public IEnumerable<IValidationRule> GetRules()
{
yield return EntityMeta.CreatedAt.NotDefault();
yield return EntityMeta.Name.Required();
}
}
public class EntityReport : ReportProvider
{
public EntityReport(string reportName = "Entities")
: base(reportName)
{
Add(EntityMeta.CreatedAt).SetDateSerialFormat();
Add(EntityMeta.Name);
}
}
public Stream ReportToExcel(Entity[] entities, IReportBuilderSettings? reportBuilderSettings)
{
var reportRows = entities.Select(entity => EntityMeta.Instance.ToContainer(entity));
var excelStream = new MemoryStream();
ExcelReportBuilder.Create(excelStream, settings: reportBuilderSettings)
.AddReportSheet(new EntityReport("Entities"), reportRows)
.SaveAndClose();
return excelStream;
}
public Entity[] ParseExcel(Stream stream)
{
var document = SpreadsheetDocument.Open(stream, false);
var messages = new List<Message>();
var entities = document
.GetSheet("Entities")
.GetRowsAs(new EntityParser(), list => new PropertyContainer(list))
.ValidateAndFilter(new EntityValidator(), result => messages.AddRange(result.ValidationMessages))
.Select(container => EntityMeta.Instance.ToModel(container))
.ToArray();
return entities;
}
[Fact]
public void UseCase()
{
// Trim DateTime to milliseconds because default DateTime render trimmed to milliseconds
DateTime NowTrimmed(long trim)
{
DateTime now = DateTime.Now;
return now.AddTicks(-(now.Ticks % trim));
}
Entity[] entities = {
new Entity(NowTrimmed(TimeSpan.TicksPerSecond), "Name1"),
new Entity(NowTrimmed(TimeSpan.TicksPerMillisecond), "Name2"),
new Entity(NowTrimmed(TimeSpan.TicksPerDay), "Name3"),
};
BuildExcelAndParseBack(null);
BuildExcelAndParseBack(new ReportBuilderSettings(cellFactory: new CachedOpenXmlCellFactory()));
void BuildExcelAndParseBack(IReportBuilderSettings? reportBuilderSettings)
{
Stream excelStream = ReportToExcel(entities, reportBuilderSettings);
Entity[] fromExcel = ParseExcel(excelStream);
fromExcel.Should().HaveCount(3);
fromExcel.Should().BeEquivalentTo(entities);
}
}
}
}