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

JaCraig / Archivist / 19320779687

13 Nov 2025 04:42AM UTC coverage: 77.456% (-1.3%) from 78.739%
19320779687

push

github

JaCraig
feat(dependencies): update package versions

Update various package dependencies to their latest versions to ensure compatibility, security, and access to new features.

- Update `Microsoft.NET.Test.Sdk` to `18.0.1` in `Archivist.OCR.Tests.csproj` and `Archivist.Tests.csproj`.
- Update `Microsoft.CodeAnalysis.NetAnalyzers` to `10.0.100` in `Archivist.OCR.csproj` and `Archivist.csproj`.
- Update `Microsoft.Extensions.Logging` to `10.0.0` in `Archivist.Tests.csproj`.
- Update `Microsoft.Extensions.DependencyInjection` and `Microsoft.Extensions.Options` to `10.0.0` in `Archivist.csproj`.
- Update `ObjectCartographer` to `4.2.0` in `Archivist.csproj`.
- Update `System.Text.Encoding.CodePages` to `10.0.0` in `Archivist.csproj`.

2411 of 3412 branches covered (70.66%)

Branch coverage included in aggregate %.

3203 of 3836 relevant lines covered (83.5%)

6733.13 hits per line

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

83.41
/Archivist/DataTypes/StructuredObject.cs
1
using Archivist.BaseClasses;
2
using Archivist.Converters;
3
using Archivist.Interfaces;
4
using Newtonsoft.Json;
5
using ObjectCartographer;
6
using System;
7
using System.Collections;
8
using System.Collections.Generic;
9
using System.Diagnostics.CodeAnalysis;
10
using System.Dynamic;
11

