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

HicServices / RDMP / 6237307473

19 Sep 2023 04:02PM UTC coverage: 57.015% (-0.4%) from 57.44%
6237307473

push

github

web-flow
Feature/rc4 (#1570)

* Syntax tidying
* Dependency updates
* Event handling singletons (ThrowImmediately and co)

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: James A Sutherland <>
Co-authored-by: James Friel <jfriel001@dundee.ac.uk>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

10734 of 20259 branches covered (0.0%)

Branch coverage included in aggregate %.

5922 of 5922 new or added lines in 565 files covered. (100.0%)

30687 of 52390 relevant lines covered (58.57%)

7361.8 hits per line

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

57.14
/Rdmp.Core/ReusableLibraryCode/Settings/RDMPApplicationSettings.cs
1
// Copyright (c) The University of Dundee 2018-2019
2
// This file is part of the Research Data Management Platform (RDMP).
3
// RDMP is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
4
// RDMP is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
5
// You should have received a copy of the GNU General Public License along with RDMP. If not, see <https://www.gnu.org/licenses/>.
6

7
using System;
8
using System.IO;
9
using System.IO.IsolatedStorage;
10
using System.Linq;
11

12
namespace Rdmp.Core.ReusableLibraryCode.Settings;
13

14
internal sealed class RDMPApplicationSettings
15
{
16
    private readonly IsolatedStorageFile store;
17
    private readonly object locker = new();
4✔
18

19
    public RDMPApplicationSettings()
4✔
20
    {
21
        try
22
        {
23
            store = IsolatedStorageFile.GetUserStoreForApplication();
4✔
24
        }
4✔
25
        catch (Exception)
×
26
        {
27
            store = IsolatedStorageFile.GetUserStoreForAssembly();
×
28
        }
×
29
    }
4✔
30

31
    /// <summary>
32
    /// Add or Update
33
    /// </summary>
34
    /// <typeparam name="T"></typeparam>
35
    /// <param name="key"></param>
36
    /// <param name="value"></param>
37
    /// <returns></returns>
38
    private bool AddOrUpdateValueInternal<T>(string key, T value)
39
    {
40
        if (value == null)
3,646!
41
        {
42
            Remove(key);
×
43

44
            return true;
×
45
        }
46

47
        var type = value.GetType();
3,646✔
48

49
        if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
3,646!
50
            type = type.GenericTypeArguments.FirstOrDefault() ??
×
51
                   throw new ArgumentException($"Unable to retrieve type of Nullable {value}");
×
52

53

54
        if (type != typeof(string) &&
3,646!
55
            type != typeof(decimal) &&
3,646✔
56
            type != typeof(double) &&
3,646✔
57
            type != typeof(float) &&
3,646✔
58
            type != typeof(DateTime) &&
3,646✔
59
            type != typeof(Guid) &&
3,646✔
60
            type != typeof(bool) &&
3,646✔
61
            type != typeof(int) &&
3,646✔
62
            type != typeof(long) &&
3,646✔
63
            type != typeof(byte)) throw new ArgumentException($"Value of type {type.Name} is not supported.");
3,646✔
64

65
        lock (locker)
3,646!
66
        {
67
            string str;
68

69
            switch (value)
70
            {
71
                case decimal:
72
                    return AddOrUpdateValue(key,
×
73
                        Convert.ToString(Convert.ToDecimal(value), System.Globalization.CultureInfo.InvariantCulture));
×
74
                case DateTime:
75
                    return AddOrUpdateValue(key,
×
76
                        Convert.ToString(-Convert.ToDateTime(value).ToUniversalTime().Ticks,
×
77
                            System.Globalization.CultureInfo.InvariantCulture));
×
78
                default:
79
                    str = Convert.ToString(value, System.Globalization.CultureInfo.InvariantCulture);
3,646✔
80
                    break;
81
            }
82

83
            string oldValue = null;
3,646✔
84

85
            if (store.FileExists(key))
3,646✔
86
            {
87
                using var stream = store.OpenFile(key, FileMode.Open);
3,536✔
88
                using var sr = new StreamReader(stream);
3,536✔
89
                oldValue = sr.ReadToEnd();
3,536✔
90
            }
91

92
            using (var stream = store.OpenFile(key, FileMode.Create, FileAccess.Write))
3,646✔
93
            {
94
                using var sw = new StreamWriter(stream);
3,646✔
95
                sw.Write(str);
3,646✔
96
            }
97

98
            return oldValue != str;
3,646✔
99
        }
100
    }
3,646✔
101

102
    /// <summary>
103
    /// Get Value
104
    /// </summary>
105
    /// <typeparam name="T"></typeparam>
106
    /// <param name="key"></param>
107
    /// <param name="defaultValue"></param>
108
    /// <returns></returns>
109
    private T GetValueOrDefaultInternal<T>(string key, T defaultValue = default)
110
    {
111
        object value = null;
33,373✔
112
        lock (locker)
33,373✔
113
        {
114
            try
115
            {
116
                string str = null;
33,373✔
117

118
                // If the key exists, retrieve the value.
119
                if (store.FileExists(key))
33,373✔
120
                {
121
                    using var stream = store.OpenFile(key, FileMode.Open);
401✔
122
                    using var sr = new StreamReader(stream);
401✔
123
                    str = sr.ReadToEnd();
401✔
124
                }
125

126
                if (str == null)
33,373✔
127
                    return defaultValue;
32,972✔
128

129
                var type = typeof(T);
401✔
130

131
                if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
401!
132
                    type = type.GenericTypeArguments.FirstOrDefault();
×
133

134
                if (type == typeof(string))
401✔
135
                {
136
                    value = str;
26✔
137
                }
138

139
                else if (type == typeof(decimal))
375!
140
                {
141
                    var savedDecimal = Convert.ToString(str);
×
142

143

144
                    value = Convert.ToDecimal(savedDecimal, System.Globalization.CultureInfo.InvariantCulture);
×
145

146
                    return (T)value;
×
147
                }
148

149
                else if (type == typeof(double))
375!
150
                {
151
                    value = Convert.ToDouble(str, System.Globalization.CultureInfo.InvariantCulture);
×
152
                }
153

154
                else if (type == typeof(float))
375!
155
                {
156
                    value = Convert.ToSingle(str, System.Globalization.CultureInfo.InvariantCulture);
×
157
                }
158

159
                else if (type == typeof(DateTime))
375!
160
                {
161
                    var ticks = Convert.ToInt64(str, System.Globalization.CultureInfo.InvariantCulture);
×
162
                    //Old value, stored before update to UTC values
163
                    value = ticks >= 0
×
164
                        ? new DateTime(ticks)
×
165
                        :
×
166
                        //New value, UTC
×
167
                        new DateTime(-ticks, DateTimeKind.Utc);
×
168

169

170
                    return (T)value;
×
171
                }
172

173
                else if (type == typeof(Guid))
375!
174
                {
175
                    if (Guid.TryParse(str, out var guid))
×
176
                        value = guid;
×
177
                }
178

179
                else if (type == typeof(bool))
375✔
180
                {
181
                    value = Convert.ToBoolean(str, System.Globalization.CultureInfo.InvariantCulture);
327✔
182
                }
183

184
                else if (type == typeof(int))
48!
185
                {
186
                    value = Convert.ToInt32(str, System.Globalization.CultureInfo.InvariantCulture);
48✔
187
                }
188

189
                else if (type == typeof(long))
×
190
                {
191
                    value = Convert.ToInt64(str, System.Globalization.CultureInfo.InvariantCulture);
×
192
                }
193

194
                else if (type == typeof(byte))
×
195
                {
196
                    value = Convert.ToByte(str, System.Globalization.CultureInfo.InvariantCulture);
×
197
                }
198

199
                else
200
                {
201
                    throw new ArgumentException($"Value of type {type} is not supported.");
×
202
                }
203
            }
401✔
204
            catch (FormatException)
×
205
            {
206
                return defaultValue;
×
207
            }
208
        }
209

210
        return null != value ? (T)value : defaultValue;
401!
211
    }
32,972✔
212

213
    /// <summary>
214
    /// Remove key
215
    /// </summary>
216
    /// <param name="key">Key to remove</param>
217
    public void Remove(string key)
218
    {
219
        if (store.FileExists(key))
×
220
            store.DeleteFile(key);
×
221
    }
×
222

223
    /// <summary>
224
    /// Clear all keys from settings
225
    /// </summary>
226
    public void Clear()
227
    {
228
        try
229
        {
230
            foreach (var file in store.GetFileNames()) store.DeleteFile(file);
301✔
231
        }
2✔
232
        catch (Exception ex)
×
233
        {
234
            Console.WriteLine($"Unable to clear all defaults. Message: {ex.Message}");
×
235
        }
×
236
    }
2✔
237

238
    /// <summary>
239
    /// Checks to see if the key has been added.
240
    /// </summary>
241
    /// <param name="key">Key to check</param>
242
    /// <returns>True if contains key, else false</returns>
243
    public bool Contains(string key) => store.FileExists(key);
×
244

245
    #region GetValueOrDefault
246

247
    /// <summary>
248
    /// Gets the current value or the default that you specify.
249
    /// </summary>
250
    /// <param name="key">Key for settings</param>
251
    /// <param name="defaultValue">default value if not set</param>
252
    /// <param name="fileName">Name of file for settings to be stored and retrieved </param>
253
    /// <returns>Value or default</returns>
254
    public decimal GetValueOrDefault(string key, decimal defaultValue, string fileName = null) =>
255
        GetValueOrDefaultInternal(key, defaultValue);
×
256

257
    /// <summary>
258
    /// Gets the current value or the default that you specify.
259
    /// </summary>
260
    /// <param name="key">Key for settings</param>
261
    /// <param name="defaultValue">default value if not set</param>
262
    /// <param name="fileName">Name of file for settings to be stored and retrieved </param>
263
    /// <returns>Value or default</returns>
264
    public bool GetValueOrDefault(string key, bool defaultValue, string fileName = null) =>
265
        GetValueOrDefaultInternal(key, defaultValue);
31,855✔
266

267
    /// <summary>
268
    /// Gets the current value or the default that you specify.
269
    /// </summary>
270
    /// <param name="key">Key for settings</param>
271
    /// <param name="defaultValue">default value if not set</param>
272
    /// <param name="fileName">Name of file for settings to be stored and retrieved </param>
273
    /// <returns>Value or default</returns>
274
    public long GetValueOrDefault(string key, long defaultValue, string fileName = null) =>
275
        GetValueOrDefaultInternal(key, defaultValue);
×
276

277
    /// <summary>
278
    /// Gets the current value or the default that you specify.
279
    /// </summary>
280
    /// <param name="key">Key for settings</param>
281
    /// <param name="defaultValue">default value if not set</param>
282
    /// <param name="fileName">Name of file for settings to be stored and retrieved </param>
283
    /// <returns>Value or default</returns>
284
    public string GetValueOrDefault(string key, string defaultValue, string fileName = null) =>
285
        GetValueOrDefaultInternal(key, defaultValue);
116✔
286

287
    /// <summary>
288
    /// Gets the current value or the default that you specify.
289
    /// </summary>
290
    /// <param name="key">Key for settings</param>
291
    /// <param name="defaultValue">default value if not set</param>
292
    /// <param name="fileName">Name of file for settings to be stored and retrieved </param>
293
    /// <returns>Value or default</returns>
294
    public int GetValueOrDefault(string key, int defaultValue, string fileName = null) =>
295
        GetValueOrDefaultInternal(key, defaultValue);
1,402✔
296

297
    /// <summary>
298
    /// Gets the current value or the default that you specify.
299
    /// </summary>
300
    /// <param name="key">Key for settings</param>
301
    /// <param name="defaultValue">default value if not set</param>
302
    /// <param name="fileName">Name of file for settings to be stored and retrieved </param>
303
    /// <returns>Value or default</returns>
304
    public float GetValueOrDefault(string key, float defaultValue, string fileName = null) =>
305
        GetValueOrDefaultInternal(key, defaultValue);
×
306

307
    /// <summary>
308
    /// Gets the current value or the default that you specify.
309
    /// </summary>
310
    /// <param name="key">Key for settings</param>
311
    /// <param name="defaultValue">default value if not set</param>
312
    /// <param name="fileName">Name of file for settings to be stored and retrieved </param>
313
    /// <returns>Value or default</returns>
314
    public DateTime GetValueOrDefault(string key, DateTime defaultValue, string fileName = null) =>
315
        GetValueOrDefaultInternal(key, defaultValue);
×
316

317
    /// <summary>
318
    /// Gets the current value or the default that you specify.
319
    /// </summary>
320
    /// <param name="key">Key for settings</param>
321
    /// <param name="defaultValue">default value if not set</param>
322
    /// <param name="fileName">Name of file for settings to be stored and retrieved </param>
323
    /// <returns>Value or default</returns>
324
    public Guid GetValueOrDefault(string key, Guid defaultValue, string fileName = null) =>
325
        GetValueOrDefaultInternal(key, defaultValue);
×
326

327
    /// <summary>
328
    /// Gets the current value or the default that you specify.
329
    /// </summary>
330
    /// <param name="key">Key for settings</param>
331
    /// <param name="defaultValue">default value if not set</param>
332
    /// <param name="fileName">Name of file for settings to be stored and retrieved </param>
333
    /// <returns>Value or default</returns>
334
    public double GetValueOrDefault(string key, double defaultValue, string fileName = null) =>
335
        GetValueOrDefaultInternal(key, defaultValue);
×
336

337
    #endregion
338

339
    #region AddOrUpdateValue
340

341
    /// <summary>
342
    /// Adds or updates the value
343
    /// </summary>
344
    /// <param name="key">Key for setting</param>
345
    /// <param name="value">Value to set</param>
346
    /// <returns>True of was added or updated and you need to save it.</returns>
347
    public bool AddOrUpdateValue(string key, decimal value) => AddOrUpdateValueInternal(key, value);
×
348

349
    /// <summary>
350
    /// Adds or updates the value
351
    /// </summary>
352
    /// <param name="key">Key for setting</param>
353
    /// <param name="value">Value to set</param>
354
    /// <returns>True of was added or updated and you need to save it.</returns>
355
    public bool AddOrUpdateValue(string key, bool value) => AddOrUpdateValueInternal(key, value);
274✔
356

357
    /// <summary>
358
    /// Adds or updates the value
359
    /// </summary>
360
    /// <param name="key">Key for setting</param>
361
    /// <param name="value">Value to set</param>
362
    /// <returns>True of was added or updated and you need to save it.</returns>
363
    public bool AddOrUpdateValue(string key, long value) => AddOrUpdateValueInternal(key, value);
×
364

365
    /// <summary>
366
    /// Adds or updates the value
367
    /// </summary>
368
    /// <param name="key">Key for setting</param>
369
    /// <param name="value">Value to set</param>
370
    /// <returns>True of was added or updated and you need to save it.</returns>
371
    public bool AddOrUpdateValue(string key, string value) => AddOrUpdateValueInternal(key, value);
240✔
372

373
    /// <summary>
374
    /// Adds or updates the value
375
    /// </summary>
376
    /// <param name="key">Key for setting</param>
377
    /// <param name="value">Value to set</param>
378
    /// <param name="fileName">Name of file for settings to be stored and retrieved </param>
379
    /// <returns>True of was added or updated and you need to save it.</returns>
380
    public bool AddOrUpdateValue(string key, int value, string fileName = null) => AddOrUpdateValueInternal(key, value);
3,132✔
381

382
    /// <summary>
383
    /// Adds or updates the value
384
    /// </summary>
385
    /// <param name="key">Key for setting</param>
386
    /// <param name="value">Value to set</param>
387
    /// <param name="fileName">Name of file for settings to be stored and retrieved </param>
388
    /// <returns>True of was added or updated and you need to save it.</returns>
389
    public bool AddOrUpdateValue(string key, float value, string fileName = null) =>
390
        AddOrUpdateValueInternal(key, value);
×
391

392
    /// <summary>
393
    /// Adds or updates the value
394
    /// </summary>
395
    /// <param name="key">Key for setting</param>
396
    /// <param name="value">Value to set</param>
397
    /// <param name="fileName">Name of file for settings to be stored and retrieved </param>
398
    /// <returns>True of was added or updated and you need to save it.</returns>
399
    public bool AddOrUpdateValue(string key, DateTime value, string fileName = null) =>
400
        AddOrUpdateValueInternal(key, value);
×
401

402
    /// <summary>
403
    /// Adds or updates the value
404
    /// </summary>
405
    /// <param name="key">Key for setting</param>
406
    /// <param name="value">Value to set</param>
407
    /// <param name="fileName">Name of file for settings to be stored and retrieved </param>
408
    /// <returns>True of was added or updated and you need to save it.</returns>
409
    public bool AddOrUpdateValue(string key, Guid value, string fileName = null) =>
410
        AddOrUpdateValueInternal(key, value);
×
411

412
    /// <summary>
413
    /// Adds or updates the value
414
    /// </summary>
415
    /// <param name="key">Key for setting</param>
416
    /// <param name="value">Value to set</param>
417
    /// <param name="fileName">Name of file for settings to be stored and retrieved </param>
418
    /// <returns>True of was added or updated and you need to save it.</returns>
419
    public bool AddOrUpdateValue(string key, double value, string fileName = null) =>
420
        AddOrUpdateValueInternal(key, value);
×
421

422
    #endregion
423
}
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