• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

djsuperchief / Kyameru / 8401706343

23 Mar 2024 12:18PM UTC coverage: 89.113% (-7.0%) from 96.15%
8401706343

push

github

web-flow
Merge pull request #104 from djsuperchief/103-release-config

103 release config

308 of 387 branches covered (79.59%)

Branch coverage included in aggregate %.

1812 of 1992 relevant lines covered (90.96%)

21.98 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

85.12
/source/components/Kyameru.Component.File/Implementation/FileTo.cs
1
using System;
2
using System.Collections.Generic;
3
using System.IO;
4
using System.Threading;
5
using System.Threading.Tasks;
6
using Kyameru.Component.File.Utilities;
7
using Kyameru.Core.Entities;
8
using Microsoft.Extensions.Logging;
9

10
namespace Kyameru.Component.File
11
{
12
    /// <summary>
13
    /// To Component.
14
    /// </summary>
15
    public class FileTo : IFileTo
16
    {
17
        /// <summary>
18
        /// Valid actions
19
        /// </summary>
20
        private readonly Dictionary<string, Action<Routable>> toActions = new Dictionary<string, Action<Routable>>();
15✔
21

22
        private readonly Dictionary<string, Func<Routable, CancellationToken, Task>> toActionsAsync =
15✔
23
            new Dictionary<string, Func<Routable, CancellationToken, Task>>();
15✔
24

25
        /// <summary>
26
        /// Valid headers
27
        /// </summary>
28
        private readonly Dictionary<string, string> headers;
29

30
        /// <summary>
31
        /// File utilities.
32
        /// </summary>
33
        /// <remarks>
34
        /// To allow testing of all code paths.
35
        /// </remarks>
36
        private readonly IFileUtils fileUtils;
37

38
        /// <summary>
39
        /// Value indicating whether the overwrite facility should be used.
40
        /// </summary>
41
        private readonly bool overwrite;
42

43
        /// <summary>
44
        /// Initializes a new instance of the <see cref="FileTo"/> class.
45
        /// </summary>
46
        /// <param name="incomingHeaders">Incoming headers.</param>
47
        public FileTo(Dictionary<string, string> incomingHeaders, IFileUtils fileUtils)
15✔
48
        {
15✔
49
            SetupInternalActions();
15✔
50
            headers = incomingHeaders.ToToConfig();
15✔
51
            this.fileUtils = fileUtils;
15✔
52
            overwrite = bool.Parse(headers["Overwrite"]);
15✔
53
        }
15✔
54

55
        /// <summary>
56
        /// Log event.
57
        /// </summary>
58
        public event EventHandler<Log> OnLog;
59

60
        /// <summary>
61
        /// Process the message.
62
        /// </summary>
63
        /// <param name="item">Message to process.</param>
64
        public void Process(Routable item)
65
        {
9✔
66
            toActions[headers["Action"]](item);
9✔
67
        }
9✔
68

69
        public async Task ProcessAsync(Routable item, CancellationToken cancellationToken)
70
        {
5✔
71
            await toActionsAsync[headers["Action"]](item, cancellationToken);
5✔
72
            
73
        }
5✔
74

75
        /// <summary>
76
        /// Sets up internal delegates.
77
        /// </summary>
78
        private void SetupInternalActions()
79
        {
15✔
80
            toActions.Add("Move", MoveFile);
15✔
81
            toActionsAsync.Add("Move", MoveFileAsync);
15✔
82
            toActions.Add("Copy", CopyFile);
15✔
83
            toActionsAsync.Add("Copy", this.CopyFileAsync);
15✔
84
            toActions.Add("Delete", DeleteFile);
15✔
85
            toActionsAsync.Add("Delete", DeleteFileAsync);
15✔
86
            toActions.Add("Write", WriteFile);
15✔
87
            toActionsAsync.Add("Write", WriteFileAsync);
15✔
88
        }
15✔
89

90

91

92

93
        /// <summary>
94
        /// Abstraction for logging event.
95
        /// </summary>
96
        /// <param name="logLevel">Log level to raise.</param>
97
        /// <param name="message">Log message.</param>
98
        /// <param name="exception">Log exception.</param>
99
        private void Log(LogLevel logLevel, string message, Exception exception = null)
100
        {
22✔
101
            OnLog?.Invoke(this, new Log(logLevel, message, exception));
22!
102
        }
22✔
103

104
        /// <summary>
105
        /// Writes a file to disk.
106
        /// </summary>
107
        /// <param name="item">Message to process.</param>
108
        private void WriteFile(Routable item)
109
        {
3✔
110
            Log(LogLevel.Information, string.Format(Resources.INFO_ACTION_WRITE, item.Headers["SourceFile"]));
3✔
111
            try
112
            {
3✔
113
                EnsureDestinationExists();
3✔
114
                if (item.Headers["DataType"] == "String")
3✔
115
                {
1✔
116
                    fileUtils.WriteAllText(GetDestination(item.Headers["SourceFile"]), (string)item.Body, overwrite);
1✔
117
                }
1✔
118
                else
119
                {
1✔
120
                    fileUtils.WriteAllBytes(GetDestination(item.Headers["SourceFile"]), (byte[])item.Body, overwrite);
1✔
121
                }
1✔
122

123
                DeleteFile(item);
2✔
124
            }
2✔
125
            catch (Exception ex)
1✔
126
            {
1✔
127
                Log(LogLevel.Error, Resources.ERROR_ACTION_WRITE, ex);
1✔
128
                item.SetInError(RaiseError("WriteFile", "Error writing file"));
1✔
129
            }
1✔
130
        }
3✔
131

132
        private async Task WriteFileAsync(Routable item, CancellationToken cancellationToken)
133
        {
2✔
134
            Log(LogLevel.Information, string.Format(Resources.INFO_ACTION_WRITE, item.Headers["SourceFile"]));
2✔
135
            try
136
            {
2✔
137
                await EnsureDestinationExistsAsync(cancellationToken);
2✔
138
                if (item.Headers["DataType"] == "String")
2✔
139
                {
1✔
140
                    await fileUtils.WriteAllTextAsync(GetDestination(item.Headers["SourceFile"]),
1✔
141
                        (string)item.Body, overwrite, cancellationToken);
1✔
142
                }
1✔
143
                else
144
                {
1✔
145
                    await fileUtils.WriteAllBytesAsync(GetDestination(item.Headers["SourceFile"]),
1✔
146
                        (byte[])item.Body, overwrite, cancellationToken);
1✔
147
                }
1✔
148

149
                DeleteFile(item);
2✔
150
            }
2✔
151
            catch (Exception ex)
×
152
            {
×
153
                Log(LogLevel.Error, Resources.ERROR_ACTION_WRITE, ex);
×
154
                item.SetInError(RaiseError("WriteFile", "Error writing file"));
×
155
            }
×
156
        }
2✔
157

158
        /// <summary>
159
        /// Moves a file.
160
        /// </summary>
161
        /// <param name="item">Message to process.</param>
162
        private void MoveFile(Routable item)
163
        {
2✔
164
            Log(LogLevel.Information, string.Format(Resources.INFO_ACTION_MOVE, item.Headers["SourceFile"]));
2✔
165
            try
166
            {
2✔
167
                EnsureDestinationExists();
2✔
168
                fileUtils.Move(item.Headers["FullSource"], GetDestination(item.Headers["SourceFile"]), overwrite);
2✔
169
            }
1✔
170
            catch (Exception ex)
1✔
171
            {
1✔
172
                Log(LogLevel.Error, Resources.ERROR_ACTION_MOVE, ex);
1✔
173
                item.SetInError(RaiseError("MoveFile", "Error writing file"));
1✔
174
            }
1✔
175
        }
2✔
176

177
        private async Task MoveFileAsync(Routable item, CancellationToken cancellationToken)
178
        {
1✔
179
            Log(LogLevel.Information, string.Format(Resources.INFO_ACTION_MOVE, item.Headers["SourceFile"]));
1✔
180
            try
181
            {
1✔
182
                await EnsureDestinationExistsAsync(cancellationToken);
1✔
183
                await fileUtils.MoveAsync(item.Headers["FullSource"], GetDestination(item.Headers["SourceFile"]), overwrite, cancellationToken);
1✔
184
            }
1✔
185
            catch (Exception ex)
×
186
            {
×
187
                Log(LogLevel.Error, Resources.ERROR_ACTION_MOVE, ex);
×
188
                item.SetInError(RaiseError("MoveFile", "Error writing file"));
×
189
            }
×
190
        }
1✔
191

192
        /// <summary>
193
        /// Ensures destination folder exists.
194
        /// </summary>
195
        private void EnsureDestinationExists()
196
        {
7✔
197
            if (!Directory.Exists(headers["Target"]))
7✔
198
            {
1✔
199
                fileUtils.CreateDirectory(headers["Target"]);
1✔
200
            }
1✔
201
        }
7✔
202

203
        private async Task EnsureDestinationExistsAsync(CancellationToken cancellationToken)
204
        {
4✔
205
            if (!Directory.Exists(headers["Target"]))
4!
206
            {
×
207
                await fileUtils.CreateDirectoryAsync(headers["Target"], cancellationToken);
×
208
            }
×
209
        }
4✔
210

211
        /// <summary>
212
        /// Copies the source file but leaves original in place.
213
        /// </summary>
214
        /// <param name="item">Message to process.</param>
215
        private void CopyFile(Routable item)
216
        {
2✔
217
            Log(LogLevel.Information, string.Format(Resources.INFO_ACTION_COPY, item.Headers["SourceFile"]));
2✔
218
            try
219
            {
2✔
220
                EnsureDestinationExists();
2✔
221
                fileUtils.CopyFile(item.Headers["FullSource"], GetDestination(item.Headers["SourceFile"]), overwrite);
2✔
222
            }
1✔
223
            catch (Exception ex)
1✔
224
            {
1✔
225
                Log(LogLevel.Error, Resources.ERROR_ACTION_COPY, ex);
1✔
226
                item.SetInError(RaiseError("CopyFile", "Error writing file"));
1✔
227
            }
1✔
228
        }
2✔
229
        
230
        private async Task CopyFileAsync(Routable item, CancellationToken cancellationToken)
231
        {
1✔
232
            Log(LogLevel.Information, string.Format(Resources.INFO_ACTION_COPY, item.Headers["SourceFile"]));
1✔
233
            try
234
            {
1✔
235
                await EnsureDestinationExistsAsync(cancellationToken);
1✔
236
                await fileUtils.CopyFileAsync(item.Headers["FullSource"], GetDestination(item.Headers["SourceFile"]),
1✔
237
                    overwrite, cancellationToken);
1✔
238
            }
1✔
239
            catch (Exception ex)
×
240
            {
×
241
                Log(LogLevel.Error, Resources.ERROR_ACTION_COPY, ex);
×
242
                item.SetInError(RaiseError("CopyFile", "Error writing file"));
×
243
            }
×
244
        }
1✔
245

246
        /// <summary>
247
        /// Deletes source file.
248
        /// </summary>
249
        /// <param name="item">Message to process.</param>
250
        private void DeleteFile(Routable item)
251
        {
6✔
252
            Log(LogLevel.Information, string.Format(Resources.INFO_ACTION_DELETE, item.Headers["SourceFile"]));
6✔
253
            try
254
            {
6✔
255
                fileUtils.Delete(item.Headers["FullSource"]);
6✔
256
            }
5✔
257
            catch (Exception ex)
1✔
258
            {
1✔
259
                Log(LogLevel.Error, Resources.ERROR_ACTION_DELETE, ex);
1✔
260
                item.SetInError(RaiseError("DeleteError", "Error writing file"));
1✔
261
            }
1✔
262
        }
6✔
263
        
264
        private async Task DeleteFileAsync(Routable item, CancellationToken cancellationToken)
265
        {
1✔
266
            Log(LogLevel.Information, string.Format(Resources.INFO_ACTION_DELETE, item.Headers["SourceFile"]));
1✔
267
            try
268
            {
1✔
269
                await fileUtils.DeleteAsync(item.Headers["FullSource"], cancellationToken);
1✔
270
            }
1✔
271
            catch (Exception ex)
×
272
            {
×
273
                Log(LogLevel.Error, Resources.ERROR_ACTION_DELETE, ex);
×
274
                item.SetInError(RaiseError("DeleteError", "Error writing file"));
×
275
            }
×
276
        }
1✔
277

278
        /// <summary>
279
        /// Constructs the destination.
280
        /// </summary>
281
        /// <param name="filename">Source file.</param>
282
        /// <returns>Returns a valid destination for the file.</returns>
283
        private string GetDestination(string filename)
284
        {
10✔
285
            return Path.Combine(headers["Target"], filename);
10✔
286
        }
10✔
287

288
        /// <summary>
289
        /// Raises an error object.
290
        /// </summary>
291
        /// <param name="action">Current action.</param>
292
        /// <param name="message">Error message.</param>
293
        /// <returns>Returns a new instance of the <see cref="Error"/> object.</returns>
294
        private Error RaiseError(string action, string message)
295
        {
4✔
296
            return new Error("ToFile", action, message);
4✔
297
        }
4✔
298
    }
299
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc