-
Notifications
You must be signed in to change notification settings - Fork 0
/
ParquetStorage.cs
135 lines (118 loc) · 4.05 KB
/
ParquetStorage.cs
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
using Microsoft.Extensions.Logging;
using Parquet;
using System;
using System.Collections.Generic;
using System.IO;
using TeleScope.Logging;
using TeleScope.Logging.Extensions;
using TeleScope.Persistence.Abstractions;
using TeleScope.Persistence.Abstractions.Enumerations;
using TeleScope.Persistence.Abstractions.Extensions;
namespace TeleScope.Persistence.Parquet
{
/// <summary>
/// This class provides access to Parquet files and parses the data into the application-side type T.
/// </summary>
/// <typeparam name="T">The type T is used application-side and can be read from the data source
/// or be written to the data sink.</typeparam>
public class ParquetStorage<T> : IReadable<T>, IFileWritable<T> where T : new()
{
// -- fields
private readonly ILogger<ParquetStorage<T>> log;
private readonly ParquetStorageSetup setup;
// -- properties
/// <summary>
/// Gets the flags of permissions how files may be treated.
/// </summary>
public WritePermissions Permissions => setup.Permissions;
// -- constructor
/// <summary>
/// The constructor takes the file string as input parameter,
/// creates the <see cref="ParquetStorageSetup"/> and allows to config the properties afterwards.
/// </summary>
/// <param name="file">The specific Parquet file that the storage is related to.</param>
public ParquetStorage(string file)
: this(new ParquetStorageSetup(file))
{
}
/// <summary>
/// The constructor takes the setup of type <see cref="ParquetStorageSetup"/> as input parameter
/// and binds the logging mechanism.
/// </summary>
/// <param name="parquetSetup">The setup is needed to work with a specific Parquet file.</param>
public ParquetStorage(ParquetStorageSetup parquetSetup) : this()
{
setup = parquetSetup ?? throw new ArgumentNullException(nameof(parquetSetup));
}
private ParquetStorage()
{
log = LoggingProvider.CreateLogger<ParquetStorage<T>>();
}
// -- methods
/// <summary>
/// Checks if the permission is a present flag or not.
/// </summary>
/// <param name="permission">The enum that is checked.</param>
/// <returns>True if the value is a present flag, otherwise false.</returns>
public bool HasPermission(WritePermissions permission)
{
return Permissions.HasFlag(permission);
}
/// <summary>
/// Reads a given Parquet file as data source and provides a collection of type T.
/// If there is only one data object a collection with the length one is returned.
/// </summary>
/// <returns>The resulting data objects of type T.</returns>
public IEnumerable<T> Read()
{
T[] data;
using (var stream = new FileStream(setup.File, FileMode.Open))
{
data = ParquetConvert.Deserialize<T>(stream);
}
return data;
}
/// <summary>
/// Writes a collection of type T to a Parquet file as data sink.
/// If there is only one data object there is the need to provide a collection with one element.
/// If the collection has only one element the Parquet file won't have an array as root element.
/// </summary>
/// <param name="data">The application-side data collection of type T.</param>
public void Write(IEnumerable<T> data)
{
try
{
if (!this.ValidateOrThrow(data, setup.Info()))
{
return;
}
ParquetConvert.Serialize(data, setup.File);
}
catch (InvalidOperationException ex)
{
log.Critical(ex);
}
}
/// <summary>
/// Updates the reference to the internal <see cref="FileInfo"/> instance
/// so that the data sink can be updated.
/// </summary>
/// <param name="file">The new string of the file.</param>
/// <returns>The calling instance.</returns>
public IFileWritable<T> Update(string file)
{
return Update(new FileInfo(file));
}
/// <summary>
/// Updates the reference to the internal <see cref="FileInfo"/> instance
/// so that the data sink can be updated.
/// </summary>
/// <param name="fileInfo">The new FileInfo object.</param>
/// <returns>The calling instance.</returns>
public IFileWritable<T> Update(FileInfo fileInfo)
{
setup.SetFile(fileInfo);
return this;
}
}
}