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

HicServices / RDMP / 13159438705

05 Feb 2025 02:20PM UTC coverage: 57.451% (+0.01%) from 57.437%
13159438705

Pull #2125

github

JFriel
tidy up
Pull Request #2125: Task/rdmp 265 version data loads

11330 of 21275 branches covered (53.25%)

Branch coverage included in aggregate %.

966 of 1168 new or added lines in 8 files covered. (82.71%)

3 existing lines in 3 files now uncovered.

32228 of 54543 relevant lines covered (59.09%)

17081.21 hits per line

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

77.94
/Rdmp.Core/Curation/Data/DataLoad/LoadMetadata.cs
1
// Copyright (c) The University of Dundee 2018-2024
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.Collections.Generic;
9
using System.Data.Common;
10
using System.IO;
11
using System.Linq;
12
using FAnsi.Discovery;
13
using FAnsi.Discovery.QuerySyntax;
14
using MongoDB.Driver;
15
using Rdmp.Core.Curation.Data.Cache;
16
using Rdmp.Core.Curation.Data.Defaults;
17
using Rdmp.Core.Curation.Data.ImportExport;
18
using Rdmp.Core.Curation.Data.Serialization;
19
using Rdmp.Core.Logging;
20
using Rdmp.Core.Logging.PastEvents;
21
using Rdmp.Core.MapsDirectlyToDatabaseTable;
22
using Rdmp.Core.MapsDirectlyToDatabaseTable.Attributes;
23
using Rdmp.Core.Repositories;
24
using Rdmp.Core.ReusableLibraryCode;
25
using Rdmp.Core.ReusableLibraryCode.Annotations;
26
using Rdmp.Core.ReusableLibraryCode.DataAccess;
27

28
namespace Rdmp.Core.Curation.Data.DataLoad;
29

30
/// <summary>
31
/// How are files cached within the cache (e.g. within a zip? tar? just uncompressed in a directory).
32
/// </summary>
33
public enum CacheArchiveType
34
{
35
    /// <summary>
36
    /// Cached files are in a directory uncompressed
37
    /// </summary>
38
    None = 0,
39

40
    /// <summary>
41
    /// Cached files are contained in a zip file
42
    /// </summary>
43
    Zip = 1
44
}
45

46
/// <inheritdoc cref="ILoadMetadata"/>
47
public class LoadMetadata : DatabaseEntity, ILoadMetadata, IHasDependencies, IHasQuerySyntaxHelper,
48
    ILoggedActivityRootObject, IHasFolder, IVersionable