12
namespace Archivist.DataTypes
13
{
14
    /// <summary>
15
    /// Represents a structured object.
16
    /// </summary>
17
    public class StructuredObject : FileBaseClass<StructuredObject>, IComparable<StructuredObject>, IEquatable<StructuredObject>, IObjectConvertable, IDictionary<string, object?>
18
    {
19
        /// <summary>
20
        /// Initializes a new instance of the <see cref="StructuredObject"/> class.
21
        /// </summary>
22
        public StructuredObject()
23
            : this(null, new ExpandoObject())
99,840✔
24
        {
25
        }
99,840✔
26

27
        /// <summary>
28
        /// Initializes a new instance of the <see cref="StructuredObject"/> class with the
29
        /// specified content.
30
        /// </summary>
31
        /// <param name="value">The content of the structured object.</param>
32
        public StructuredObject(IDictionary<string, object?>? value)
33
            : this(null, value)
10✔
34
        {
35
        }
10✔
36

37
        /// <summary>
38
        /// Initializes a new instance of the <see cref="StructuredObject"/> class with the
39
        /// specified content.
40
        /// </summary>
41
        /// <param name="converter">The type converter.</param>
42
        /// <param name="value">The content of the structured object.</param>
43
        public StructuredObject(Convertinator? converter, IDictionary<string, object?>? value)
44
            : base(converter)
99,868✔
45
        {
46
            Content = value ?? new ExpandoObject();
99,868!
47
        }
99,868✔
48

49
        /// <summary>
50
        /// Gets the number of items in the structured object.
51
        /// </summary>
52
        public int Count => Content.Count;
7✔
53

54
        /// <summary>
55
        /// Determines whether the structured object is read-only.
56
        /// </summary>
57
        public bool IsReadOnly => Content.IsReadOnly;
2✔
58

59
        /// <summary>
60
        /// Keys in the structured object.
61
        /// </summary>
62
        public ICollection<string> Keys => Content.Keys;
13✔
63

64
        /// <summary>
65
        /// Values in the structured object.
66
        /// </summary>
67
        public ICollection<object?> Values => Content.Values;
2✔
68

69
        /// <summary>
70
        /// Gets or sets the content of the structured object.
71
        /// </summary>
72
        private IDictionary<string, object?> Content { get; set; }
498,742✔
73

74
        /// <summary>
75
        /// Gets the value of the structured object with the specified key.
76
        /// </summary>
77
        /// <param name="key">The key of the value to get.</param>
78
        /// <returns>The value of the structured object with the specified key.</returns>
79
        public object? this[string key]
80
        {
81
            get
82
            {
83
                if (string.IsNullOrEmpty(key))
13✔
84
                    return null;
1✔
85
                _ = Content.TryGetValue(key, out var Value);
12✔
86
                return Value;
12✔
87
            }
88
            set
89
            {
90
                if (string.IsNullOrEmpty(key))
30✔
91
                    return;
1✔
92
                Content[key] = value;
29✔
93
            }
29✔
94
        }
95

96
        /// <summary>
97
        /// Converts the structured object to a calendar.
98
        /// </summary>
99
        /// <param name="structuredObject">The structured object to convert.</param>
100
        public static implicit operator Calendar?(StructuredObject? structuredObject)
101
        {
102
            return StructuredObjectToCalendarConverter.Convert(structuredObject);
1✔
103
        }
104

105
        /// <summary>
106
        /// Converts the structured object to a card.
107
        /// </summary>
108
        /// <param name="structuredObject">The structured object to convert.</param>
109
        public static implicit operator Card?(StructuredObject? structuredObject)
110
        {
111
            return StructuredObjectToCardConverter.Convert(structuredObject);
1✔
112
        }
113

114
        /// <summary>
115
        /// Converts the structured object to a feed.
116
        /// </summary>
117
        /// <param name="structuredObject">The structured object to convert.</param>
118
        /// <returns>The feed representation of the structured object.</returns>
119
        public static implicit operator Feed?(StructuredObject? structuredObject)
120
        {
121
            return StructuredObjectToFeedConverter.Convert(structuredObject);
1✔
122
        }
123

124
        /// <summary>
125
        /// Converts the structured object to an image.
126
        /// </summary>
127
        /// <param name="structuredObject">The structured object to convert.</param>
128
        /// <returns>The image representation of the structured object.</returns>
129
        public static implicit operator Image?(StructuredObject? structuredObject)
130
        {
131
            return AnythingToImageConverter.Convert(structuredObject);
1✔
132
        }
133

134
        /// <summary>
135
        /// Converts the structured object to a table.
136
        /// </summary>
137
        /// <param name="structuredObject">The structured object to convert.</param>
138
        public static implicit operator Table?(StructuredObject? structuredObject)
139
        {
140
            return StructuredObjectToTableConverter.Convert(structuredObject);
1✔
141
        }
142

143
        /// <summary>
144
        /// Converts the structured object to a tables object.
145
        /// </summary>
146
        /// <param name="structuredObject">The structured object to convert.</param>
147
        public static implicit operator Tables?(StructuredObject? structuredObject)
148
        {
149
            return StructuredObjectToTablesConverter.Convert(structuredObject);
1✔
150
        }
151

152
        /// <summary>
153
        /// Converts the structured object to a text object.
154
        /// </summary>
155
        /// <param name="structuredObject">The structured object to convert.</param>
156
        public static implicit operator Text?(StructuredObject? structuredObject)
157
        {
158
            return AnythingToTextConverter.Convert(structuredObject);
1✔
159
        }
160

161
        /// <summary>
162
        /// Determines whether two structured objects are not equal.
163
        /// </summary>
164
        /// <param name="left">The left structured object.</param>
165
        /// <param name="right">The right structured object.</param>
166
        /// <returns><c>true</c> if the structured objects are not equal; otherwise, <c>false</c>.</returns>
167
        public static bool operator !=(StructuredObject? left, StructuredObject? right)
168
        {
169
            return !(left == right);
6✔
170
        }
171

172
        /// <summary>
173
        /// Determines whether the left structured object is less than the right structured object.
174
        /// </summary>
175
        /// <param name="left">The left structured object.</param>
176
        /// <param name="right">The right structured object.</param>
177
        /// <returns>
178
        /// <c>true</c> if the left structured object is less than the right structured object;
179
        /// otherwise, <c>false</c>.
180
        /// </returns>
181
        public static bool operator <(StructuredObject? left, StructuredObject? right)
182
        {
183
            return left is null ? right is not null : left.CompareTo(right) < 0;
4✔
184
        }
185

186
        /// <summary>
187
        /// Determines whether the left structured object is less than or equal to the right
188
        /// structured object.
189
        /// </summary>
190
        /// <param name="left">The left structured object.</param>
191
        /// <param name="right">The right structured object.</param>
192
        /// <returns>
193
        /// <c>true</c> if the left structured object is less than or equal to the right structured
194
        /// object; otherwise, <c>false</c>.
195
        /// </returns>
196
        public static bool operator <=(StructuredObject? left, StructuredObject? right)
197
        {
198
            return left is null || left.CompareTo(right) <= 0;
4✔
199
        }
200

201
        /// <summary>
202
        /// Determines whether two structured objects are equal.
203
        /// </summary>
204
        /// <param name="left">The left structured object.</param>
205
        /// <param name="right">The right structured object.</param>
206
        /// <returns><c>true</c> if the structured objects are equal; otherwise, <c>false</c>.</returns>
207
        public static bool operator ==(StructuredObject? left, StructuredObject? right)
208
        {
209
            if (left is null)
12✔
210
                return right is null;
4✔
211
            return left.Equals(right);
8✔
212
        }
213

214
        /// <summary>
215
        /// Determines whether the left structured object is greater than the right structured object.
216
        /// </summary>
217
        /// <param name="left">The left structured object.</param>
218
        /// <param name="right">The right structured object.</param>
219
        /// <returns>
220
        /// <c>true</c> if the left structured object is greater than the right structured object;
221
        /// otherwise, <c>false</c>.
222
        /// </returns>
223
        public static bool operator >(StructuredObject? left, StructuredObject? right)
224
        {
225
            return left?.CompareTo(right) > 0;
4✔
226
        }
227

228
        /// <summary>
229
        /// Determines whether the left structured object is greater than or equal to the right
230
        /// structured object.
231
        /// </summary>
232
        /// <param name="left">The left structured object.</param>
233
        /// <param name="right">The right structured object.</param>
234
        /// <returns>
235
        /// <c>true</c> if the left structured object is greater than or equal to the right
236
        /// structured object; otherwise, <c>false</c>.
237
        /// </returns>
238
        public static bool operator >=(StructuredObject? left, StructuredObject? right)
239
        {
240
            return left is null ? right is null : left.CompareTo(right) >= 0;
4✔
241
        }
242

243
        /// <summary>
244
        /// Adds a key-value pair to the structured object.
245
        /// </summary>
246
        /// <param name="key">The key of the value to add.</param>
247
        /// <param name="value">The value to add.</param>
248
        public void Add(string key, object? value)
249
        {
250
            if (string.IsNullOrEmpty(key))
6✔
251
                return;
1✔
252
            Content.Add(key, value);
5✔
253
        }
5✔
254

255
        /// <summary>
256
        /// Adds a key-value pair to the structured object.
257
        /// </summary>
258
        /// <param name="item">The key-value pair to add.</param>
259
        public void Add(KeyValuePair<string, object?> item)
260
        {
261
            if (string.IsNullOrEmpty(item.Key))
2✔
262
                return;
1✔
263
            Content.Add(item);
1✔
264
        }
1✔
265

266
        /// <summary>
267
        /// Clears the structured object.
268
        /// </summary>
269
        public void Clear() => Content.Clear();
2✔
270

271
        /// <summary>
272
        /// Compares the current structured object with another structured object.
273
        /// </summary>
274
        /// <param name="other">The structured object to compare with this structured object.</param>
275
        /// <returns>A value indicating the relative order of the objects being compared.</returns>
276
        public override int CompareTo(StructuredObject? other)
277
        {
278
            if (other?.Content is null && Content is null)
13!
279
                return 0;
×
280
            if (other?.Content is null)
13✔
281
                return 1;
5✔
282
            if (Content is null)
8!
283
                return -1;
×
284
            return other.GetContent()?.CompareTo(GetContent()) ?? 0;
8!
285
        }
286

287
        /// <summary>
288
        /// Determines whether the current structured object contains the specified key-value pair.
289
        /// </summary>
290
        /// <param name="item">The key-value pair to locate in the structured object.</param>
291
        /// <returns>True if the structured object contains the key-value pair; otherwise, false.</returns>
292
        public bool Contains(KeyValuePair<string, object?> item)
293
        {
294
            if (string.IsNullOrEmpty(item.Key))
3✔
295
                return false;
2✔
296
            return Content.Contains(item);
1✔
297
        }
298

299
        /// <summary>
300
        /// Determines whether the current structured object contains the specified key.
301
        /// </summary>
302
        /// <param name="key">The key to locate in the structured object.</param>
303
        /// <returns>True if the structured object contains the key; otherwise, false.</returns>
304
        public bool ContainsKey(string key)
305
        {
306
            if (string.IsNullOrEmpty(key))
4✔
307
                return false;
1✔
308
            return Content.ContainsKey(key);
3✔
309
        }
310

311
        /// <summary>
312
        /// Converts the structured object from the specified object.
313
        /// </summary>
314
        /// <typeparam name="TObject">The type of the object to convert from.</typeparam>
315
        /// <param name="obj">The object to convert from.</param>
316
        public void ConvertFrom<TObject>(TObject obj)
317
        {
318
            if (obj is null)
8✔
319
                return;
1✔
320
            if (obj is string StringObject)
7!
321
            {
322
                Content = JsonConvert.DeserializeObject<ExpandoObject>(StringObject) ?? new ExpandoObject();
7!
323
                return;
7✔
324
            }
325
            Content = obj.To<ExpandoObject>();
×
326
        }
×
327

328
        /// <summary>
329
        /// Converts the structured object to the specified object type.
330
        /// </summary>
331
        /// <typeparam name="TObject">The type of the object to convert to.</typeparam>
332
        /// <returns>The converted object.</returns>
333
        public TObject? ConvertTo<TObject>()
334
        {
335
            if (Content is null)
10!
336
                return default;
×
337
            return Content.To<TObject>();
10✔
338
        }
339

340
        /// <summary>
341
        /// Copies the key-value pairs of the structured object to an array.
342
        /// </summary>
343
        /// <param name="array">The array to copy the key-value pairs to.</param>
344
        /// <param name="arrayIndex">
345
        /// The index in the array to start copying the key-value pairs to.
346
        /// </param>
347
        public void CopyTo(KeyValuePair<string, object?>[] array, int arrayIndex)
348
        {
349
            if (array is null)
2✔
350
                return;
1✔
351
            if (arrayIndex < 0 || arrayIndex >= array.Length)
1!
352
                return;
×
353
            Content.CopyTo(array, arrayIndex);
1✔
354
        }
1✔
355

356
        /// <summary>
357
        /// Determines whether the current structured object is equal to another object.
358
        /// </summary>
359
        /// <param name="obj">The object to compare with the current structured object.</param>
360
        /// <returns>
361
        /// <c>true</c> if the current structured object is equal to the other object; otherwise, <c>false</c>.
362
        /// </returns>
363
        public override bool Equals(object? obj)
364
        {
365
            if (ReferenceEquals(this, obj))
6!
366
                return true;
×
367
            if (obj is not StructuredObject StructuredObject)
6✔
368
                return false;
4✔
369
            return Equals(StructuredObject);
2✔
370
        }
371

372
        /// <summary>
373
        /// Determines whether the current structured object is equal to another structured object.
374
        /// </summary>
375
        /// <param name="other">The structured object to compare with the current structured object.</param>
376
        /// <returns>
377
        /// <c>true</c> if the current structured object is equal to the other structured object;
378
        /// otherwise, <c>false</c>.
379
        /// </returns>
380
        public override bool Equals(StructuredObject? other) => other is not null && other.GetContent() == GetContent();
14✔
381

382
        /// <summary>
383
        /// Gets the content of the structured object as a string.
384
        /// </summary>
385
        /// <returns>The content of the structured object as a string.</returns>
386
        public override string? GetContent()
387
        {
388
            if (Content is null)
60!
389
                return "";
×
390
            return JsonConvert.SerializeObject(Content);
60✔
391
        }
392

393
        /// <summary>
394
        /// Gets the enumerator for the structured object.
395
        /// </summary>
396
        /// <returns>The enumerator for the structured object.</returns>
397
        public IEnumerator<KeyValuePair<string, object?>> GetEnumerator()
398
        {
399
            if (Content is null)
199,296!
400
                return new Dictionary<string, object?>().GetEnumerator();
×
401
            return Content.GetEnumerator();
199,296✔
402
        }
403

404
        /// <summary>
405
        /// Gets the enumerator for the structured object.
406
        /// </summary>
407
        /// <returns>The enumerator for the structured object.</returns>
408
        IEnumerator IEnumerable.GetEnumerator() => Content.GetEnumerator();
1✔
409

410
        /// <summary>
411
        /// Gets the hash code of the structured object.
412
        /// </summary>
413
        /// <returns>The hash code of the structured object.</returns>
414
        public override int GetHashCode() => GetContent()?.GetHashCode() ?? 0;
6!
415

416
        /// <summary>
417
        /// Gets the value of the structured object with the specified key.
418
        /// </summary>
419
        /// <typeparam name="TObject">The type of the value to get.</typeparam>
420
        /// <param name="key">The key of the value to get.</param>
421
        /// <returns>The value of the structured object with the specified key.</returns>
422
        public TObject? GetValue<TObject>(string key)
423
        {
424
            _ = TryGetValue(key, out TObject? Value);
15✔
425
            return Value;
15✔
426
        }
427

428
        /// <summary>
429
        /// Removes the key-value pair with the specified key from the structured object.
430
        /// </summary>
431
        /// <param name="key">The key of the key-value pair to remove.</param>
432
        /// <returns><c>true</c> if the key-value pair was removed; otherwise, <c>false</c>.</returns>
433
        public bool Remove(string key)
434
        {
435
            if (string.IsNullOrEmpty(key))
2✔
436
                return false;
1✔
437
            return Content.Remove(key);
1✔
438
        }
439

440
        /// <summary>
441
        /// Removes the key-value pair with the specified key from the structured object.
442
        /// </summary>
443
        /// <param name="item">The key-value pair to remove.</param>
444
        /// <returns><c>true</c> if the key-value pair was removed; otherwise, <c>false</c>.</returns>
445
        public bool Remove(KeyValuePair<string, object?> item)
446
        {
447
            if (string.IsNullOrEmpty(item.Key))
2✔
448
                return false;
1✔
449
            return Content.Remove(item);
1✔
450
        }
451

452
        /// <summary>
453
        /// Sets the value of the structured object with the specified key.
454
        /// </summary>
455
        /// <typeparam name="TObject">The type of the value to set.</typeparam>
456
        /// <param name="key">The key of the value to set.</param>
457
        /// <param name="value">Value to set</param>
458
        /// <returns>The structured object with the value set.</returns>
459
        public StructuredObject SetValue<TObject>(string key, TObject value)
460
        {
461
            if (string.IsNullOrEmpty(key))
9✔
462
                return this;
1✔
463

464
            Content[key] = value;
8✔
465

466
            return this;
8✔
467
        }
468

469
        /// <summary>
470
        /// Converts the structured object to the specified file type.
471
        /// </summary>
472
        /// <typeparam name="TFile">The type of the file.</typeparam>
473
        /// <returns>The file of the specified type.</returns>
474
        public override TFile? ToFileType<TFile>() where TFile : default
475
        {
476
            Type FileType = typeof(TFile);
3✔
477
            IGenericFile? ReturnValue;
478
            if (FileType == typeof(Card))
3!
479
                ReturnValue = (Card?)this;
×
480
            else if (FileType == typeof(Calendar))
3!
481
                ReturnValue = (Calendar?)this;
×
482
            else if (FileType == typeof(Feed))
3!
483
                ReturnValue = (Feed?)this;
×
484
            else if (FileType == typeof(Image))
3!
485
                ReturnValue = (Image?)this;
×
486
            else if (FileType == typeof(Table))
3!
487
                ReturnValue = (Table?)this;
×
488
            else if (FileType == typeof(Tables))
3!
489
                ReturnValue = (Tables?)this;
×
490
            else if (FileType == typeof(Text))
3!
491
                ReturnValue = (Text?)this;
×
492
            else if (FileType == typeof(StructuredObject))
3✔
493
                ReturnValue = this;
2✔
494
            else
495
                ReturnValue = (IGenericFile?)Converter?.Convert(this, FileType);
1!
496

497
            return (TFile?)ReturnValue;
3✔
498
        }
499

500
        /// <summary>
501
        /// Tries to get the value of the structured object with the specified key.
502
        /// </summary>
503
        /// <typeparam name="TObject">The type of the value to get.</typeparam>
504
        /// <param name="key">The key of the value to get.</param>
505
        /// <param name="value">The value of the structured object with the specified key.</param>
506
        /// <returns><c>true</c> if the value was retrieved; otherwise, <c>false</c>.</returns>
507
        public bool TryGetValue<TObject>(string key, out TObject? value)
508
        {
509
            value = default;
17✔
510
            if (string.IsNullOrEmpty(key))
17✔
511
                return false;
2✔
512
            if (!Content.TryGetValue(key, out var Value))
15✔
513
                return false;
2✔
514
            value = Value.To<TObject>();
13✔
515
            return true;
13✔
516
        }
517

518
        /// <summary>
519
        /// Tries to get the value of the structured object with the specified key.
520
        /// </summary>
521
        /// <param name="key">The key of the value to get.</param>
522
        /// <param name="value">The value of the structured object with the specified key.</param>
523
        /// <returns><c>true</c> if the value was retrieved; otherwise, <c>false</c>.</returns>
524
        public bool TryGetValue(string key, [MaybeNullWhen(false)] out object? value)
525
        {
526
            value = default;
3✔
527
            if (string.IsNullOrEmpty(key))
3✔
528
                return false;
1✔
529
            return Content.TryGetValue(key, out _);
2✔
530
        }
531
    }
532
}
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

© 2025 Coveralls, Inc