Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
ConsolidatedTable.cs
1using System;
2using System.Collections.Generic;
3using System.Text;
4using System.Threading;
5using System.Threading.Tasks;
9
11{
15 public class ConsolidatedTable
16 {
17 private string caption;
18 private string id;
19 private int nrColumns;
20 private int nrHeaderRows;
21 private int nrCellRows;
22 private readonly Dictionary<string, int> columnIndices = new Dictionary<string, int>();
23 private readonly Dictionary<long, MarkdownElement> headers = new Dictionary<long, MarkdownElement>();
24 private readonly Dictionary<long, MarkdownElement> cells = new Dictionary<long, MarkdownElement>();
25 private readonly Dictionary<long, TextAlignment?> headerAlignments = new Dictionary<long, TextAlignment?>();
26 private readonly Dictionary<long, TextAlignment?> cellAlignments = new Dictionary<long, TextAlignment?>();
27 private readonly Dictionary<int, TextAlignment> columnAlignments = new Dictionary<int, TextAlignment>();
28 private readonly Dictionary<int, string> sources = new Dictionary<int, string>();
29 private readonly SemaphoreSlim synchObj = new SemaphoreSlim(1);
30
35 private ConsolidatedTable(Table MarkdownTable)
36 {
37 this.nrColumns = MarkdownTable.Columns;
38 this.nrHeaderRows = MarkdownTable.Headers.Length;
39 this.nrCellRows = MarkdownTable.Rows.Length;
40 this.caption = MarkdownTable.Caption;
41 this.id = MarkdownTable.Id;
42 }
43
50 public static async Task<ConsolidatedTable> CreateAsync(string Source, Table MarkdownTable)
51 {
52 ConsolidatedTable Result = new ConsolidatedTable(MarkdownTable);
53 MarkdownElement[] Row;
54 TextAlignment?[] CellAlignments;
55 int RowIndex, NrRows;
56 int ColumnIndex, NrColumns = MarkdownTable.Columns;
57 long l;
58
59 for (ColumnIndex = 0; ColumnIndex < NrColumns; ColumnIndex++)
60 {
61 Result.columnIndices[await Result.GetHeaderKey(MarkdownTable.Headers, ColumnIndex)] = ColumnIndex;
62 Result.columnAlignments[ColumnIndex] = MarkdownTable.ColumnAlignments[ColumnIndex];
63 }
64
65 for (RowIndex = 0, NrRows = MarkdownTable.Headers.Length; RowIndex < NrRows; RowIndex++)
66 {
67 Row = MarkdownTable.Headers[RowIndex];
68 CellAlignments = MarkdownTable.HeaderCellAlignments[RowIndex];
69
70 for (ColumnIndex = 0; ColumnIndex < NrColumns; ColumnIndex++)
71 {
72 l = (((long)RowIndex) << 32) + ColumnIndex;
73 Result.headers[l] = Row[ColumnIndex];
74 Result.headerAlignments[l] = CellAlignments[ColumnIndex];
75 }
76 }
77
78 for (RowIndex = 0, NrRows = MarkdownTable.Headers.Length; RowIndex < NrRows; RowIndex++)
79 {
80 Row = MarkdownTable.Rows[RowIndex];
81 CellAlignments = MarkdownTable.RowCellAlignments[RowIndex];
82
83 for (ColumnIndex = 0; ColumnIndex < NrColumns; ColumnIndex++)
84 {
85 l = (((long)RowIndex) << 32) + ColumnIndex;
86 Result.cells[l] = Row[ColumnIndex];
87 Result.cellAlignments[l] = CellAlignments[ColumnIndex];
88 }
89
90 Result.sources[ColumnIndex] = Source;
91 }
92
93 return Result;
94 }
95
96 private async Task<string> GetHeaderKey(MarkdownElement[][] Headers, int ColumnIndex)
97 {
98 StringBuilder sb = new StringBuilder();
99 bool First = true;
100
101 foreach (MarkdownElement[] Row in Headers)
102 {
103 if (First)
104 First = false;
105 else
106 sb.AppendLine();
107
108 if (ColumnIndex < Row.Length)
109 await Row[ColumnIndex].GenerateMarkdown(sb);
110 }
111
112 return sb.ToString();
113 }
114
118 public Task<int> NrColumns => this.GetNrColumns();
119
124 public async Task<int> GetNrColumns()
125 {
126 await this.synchObj.WaitAsync();
127 try
128 {
129 return this.nrColumns;
130 }
131 finally
132 {
133 this.synchObj.Release();
134 }
135 }
136
140 public Task<int> NrHeaderRows => this.GetNrHeaderRows();
141
146 public async Task<int> GetNrHeaderRows()
147 {
148 await this.synchObj.WaitAsync();
149 try
150 {
151 return this.nrHeaderRows;
152 }
153 finally
154 {
155 this.synchObj.Release();
156 }
157 }
158
162 public Task<int> NrCellRows => this.GetNrCellRows();
163
168 public async Task<int> GetNrCellRows()
169 {
170 await this.synchObj.WaitAsync();
171 try
172 {
173 return this.nrCellRows;
174 }
175 finally
176 {
177 this.synchObj.Release();
178 }
179 }
180
186 public async Task<TextAlignment> GetAlignment(int Column)
187 {
188 await this.synchObj.WaitAsync();
189 try
190 {
191 if (Column < 0 || Column > this.nrColumns)
192 throw new ArgumentOutOfRangeException("Invalid column.", nameof(Column));
193
194 return this.columnAlignments.TryGetValue(Column, out TextAlignment Alignment) ? Alignment : TextAlignment.Left;
195 }
196 finally
197 {
198 this.synchObj.Release();
199 }
200 }
201
207 public async Task Add(string Source, Table MarkdownTable)
208 {
209 await this.synchObj.WaitAsync();
210 try
211 {
212 if (this.caption != MarkdownTable.Caption)
213 this.caption = string.Empty;
214
215 if (this.id != MarkdownTable.Id)
216 this.id = string.Empty;
217
218 if (MarkdownTable.Headers.Length > this.nrHeaderRows)
219 this.nrHeaderRows = MarkdownTable.Headers.Length;
220
221 MarkdownElement[] Row;
222 TextAlignment?[] CellAlignments;
223 int[] Indices = new int[MarkdownTable.Columns];
224 int i, i2, j, j2;
225 int RowIndex, NrRows;
226 long l;
227 string Key;
228
229 i = 0;
230 foreach (TextAlignment Alignment in MarkdownTable.ColumnAlignments)
231 {
232 Key = await this.GetHeaderKey(MarkdownTable.Headers, i);
233
234 if (!this.columnIndices.TryGetValue(Key, out i2))
235 {
236 i2 = this.nrColumns++;
237 this.columnIndices[Key] = i2;
238 this.columnAlignments[i2] = Alignment;
239
240 for (RowIndex = 0, NrRows = MarkdownTable.Headers.Length; RowIndex < NrRows; RowIndex++)
241 {
242 Row = MarkdownTable.Headers[RowIndex];
243 CellAlignments = MarkdownTable.HeaderCellAlignments[RowIndex];
244
245 l = (((long)RowIndex) << 32) + i2;
246 this.headers[l] = Row[i];
247 this.headerAlignments[l] = CellAlignments[i];
248 }
249 }
250
251 Indices[i++] = i2;
252 }
253
254 i = 0;
255 i2 = this.nrCellRows;
256
257 this.nrCellRows += MarkdownTable.Rows.Length;
258
259 for (RowIndex = 0, NrRows = MarkdownTable.Rows.Length; RowIndex < NrRows; RowIndex++)
260 {
261 Row = MarkdownTable.Rows[RowIndex];
262 CellAlignments = MarkdownTable.RowCellAlignments[RowIndex];
263
264 j = 0;
265 foreach (MarkdownElement Element in Row)
266 {
267 j2 = Indices[j];
268 l = (((long)i2) << 32) + j2;
269 this.cells[l] = Element;
270 this.cellAlignments[l] = CellAlignments[j];
271 j++;
272 }
273
274 i++;
275 this.sources[i2++] = Source;
276 }
277 }
278 finally
279 {
280 this.synchObj.Release();
281 }
282 }
283
288 public async Task Export(StringBuilder Markdown)
289 {
290 await this.synchObj.WaitAsync();
291 try
292 {
293 TextAlignment? CellAlignment;
294 long l;
295 int i, j;
296
297 for (i = 0; i < this.nrHeaderRows; i++)
298 {
299 Markdown.Append("| Nr | Source |");
300
301 for (j = 0; j < this.nrColumns; j++)
302 {
303 l = (((long)i) << 32) + j;
304
305 if (!this.headerAlignments.TryGetValue(l, out CellAlignment))
306 CellAlignment = null;
307
308 if (this.headers.TryGetValue(l, out MarkdownElement E))
309 {
310 if (E is null)
311 Markdown.Append('|');
312 else
313 {
314 Markdown.Append(' ');
315
316 if (CellAlignment.HasValue)
317 {
318 switch (CellAlignment.Value)
319 {
320 case TextAlignment.Left:
321 Markdown.Append("<<");
322 await E.GenerateMarkdown(Markdown);
323 break;
324
325 case TextAlignment.Center:
326 Markdown.Append(">>");
327 await E.GenerateMarkdown(Markdown);
328 Markdown.Append("<<");
329 break;
330
331 case TextAlignment.Right:
332 await E.GenerateMarkdown(Markdown);
333 Markdown.Append(">>");
334 break;
335
336 default:
337 await E.GenerateMarkdown(Markdown);
338 break;
339 }
340 }
341 else
342 await E.GenerateMarkdown(Markdown);
343
344 Markdown.Append(" |");
345 }
346 }
347 else
348 Markdown.Append(" |");
349 }
350
351 Markdown.AppendLine();
352 }
353
354 Markdown.Append("|--:|:--|");
355
356 for (j = 0; j < this.nrColumns; j++)
357 {
358 if (!this.columnAlignments.TryGetValue(j, out TextAlignment Alignment))
359 Alignment = TextAlignment.Left;
360
361 switch (Alignment)
362 {
363 case TextAlignment.Left:
364 Markdown.Append(":--|");
365 break;
366
367 case TextAlignment.Right:
368 Markdown.Append("--:|");
369 break;
370
371 case TextAlignment.Center:
372 Markdown.Append(":-:|");
373 break;
374
375 default:
376 Markdown.Append("---|");
377 break;
378 }
379 }
380
381 Markdown.AppendLine();
382
383 for (i = 0; i < this.nrCellRows; i++)
384 {
385 Markdown.Append("| ");
386 Markdown.Append((i + 1).ToString());
387 Markdown.Append(" | `");
388
389 if (this.sources.TryGetValue(i, out string Source))
390 Markdown.Append(Source);
391
392 Markdown.Append("` |");
393
394 for (j = 0; j < this.nrColumns; j++)
395 {
396 l = (((long)i) << 32) + j;
397
398 if (!this.cellAlignments.TryGetValue(l, out CellAlignment))
399 CellAlignment = null;
400
401 if (this.cells.TryGetValue(l, out MarkdownElement E))
402 {
403 if (E is null)
404 Markdown.Append('|');
405 else
406 {
407 Markdown.Append(' ');
408
409 if (CellAlignment.HasValue)
410 {
411 switch (CellAlignment.Value)
412 {
413 case TextAlignment.Left:
414 Markdown.Append("<<");
415 await E.GenerateMarkdown(Markdown);
416 break;
417
418 case TextAlignment.Center:
419 Markdown.Append(">>");
420 await E.GenerateMarkdown(Markdown);
421 Markdown.Append("<<");
422 break;
423
424 case TextAlignment.Right:
425 await E.GenerateMarkdown(Markdown);
426 Markdown.Append(">>");
427 break;
428
429 default:
430 await E.GenerateMarkdown(Markdown);
431 break;
432 }
433 }
434 else
435 await E.GenerateMarkdown(Markdown);
436
437 Markdown.Append(" |");
438 }
439 }
440 else
441 Markdown.Append(" |");
442 }
443
444 Markdown.AppendLine();
445 }
446 }
447 finally
448 {
449 this.synchObj.Release();
450 }
451 }
452
453 }
454}
async Task Export(StringBuilder Markdown)
Exports the consolidated table to Markdown.
async Task< TextAlignment > GetAlignment(int Column)
Gets the alignment of a column.
async Task< int > GetNrColumns()
Gets the number of columns.
async Task< int > GetNrCellRows()
Gets the number of cell rows.
async Task Add(string Source, Table MarkdownTable)
Adds data from a Markdown table to the consolidated table.
static async Task< ConsolidatedTable > CreateAsync(string Source, Table MarkdownTable)
Creates a consolidated table.
async Task< int > GetNrHeaderRows()
Gets the number of header rows.
Represents a table in a markdown document.
Definition: Table.cs:11
TextAlignment[] ColumnAlignments
Table column alignments.
Definition: Table.cs:64
MarkdownElement[][] Headers
Headers in table.
Definition: Table.cs:54
TextAlignment?[][] RowCellAlignments
Row cell alignments in table.
Definition: Table.cs:79
TextAlignment?[][] HeaderCellAlignments
Header cell alignments in table.
Definition: Table.cs:74
MarkdownElement[][] Rows
Rows in table.
Definition: Table.cs:59
Abstract base class for all markdown elements.
TextAlignment
Text alignment of contents.