49
{
50
    #region Database Properties
51

52
    private string _locationOfForLoadingDirectory;
53
    private string _locationOfForArchivingDirectory;
54
    private string _locationOfExecutablesDirectory;
55
    private string _locationOfCacheDirectory;
56
    private string _anonymisationEngineClass;
57
    private string _name;
58
    private string _description;
59
    private CacheArchiveType _cacheArchiveType;
60
    private int? _overrideRawServerID;
61
    private bool _ignoreTrigger;
62
    private string _folder;
63
    private DateTime? _lastLoadTime;
64
    private bool _allowReservedPrefix;
65
    private int? _rootLoadMetadata_ID;
66

67
    public string DefaultForLoadingPath = Path.Combine("Data", "ForLoading");
1,130✔
68
    public string DefaultForArchivingPath = Path.Combine("Data", "ForArchiving");
1,130✔
69
    public string DefaultExecutablesPath = "Executables";
1,130✔
70
    public string DefaultCachePath = Path.Combine("Data", "Cache");
1,130✔
71

72
    public DirectoryInfo GetRootDirectory()
73
    {
74
        if (!string.IsNullOrWhiteSpace(_locationOfForLoadingDirectory) && !string.IsNullOrWhiteSpace(_locationOfForArchivingDirectory) && !string.IsNullOrWhiteSpace(_locationOfExecutablesDirectory) && !string.IsNullOrWhiteSpace(_locationOfCacheDirectory))
×
75
        {
76
            var forLoadingRoot = _locationOfForLoadingDirectory.Replace(DefaultForLoadingPath, "");
×
77
            var forArchivingRoot = _locationOfForArchivingDirectory.Replace(DefaultForArchivingPath, "");
×
78
            var forExecutablesRoot = _locationOfExecutablesDirectory.Replace(DefaultExecutablesPath, "");
×
79
            var forCacheRoot = _locationOfCacheDirectory.Replace(DefaultCachePath, "");
×
80
            if (forLoadingRoot == forArchivingRoot && forExecutablesRoot == forCacheRoot && forArchivingRoot == forExecutablesRoot)
×
81
            {
82
                return new DirectoryInfo(forLoadingRoot);
×
83
            }
84
        }
85
        return null;
×
86
    }
87

88

89
    ///  <inheritdoc/>
90
    public bool AllowReservedPrefix
91
    {
92
        get => _allowReservedPrefix;
930✔
93
        set => SetField(ref _allowReservedPrefix, value);
984✔
94
    }
95

96
    ///  <inheritdoc/>
97
    public string LocationOfForLoadingDirectory
98
    {
99
        get => _locationOfForLoadingDirectory;
2,204✔
100
        set => SetField(ref _locationOfForLoadingDirectory, value);
1,112✔
101
    }
102

103
    ///  <inheritdoc/>
104
    public string LocationOfForArchivingDirectory
105
    {
106
        get => _locationOfForArchivingDirectory;
1,952✔
107
        set => SetField(ref _locationOfForArchivingDirectory, value);
1,112✔
108
    }
109

110
    ///  <inheritdoc/>
111
    public string LocationOfExecutablesDirectory
112
    {
113
        get => _locationOfExecutablesDirectory;
1,952✔
114
        set => SetField(ref _locationOfExecutablesDirectory, value);
1,112✔
115
    }
116

117
    ///  <inheritdoc/>
118
    public string LocationOfCacheDirectory
119
    {
120
        get => _locationOfCacheDirectory;
1,952✔
121
        set => SetField(ref _locationOfCacheDirectory, value);
1,112✔
122
    }
123

124
    /// <summary>
125
    /// Not used
126
    /// </summary>
127
    public string AnonymisationEngineClass
128
    {
129
        get => _anonymisationEngineClass;
880✔
130
        set => SetField(ref _anonymisationEngineClass, value);
974✔
131
    }
132

133
    /// <inheritdoc/>
134
    [Unique]
135
    [NotNull]
136
    public string Name
137
    {
138
        get => _name;
1,222✔
139
        set => SetField(ref _name, value);
1,844✔
140
    }
141

142
    /// <summary>
143
    /// Human readable description of the load, what it does etc
144
    /// </summary>
145
    public string Description
146
    {
147
        get => _description;
894✔
148
        set => SetField(ref _description, value);
980✔
149
    }
150

151
    /// <summary>
152
    /// The format for storing files in when reading/writing to a cache with a <see cref="CacheProgress"/>.  This may not be respected
153
    /// depending on the implementation of the sepecific ICacheLayout
154
    /// </summary>
155
    public CacheArchiveType CacheArchiveType
156
    {
157
        get => _cacheArchiveType;
880✔
158
        set => SetField(ref _cacheArchiveType, value);
984✔
159
    }
160

161
    /// <summary>
162
    /// Optional.  Indicates that when running the Data Load Engine, the specific <see cref="ExternalDatabaseServer"/> should be used for the RAW server (instead of
163
    /// the system default - see <see cref="ServerDefaults"/>).
164
    /// </summary>
165
    public int? OverrideRAWServer_ID
166
    {
167
        get => _overrideRawServerID;
1,780✔
168
        set => SetField(ref _overrideRawServerID, value);
974✔
169
    }
170

171

172
    /// <iheritdoc/>
173
    public bool IgnoreTrigger
174
    {
175
        get => _ignoreTrigger;
1,272✔
176
        set => SetField(ref _ignoreTrigger, value);
1,132✔
177
    }
178

179
    /// <inheritdoc/>
180
    [UsefulProperty]
181
    public string Folder
182
    {
183
        get => _folder;
1,532✔
184
        set => SetField(ref _folder, FolderHelper.Adjust(value));
1,108✔
185
    }
186

187

188
    /// <summary>
189
    /// Stores the last time the load was ran.
190
    /// </summary>
191
    public DateTime? LastLoadTime
192
    {
193
        get => _lastLoadTime;
888✔
194
        set => SetField(ref _lastLoadTime, value);
1,126✔
195
    }
196

197
    /// <inheritdoc/>
198
    public int? RootLoadMetadata_ID { get => _rootLoadMetadata_ID; private set => SetField(ref _rootLoadMetadata_ID, value); }
8,922✔
199

200
    #endregion
201

202

203
    #region Relationships
204

205
    /// <inheritdoc/>
206
    [NoMappingToDatabase]
207
    public ExternalDatabaseServer OverrideRAWServer => OverrideRAWServer_ID.HasValue
350!
208
        ? Repository.GetObjectByID<ExternalDatabaseServer>(OverrideRAWServer_ID.Value)
350✔
209
        : null;
350✔
210

211
    /// <inheritdoc/>
212
    [NoMappingToDatabase]
213
    public ILoadProgress[] LoadProgresses => Repository.GetAllObjectsWithParent<LoadProgress>(this);
202✔
214

215
    /// <inheritdoc/>
216
    [NoMappingToDatabase]
217
    public IOrderedEnumerable<IProcessTask> ProcessTasks
218
    {
219
        get
220
        {
221
            return
320✔
222
                Repository.GetAllObjectsWithParent<ProcessTask>(this).Cast<IProcessTask>().OrderBy(pt => pt.Order);
620✔
223
        }
224
    }
225

226
    #endregion
227

228
    public LoadMetadata()
30✔
229
    {
230
    }
30✔
231

232
    /// <summary>
233
    /// Create a new DLE load.  This load will not have any <see cref="ProcessTask"/> and will not load any <see cref="TableInfo"/> yet.
234
    /// 
235
    /// <para>To set the loaded tables, set <see cref="Catalogue.LoadMetadatas"/> on some of your datasets</para>
236
    /// </summary>
237
    /// <param name="repository"></param>
238
    /// <param name="name"></param>
239
    /// <param name="rootLoadMetadata"></param>
240
    public LoadMetadata(ICatalogueRepository repository, string name = null, LoadMetadata rootLoadMetadata = null)
358✔
241
    {
242
        name ??= $"NewLoadMetadata{Guid.NewGuid()}";
358✔
243
        repository.InsertAndHydrate(this, new Dictionary<string, object>
358!
244
        {
358✔
245
            { "Name", name },
358✔
246
            { "IgnoreTrigger", false /*todo could be system global default here*/ },
358✔
247
            { "Folder", FolderHelper.Root },
358✔
248
            {"LastLoadTime", null },
358✔
249
            {"RootLoadMetadata_ID", rootLoadMetadata is null? null: rootLoadMetadata.ID }
358✔
250
        });
358✔
251
    }
358✔
252

253
    internal LoadMetadata(ICatalogueRepository repository, DbDataReader r)
254
        : base(repository, r)
732✔
255
    {
256
        LocationOfForLoadingDirectory = r["LocationOfForLoadingDirectory"].ToString();
732✔
257
        LocationOfForArchivingDirectory = r["LocationOfForArchivingDirectory"].ToString();
732✔
258
        LocationOfExecutablesDirectory = r["LocationOfExecutablesDirectory"].ToString();
732✔
259
        LocationOfCacheDirectory = r["LocationOfCacheDirectory"].ToString();
732✔
260
        Name = r["Name"] as string;
732✔
261
        AnonymisationEngineClass = r["AnonymisationEngineClass"].ToString();
732✔
262
        Name = r["Name"].ToString();
732✔
263
        Description = r["Description"] as string; //allows for nulls
732✔
264
        CacheArchiveType = (CacheArchiveType)r["CacheArchiveType"];
732✔
265
        OverrideRAWServer_ID = ObjectToNullableInt(r["OverrideRAWServer_ID"]);
732✔
266
        IgnoreTrigger = ObjectToNullableBool(r["IgnoreTrigger"]) ?? false;
732✔
267
        Folder = r["Folder"] as string ?? FolderHelper.Root;
732!
268
        LastLoadTime = string.IsNullOrWhiteSpace(r["LastLoadTime"].ToString()) ? null : DateTime.Parse(r["LastLoadTime"].ToString());
732✔
269
        AllowReservedPrefix = ObjectToNullableBool(r["AllowReservedPrefix"]) ?? false;
732✔
270
        RootLoadMetadata_ID = ObjectToNullableInt(r["RootLoadMetadata_ID"]);
732✔
271
    }
732✔
272

273

274
    public LoadMetadata Clone()
275
    {
276
        var lmd = new LoadMetadata(CatalogueRepository, this.Name)
6✔
277
        {
6✔
278
            LocationOfForLoadingDirectory = LocationOfForLoadingDirectory,
6✔
279
            LocationOfForArchivingDirectory = LocationOfForArchivingDirectory,
6✔
280
            LocationOfCacheDirectory = LocationOfCacheDirectory,
6✔
281
            LocationOfExecutablesDirectory = LocationOfExecutablesDirectory,
6✔
282
            AnonymisationEngineClass = AnonymisationEngineClass,
6✔
283
            Name = Name,
6✔
284
            Description = Description,
6✔
285
            CacheArchiveType = CacheArchiveType,
6✔
286
            AllowReservedPrefix = false,
6✔
287
            LastLoadTime = LastLoadTime,
6✔
288
            OverrideRAWServer_ID = OverrideRAWServer_ID,
6✔
289
            IgnoreTrigger = IgnoreTrigger,
6✔
290
            Folder = Folder,
6✔
291
        };
6✔
292
        lmd.SaveToDatabase();
6✔
293
        //link to catalogue
294
        foreach (var catalogue in this.GetAllCatalogues())
24✔
295
        {
296
            lmd.LinkToCatalogue(catalogue);
6✔
297
        }
298
        //process task
299
        var pts = CatalogueRepository.GetAllObjectsWhere<ProcessTask>("LoadMetadata_ID", this.ID);
6✔
300
        foreach (ProcessTask pt in pts)
24✔
301
        {
302
            pt.Clone(lmd);
6✔
303
        }
304
        return lmd;
6✔
305
    }
306

307
    internal LoadMetadata(ShareManager shareManager, ShareDefinition shareDefinition) : base()
10✔
308
    {
309
        shareManager.UpsertAndHydrate(this, shareDefinition);
10✔
310
    }
10✔
311

312
    public void LinkToCatalogue(ICatalogue catalogue)
313
    {
314
        var linkage = new LoadMetadataCatalogueLinkage(CatalogueRepository, this, catalogue);
308✔
315
        linkage.SaveToDatabase();
308✔
316
    }
308✔
317

318
    public void UnlinkFromCatalogue(ICatalogue catalogue)
319
    {
320
        foreach (var l in CatalogueRepository.GetAllObjects<LoadMetadataCatalogueLinkage>().Where(link => link.CatalogueID == catalogue.ID && link.LoadMetadataID == this.ID))
56✔
321
        {
322
            l.DeleteInDatabase();
8✔
323
        }
324
    }
8✔
325

326
    /// <inheritdoc/>
327
    public override void DeleteInDatabase()
328
    {
329
        var firstOrDefault = GetAllCatalogues().FirstOrDefault();
74✔
330

331
        if (firstOrDefault != null && this.RootLoadMetadata_ID == null)
74!
332
            throw new Exception(
×
333
                $"This load is used by {firstOrDefault.Name} so cannot be deleted (Disassociate it first)");
×
334

335
        var versions = Repository.GetAllObjectsWhere<LoadMetadata>("RootLoadMetadata_ID", ID);
74✔
336
        foreach (var version in versions)
148!
337
        {
NEW
338
            version.DeleteInDatabase();
×
339
        }
340
        if (this.RootLoadMetadata_ID != null)
74!
341
        {
NEW
342
            var catalogueLinkIDs = Repository.GetAllObjectsWhere<LoadMetadataCatalogueLinkage>("LoadMetadataID", ID);
×
NEW
343
            foreach (var link in catalogueLinkIDs)
×
344
            {
NEW
345
                link.DeleteInDatabase();
×
346
            }
347
        }
348

349

350
        base.DeleteInDatabase();
74✔
351
    }
74✔
352

353
    /// <inheritdoc/>
354
    public override string ToString() => Name;
98✔
355

356
    /// <inheritdoc/>
357
    public IEnumerable<ICatalogue> GetAllCatalogues()
358
    {
359
        var catalogueLinkIDs = Repository.GetAllObjectsWhere<LoadMetadataCatalogueLinkage>("LoadMetadataID", ID).Select(l => l.CatalogueID);
3,978✔
360
        return Repository.GetAllObjects<Catalogue>().Where(cat => catalogueLinkIDs.Contains(cat.ID));
3,858✔
361
    }
362

363
    /// <inheritdoc cref="GetDistinctLoggingDatabase()"/>
364
    public DiscoveredServer GetDistinctLoggingDatabase(out IExternalDatabaseServer serverChosen)
365
    {
366
        var loggingServers = GetLoggingServers();
114✔
367

368
        var loggingServer = loggingServers.FirstOrDefault();
112✔
369

370
        //get distinct connection
371
        var toReturn = DataAccessPortal.ExpectDistinctServer(loggingServers, DataAccessContext.Logging, true);
112✔
372

373
        serverChosen = (IExternalDatabaseServer)loggingServer;
108✔
374
        return toReturn;
108✔
375
    }
376

377
    /// <summary>
378
    /// The unique logging server for auditing the load (found by querying <see cref="Catalogue.LiveLoggingServer"/>)
379
    /// </summary>
380
    /// <returns></returns>
381
    public DiscoveredServer GetDistinctLoggingDatabase() => GetDistinctLoggingDatabase(out _);
114✔
382

383
    private IDataAccessPoint[] GetLoggingServers()
384
    {
385
        var catalogue = GetAllCatalogues().ToArray();
114✔
386

387
        return !catalogue.Any()
114!
388
            ? throw new NotSupportedException(
114✔
389
                $"LoadMetaData '{ToString()} (ID={ID}) does not have any Catalogues associated with it so it is not possible to fetch its LoggingDatabaseSettings")
114✔
390
            : (IDataAccessPoint[])catalogue.Select(c => c.LiveLoggingServer).ToArray();
236✔
391
    }
392

393
    /// <summary>
394
    /// Returns the unique value of <see cref="Catalogue.LoggingDataTask"/> amongst all catalogues loaded by the <see cref="LoadMetadata"/>
395
    /// </summary>
396
    /// <returns></returns>
397
    public string GetDistinctLoggingTask()
398
    {
399
        var catalogueMetadatas = GetAllCatalogues().ToArray();
88✔
400

401
        if (!catalogueMetadatas.Any())
88!
402
            throw new Exception($"There are no Catalogues associated with load metadata (ID={ID})");
×
403

404
        var cataloguesWithoutLoggingTasks =
88✔
405
            catalogueMetadatas.Where(c => string.IsNullOrWhiteSpace(c.LoggingDataTask)).ToArray();
186✔
406

407
        if (cataloguesWithoutLoggingTasks.Any())
88✔
408
            throw new Exception(
2✔
409
                $"The following Catalogues do not have a LoggingDataTask specified:{cataloguesWithoutLoggingTasks.Aggregate("", (s, n) => $"{s}{n}(ID={n.ID}),")}");
4✔
410

411
        var distinctLoggingTasks = catalogueMetadatas.Select(c => c.LoggingDataTask).Distinct().ToArray();
180✔
412
        return distinctLoggingTasks.Length >= 2
86!
413
            ? throw new Exception(
86✔
414
                $"There are {distinctLoggingTasks.Length} logging tasks in Catalogues belonging to this metadata (ID={ID})")
86✔
415
            : distinctLoggingTasks[0];
86✔
416
    }
417

418
    /// <summary>
419
    /// Return all <see cref="TableInfo"/> underlying the <see cref="Catalogue"/>(s) which use this load (what tables will be loaded by the DLE).
420
    /// </summary>
421
    /// <param name="includeLookups">true to include lookup tables (e.g. z_sex etc) configured in the <see cref="Catalogue"/>(s)</param>
422
    /// <returns></returns>
423
    public List<TableInfo> GetDistinctTableInfoList(bool includeLookups)
424
    {
425
        var toReturn = new List<TableInfo>();
8✔
426

427
        foreach (var catalogueMetadata in GetAllCatalogues())
32✔
428
            foreach (TableInfo tableInfo in catalogueMetadata.GetTableInfoList(includeLookups))
32✔
429
                if (!toReturn.Contains(tableInfo))
8✔
430
                    toReturn.Add(tableInfo);
8✔
431

432
        return toReturn;
8✔
433
    }
434

435
    /// <inheritdoc/>
436
    public DiscoveredServer GetDistinctLiveDatabaseServer()
437
    {
438
        var normalTables = new HashSet<ITableInfo>();
244✔
439
        var lookupTables = new HashSet<ITableInfo>();
244✔
440

441
        foreach (var catalogue in GetAllCatalogues())
1,000✔
442
        {
443
            catalogue.GetTableInfos(out var normal, out var lookup);
256✔
444

445
            foreach (var n in normal)
1,024✔
446
                normalTables.Add(n);
256✔
447
            foreach (var l in lookup)
512!
448
                lookupTables.Add(l);
×
449
        }
450

451
        if (normalTables.Any())
244!
452
            return DataAccessPortal.ExpectDistinctServer(normalTables.ToArray(), DataAccessContext.DataLoad, true);
244✔
453

454
        return lookupTables.Any()
×
455
            ? DataAccessPortal.ExpectDistinctServer(lookupTables.ToArray(), DataAccessContext.DataLoad, true)
×
456
            : throw new Exception(
×
457
                $"LoadMetadata {this} has no TableInfos configured (or possibly the tables have been deleted resulting in MISSING ColumnInfos?)");
×
458
    }
459

460
    /// <inheritdoc/>
461
    public IHasDependencies[] GetObjectsThisDependsOn() => null;
×
462

463
    /// <inheritdoc/>
464
    public IHasDependencies[] GetObjectsDependingOnThis() => GetAllCatalogues().ToArray();
74✔
465

466
    /// <summary>
467
    /// Tests that the logging database for the load is reachable and that it has an appropriate logging task for the load (if not a new task will be created 'Loading X')
468
    /// </summary>
469
    /// <param name="catalogue"></param>
470
    public void EnsureLoggingWorksFor(ICatalogue catalogue)
471
    {
472
        //if there's no logging task / logging server set them up with the same name as the lmd
473
        IExternalDatabaseServer loggingServer;
474

475
        if (catalogue.LiveLoggingServer_ID == null)
14!
476
        {
477
            loggingServer = CatalogueRepository.GetDefaultFor(PermissableDefaults.LiveLoggingServer_ID);
×
478

479
            if (loggingServer != null)
×
480
                catalogue.LiveLoggingServer_ID = loggingServer.ID;
×
481
            else
482
                throw new NotSupportedException(
×
483
                    "You do not yet have any logging servers configured so cannot create data loads");
×
484
        }
485
        else
486
        {
487
            loggingServer = Repository.GetObjectByID<ExternalDatabaseServer>(catalogue.LiveLoggingServer_ID.Value);
14✔
488
        }
489

490
        //if there's no logging task yet and there's a logging server
491
        if (string.IsNullOrWhiteSpace(catalogue.LoggingDataTask))
14✔
492
        {
493
            var lm = new LogManager(loggingServer);
14✔
494
            var loggingTaskName = Name;
14✔
495

496
            lm.CreateNewLoggingTaskIfNotExists(loggingTaskName);
14✔
497
            catalogue.LoggingDataTask = loggingTaskName;
14✔
498
            catalogue.SaveToDatabase();
14✔
499
        }
500
    }
14✔
501

502
    /// <inheritdoc/>
503
    public IQuerySyntaxHelper GetQuerySyntaxHelper()
504
    {
505
        var syntax = GetAllCatalogues().Select(c => c.GetQuerySyntaxHelper()).Distinct().ToArray();
4✔
506
        return syntax.Length > 1
2!
507
            ? throw new Exception(
2✔
508
                $"LoadMetadata '{this}' has multiple underlying Catalogue Live Database Type(s) - not allowed")
2✔
509
            : syntax.SingleOrDefault();
2✔
510
    }
511

512
    /// <summary>
513
    /// Returns all runs since each LoadMetadata has its own task and all runs apply to that task and hence this object
514
    /// </summary>
515
    /// <param name="runs"></param>
516
    /// <returns></returns>
517
    public IEnumerable<ArchivalDataLoadInfo> FilterRuns(IEnumerable<ArchivalDataLoadInfo> runs) => runs;
12✔
518

519
    public static bool UsesPersistentRaw(ILoadMetadata loadMetadata)
520
    {
521
        return loadMetadata.CatalogueRepository.GetExtendedProperties(ExtendedProperty.PersistentRaw,
90✔
522
            loadMetadata).Any(p => p.Value == "true");
90✔
523
    }
524

525

526
    /// <inheritdoc/>
527
    public DatabaseEntity SaveNewVersion()
528
    {
529
        var lmd = this.Clone();
4✔
530
        lmd.RootLoadMetadata_ID = this.RootLoadMetadata_ID != null ? this.RootLoadMetadata_ID : this.ID;
4!
531
        lmd.Name = $"{this.Name} - {DateTime.Now}";
4✔
532
        lmd.SaveToDatabase();
4✔
533
        return lmd;
4✔
534
    }
535
}
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