IsolatedArea.cs
8.03 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
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using Newtonsoft.Json;
using Sungero.Core;
using Sungero.SmartProcessing.Structures.Module;
namespace Sungero.SmartProcessing.Isolated.Repacking
{
/// <summary>
/// Менеджер сборки Pdf документов.
/// </summary>
public sealed class PdfBuildManager
{
#region Thread-safety Singletone
// About Singletones: https://csharpindepth.com/Articles/Singleton
private static readonly PdfBuildManager BuildInstance = new PdfBuildManager();
[SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1409:RemoveUnnecessaryCode", Justification = "Part of a thread-safety Singletone.")]
static PdfBuildManager()
{
}
private PdfBuildManager()
{
}
public static PdfBuildManager Instance
{
get
{
return BuildInstance;
}
}
#endregion
/// <summary>
/// Активные сборщики.
/// </summary>
public List<IPdfBuilder> ActivePdfBuilders { get; private set; }
/// <summary>
/// Добавить PDF сборщик.
/// </summary>
/// <param name="builder">Сборщик.</param>
public void AddPdfBuilder(IPdfBuilder builder)
{
if (this.ActivePdfBuilders == null)
this.ActivePdfBuilders = new List<IPdfBuilder>();
this.ActivePdfBuilders.Add(builder);
}
/// <summary>
/// Получить сборщик тел документов.
/// </summary>
/// <param name="builderGuid">Гуид сборщика.</param>
/// <returns>Сборщик.</returns>
public IPdfBuilder GetPdfBuilder(Guid builderGuid)
{
return this.ActivePdfBuilders.Where(x => x.Guid == builderGuid).FirstOrDefault();
}
/// <summary>
/// Убрать сборщик из списка активных.
/// </summary>
/// <param name="builderGuid">Гуид упаковщика.</param>
public void DeletePdfBuilder(Guid builderGuid)
{
var builder = this.ActivePdfBuilders.Where(x => x.Guid == builderGuid).FirstOrDefault();
if (builder != null)
this.ActivePdfBuilders.Remove(builder);
}
}
/// <summary>
/// Сборщик Pdf документов.
/// </summary>
public interface IPdfBuilder
{
/// <summary>
/// Уникальный идентификатор.
/// </summary>
Guid Guid { get; }
/// <summary>
/// Исходные документы для сборки.
/// </summary>
Dictionary<long, Aspose.Pdf.Document> SourceDocuments { get; set; }
/// <summary>
/// Добавить исходный документ.
/// </summary>
/// <param name="id">Ид документа.</param>
/// <param name="body">Тело документа.</param>
void AddSourceDocument(long id, Stream body);
/// <summary>
/// Собрать новый документ.
/// </summary>
/// <param name="pages">Информация о страницах нового документа.</param>
/// <returns>Тело нового документа.</returns>
Stream Build(List<Page> pages);
}
/// <summary>
/// Сборщик Pdf документов.
/// </summary>
public class PdfBuilder : IPdfBuilder
{
/// <summary>
/// Шаг угла поворота страницы.
/// </summary>
public const int RotationAngleStep = 90;
/// <summary>
/// Уникальный идентификатор.
/// </summary>
public Guid Guid { get; protected set; }
/// <summary>
/// Исходные документы для сборки.
/// </summary>
public Dictionary<long, Aspose.Pdf.Document> SourceDocuments { get; set; }
/// <summary>
/// Добавить исходный документ.
/// </summary>
/// <param name="id">Ид документа.</param>
/// <param name="body">Тело документа.</param>
public virtual void AddSourceDocument(long id, Stream body)
{
var document = new Aspose.Pdf.Document(body);
this.SourceDocuments.Add(id, document);
}
/// <summary>
/// Собрать документ.
/// </summary>
/// <param name="pages">Информация о страницах нового документа.</param>
/// <returns>Тело нового документа.</returns>
public virtual Stream Build(List<Page> pages)
{
var outputStream = new MemoryStream();
var document = new Aspose.Pdf.Document();
foreach (var page in pages)
document.Pages.Add(this.GetAsposePage(page));
var pageEditor = this.SetAsposeDocumentPageRotations(document, pages);
pageEditor.Save(outputStream);
return outputStream;
}
/// <summary>
/// Получить Aspose страницу.
/// </summary>
/// <param name="page">Страница.</param>
/// <returns>Aspose страница.</returns>
public virtual Aspose.Pdf.Page GetAsposePage(Page page)
{
if (!this.SourceDocuments.ContainsKey(page.DocumentId))
throw new ArgumentException(string.Format("Builder {0}. Source document with id {1} not found.", this.Guid, page.DocumentId));
var document = this.SourceDocuments[page.DocumentId];
if (document.Pages.Count < page.Number + 1)
throw new IndexOutOfRangeException(string.Format("Builder {0}. Source document with id {1}. Page number {2} is out of range.", this.Guid, page.DocumentId, page.Number + 1));
return document.Pages[page.Number + 1];
}
/// <summary>
/// Задать повороты страниц в Pdf документе.
/// </summary>
/// <param name="document">Pdf документ.</param>
/// <param name="pages">Страницы.</param>
/// <returns>Редактор страниц Pdf документа.</returns>
public virtual Aspose.Pdf.Facades.PdfPageEditor SetAsposeDocumentPageRotations(Aspose.Pdf.Document document, List<Page> pages)
{
var index = 1;
var rotationAngleStep = this.GetRotationAngleStep();
var pageRotations = pages.ToDictionary(x => index++, x => x.Rotation * rotationAngleStep);
var pagePacker = new Aspose.Pdf.Facades.PdfPageEditor(document);
pagePacker.PageRotations = pageRotations;
return pagePacker;
}
/// <summary>
/// Получить шаг угла поворота страницы.
/// </summary>
/// <returns>Шаг угла поворота страницы.</returns>
public virtual int GetRotationAngleStep()
{
return RotationAngleStep;
}
/// <summary>
/// Инициализирует новый экземпляр класса <see cref="PdfBuilder"/>
/// </summary>
public PdfBuilder()
{
this.Guid = System.Guid.NewGuid();
this.SourceDocuments = new Dictionary<long, Aspose.Pdf.Document>();
}
}
/// <summary>
/// Страница.
/// </summary>
public class Page
{
/// <summary>
/// ИД документа.
/// </summary>
public int DocumentId { get; set; }
/// <summary>
/// Номер.
/// </summary>
public int Number { get; set; }
/// <summary>
/// Поворот.
/// </summary>
/// <remarks>Количество поворотов на 90 градусов. Положительные значения - по часовой стрелке, отрицательные - против.</remarks>
public int Rotation { get; set; }
/// <summary>
/// Инициализирует новый экземпляр класса <see cref="Page" />
/// </summary>
/// <param name="documentId">ИД документа.</param>
/// <param name="number">Номер.</param>
/// <param name="pageRotation">Поворот.</param>
public Page(int documentId, int number, int pageRotation)
{
this.DocumentId = documentId;
this.Number = number;
this.Rotation = pageRotation;
}
}
}