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

HicServices / RDMP / 7194961165

13 Dec 2023 12:07PM UTC coverage: 56.776% (-0.2%) from 57.013%
7194961165

push

github

web-flow
Merge Latest Release into main (#1702)

* Bump YamlDotNet from 13.3.1 to 13.4.0

Bumps [YamlDotNet](https://github.com/aaubry/YamlDotNet) from 13.3.1 to 13.4.0.
- [Release notes](https://github.com/aaubry/YamlDotNet/releases)
- [Commits](https://github.com/aaubry/YamlDotNet/compare/v13.3.1...v13.4.0)

---
updated-dependencies:
- dependency-name: YamlDotNet
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

* Bump shogo82148/actions-setup-perl from 1.23.1 to 1.24.1

Bumps [shogo82148/actions-setup-perl](https://github.com/shogo82148/actions-setup-perl) from 1.23.1 to 1.24.1.
- [Release notes](https://github.com/shogo82148/actions-setup-perl/releases)
- [Commits](https://github.com/shogo82148/actions-setup-perl/compare/v1.23.1...v1.24.1)

---
updated-dependencies:
- dependency-name: shogo82148/actions-setup-perl
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

* fix checkbox issue

* improve confirmation text (#1639)

* improve confirmation text
* Loop tidyup, use var where possible

---------

Co-authored-by: jas88 <j.a.sutherland@dundee.ac.uk>

* correct typo in create logging sql (#1640)

* Feature/ci codescan (#1641)

* Move SecurityCodescan.VS2019 to run on Github CI alone, integrate results with CodeQL
* Remove SecurityCodescan from Packages.md, no longer used via Nuget

---------

Co-authored-by: James A Sutherland <j@sutherland.pw>

* hide source control when not available

* Remove old Plugin object bits, tidy up (#1636)

* Remove old Plugin object bits, tidy up

* Purge remaining bits of AllExpiredPluginsNode

* Fix plugin display name in tree

* Update CreateNewDataExtractionProjectUI.cs

Casting fix

* Feature/rdmp42 delete plugins (#1642)

* add ui plugin delete functionality

* Warning and inherita... (continued)

10722 of 20351 branches covered (0.0%)

Branch coverage included in aggregate %.

215 of 789 new or added lines in 63 files covered. (27.25%)

39 existing lines in 16 files now uncovered.

30650 of 52518 relevant lines covered (58.36%)

7294.17 hits per line

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

82.15
/Rdmp.Core/Repositories/MemoryCatalogueRepository.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.Collections.Generic;
9
using System.Linq;
10
using Rdmp.Core.Curation.Data;
11
using Rdmp.Core.Curation.Data.Aggregation;
12
using Rdmp.Core.Curation.Data.Cohort;
13
using Rdmp.Core.Curation.Data.Defaults;
14
using Rdmp.Core.Curation.Data.Governance;
15
using Rdmp.Core.Curation.Data.Referencing;
16
using Rdmp.Core.DataExport;
17
using Rdmp.Core.Logging;
18
using Rdmp.Core.MapsDirectlyToDatabaseTable;
19
using Rdmp.Core.MapsDirectlyToDatabaseTable.Versioning;
20
using Rdmp.Core.Providers.Nodes;
21
using Rdmp.Core.Repositories.Managers;
22
using Rdmp.Core.ReusableLibraryCode.Annotations;
23
using Rdmp.Core.ReusableLibraryCode.Comments;
24
using Rdmp.Core.ReusableLibraryCode.DataAccess;
25
using Rdmp.Core.ReusableLibraryCode.Settings;
26
using Rdmp.Core.Sharing.Dependency;
27
using Rdmp.Core.Validation.Dependency;
28
using IContainer = Rdmp.Core.Curation.Data.IContainer;
29

30
namespace Rdmp.Core.Repositories;
31

32
/// <summary>
33
/// Memory only implementation of <see cref="ICatalogueRepository"/> in which all objects are created in
34
/// dictionaries and arrays in memory instead of the database.
35
/// </summary>
36
public class MemoryCatalogueRepository : MemoryRepository, ICatalogueRepository, ITableInfoCredentialsManager,
37
    IAggregateForcedJoinManager, ICohortContainerManager, IFilterManager, IGovernanceManager
38
{
39
    public IAggregateForcedJoinManager AggregateForcedJoinManager => this;
68✔
40
    public IGovernanceManager GovernanceManager => this;
658✔
41
    public ITableInfoCredentialsManager TableInfoCredentialsManager => this;
688✔
42
    public ICohortContainerManager CohortContainerManager => this;
1,232✔
43
    public IEncryptionManager EncryptionManager { get; private set; }
1,800✔
44

45
    public IFilterManager FilterManager => this;
1,342✔
46

47
    public IJoinManager JoinManager { get; private set; }
462✔
48

49
    public CommentStore CommentStore { get; set; }
1,080✔
50

51
    private IObscureDependencyFinder _odf;
52

53
    public IObscureDependencyFinder ObscureDependencyFinder
54
    {
55
        get => _odf;
1,024✔
56
        set
57
        {
58
            _odf = value;
434✔
59
            if (_odf is CatalogueObscureDependencyFinder catFinder &&
434✔
60
                this is IDataExportRepository dataExportRepository)
434✔
61
                catFinder.AddOtherDependencyFinderIfNotExists<ValidationXMLObscureDependencyFinder>(
290✔
62
                    new RepositoryProvider(dataExportRepository));
290✔
63
        }
434✔
64
    }
65

66
    /// <summary>
67
    /// Path to RSA private key encryption certificate for decrypting encrypted credentials.
68
    /// </summary>
69
    public string EncryptionKeyPath { get; protected set; }
676✔
70

71
    protected virtual Dictionary<PermissableDefaults, IExternalDatabaseServer> Defaults { get; set; } = new();
7,210✔
72

73
    public MemoryCatalogueRepository(IServerDefaults currentDefaults = null)
434✔
74
    {
75
        JoinManager = new JoinManager(this);
434✔
76
        CommentStore = new CommentStoreWithKeywords();
434✔
77
        EncryptionManager = new PasswordEncryptionKeyLocation(this);
434✔
78

79
        //we need to know what the default servers for stuff are
80
        foreach (PermissableDefaults value in Enum.GetValues(typeof(PermissableDefaults)))
7,812✔
81
            if (currentDefaults == null)
3,472✔
82
            {
83
                Defaults.Add(value, null); //we have no defaults to import
3,392✔
84
            }
85
            else
86
            {
87
                //we have defaults to import so get the default
88
                var defaultServer = currentDefaults.GetDefaultFor(value);
80✔
89

90
                //if it's not null we must be able to return it with GetObjectByID
91
                if (defaultServer != null)
80✔
92
                    Objects.TryAdd(defaultServer, 0);
30✔
93

94
                Defaults.Add(value, defaultServer);
80✔
95
            }
96

97
        //start IDs with the maximum id of any default to avoid collisions
98
        if (Objects.Any())
434✔
99
            NextObjectId = Objects.Keys.Max(o => o.ID);
40✔
100

101

102
        var dependencyFinder = new CatalogueObscureDependencyFinder(this);
434✔
103

104
        if (this is IDataExportRepository dxm)
434✔
105
        {
106
            dependencyFinder.AddOtherDependencyFinderIfNotExists<ObjectSharingObscureDependencyFinder>(
290✔
107
                new RepositoryProvider(dxm));
290✔
108
            dependencyFinder.AddOtherDependencyFinderIfNotExists<BetweenCatalogueAndDataExportObscureDependencyFinder>(
290✔
109
                new RepositoryProvider(dxm));
290✔
110
        }
111

112
        ObscureDependencyFinder = dependencyFinder;
434✔
113
    }
434✔
114

115

116
    public LogManager GetDefaultLogManager()
117
    {
118
        var server = GetDefaultFor(PermissableDefaults.LiveLoggingServer_ID);
×
119
        return server == null ? null : new LogManager(server);
×
120
    }
121

122
    public IEnumerable<AnyTableSqlParameter> GetAllParametersForParentTable(IMapsDirectlyToDatabaseTable parent)
123
    {
124
        return GetAllObjects<AnyTableSqlParameter>().Where(o => o.IsReferenceTo(parent));
156✔
125
    }
126

127
    public TicketingSystemConfiguration GetTicketingSystem() => null;
38✔
128

129

130
    public override void DeleteFromDatabase(IMapsDirectlyToDatabaseTable oTableWrapperObject)
131
    {
132
        ObscureDependencyFinder.ThrowIfDeleteDisallowed(oTableWrapperObject);
510✔
133

134

135
        base.DeleteFromDatabase(oTableWrapperObject);
510✔
136
        ObscureDependencyFinder.HandleCascadeDeletesForDeletedObject(oTableWrapperObject);
510✔
137
    }
510✔
138

139
    public T[] GetReferencesTo<T>(IMapsDirectlyToDatabaseTable o) where T : ReferenceOtherObjectDatabaseEntity
140
    {
141
        return Objects.Keys.OfType<T>().Where(r => r.IsReferenceTo(o)).ToArray();
1,198✔
142
    }
143

144
    public bool IsLookupTable(ITableInfo tableInfo)
145
    {
146
        return GetAllObjects<Lookup>().Any(l => l.Description.TableInfo.Equals(tableInfo));
102✔
147
    }
148

149
    public Catalogue[] GetAllCataloguesUsing(TableInfo tableInfo)
150
    {
151
        return
18✔
152
            GetAllObjects<Catalogue>()
18✔
153
                .Where(
18✔
154
                    c =>
18✔
155
                        c.CatalogueItems.Any(
36✔
156
                            ci => ci.ColumnInfo_ID != null && ci.ColumnInfo.TableInfo_ID == tableInfo.ID)).ToArray();
54!
157
    }
158

159
    public ExternalDatabaseServer[] GetAllDatabases<T>() where T : IPatcher, new()
160
    {
161
        IPatcher p = new T();
26✔
162
        return GetAllObjects<ExternalDatabaseServer>().Where(s => s.WasCreatedBy(p)).ToArray();
66✔
163
    }
164

165
    public IExternalDatabaseServer GetDefaultFor(PermissableDefaults field) =>
166
        Defaults.TryGetValue(field, out var result) ? result : null;
3,294!
167

168
    public void ClearDefault(PermissableDefaults toDelete)
169
    {
170
        SetDefault(toDelete, null);
×
171
    }
×
172

173
    public virtual void SetDefault(PermissableDefaults toChange, IExternalDatabaseServer externalDatabaseServer)
174
    {
175
        Defaults[toChange] = externalDatabaseServer;
6✔
176
    }
6✔
177

178
    public override void Clear()
179
    {
UNCOV
180
        base.Clear();
×
181

UNCOV
182
        CohortContainerContents.Clear();
×
UNCOV
183
        CredentialsDictionary.Clear();
×
UNCOV
184
        ForcedJoins.Clear();
×
UNCOV
185
        WhereSubContainers.Clear();
×
UNCOV
186
        Defaults.Clear();
×
UNCOV
187
    }
×
188

189
    #region ITableInfoToCredentialsLinker
190

191
    /// <summary>
192
    /// records which credentials can be used to access the table under which contexts
193
    /// </summary>
194
    protected Dictionary<ITableInfo, Dictionary<DataAccessContext, DataAccessCredentials>> CredentialsDictionary
195
    {
196
        get;
718✔
197
        set;
2✔
198
    } =
199
        new();
434✔
200

201
    public virtual void CreateLinkBetween(DataAccessCredentials credentials, ITableInfo tableInfo,
202
        DataAccessContext context)
203
    {
204
        if (!CredentialsDictionary.ContainsKey(tableInfo))
4✔
205
            CredentialsDictionary.Add(tableInfo, new Dictionary<DataAccessContext, DataAccessCredentials>());
4✔
206

207
        CredentialsDictionary[tableInfo].Add(context, credentials);
4✔
208

209
        tableInfo.ClearAllInjections();
4✔
210
    }
4✔
211

212
    public virtual void BreakLinkBetween(DataAccessCredentials credentials, ITableInfo tableInfo,
213
        DataAccessContext context)
214
    {
NEW
215
        if (!CredentialsDictionary.TryGetValue(tableInfo, out var credentialsMap))
×
216
            return;
×
217

NEW
218
        credentialsMap.Remove(context);
×
219

220
        tableInfo.ClearAllInjections();
×
221
    }
×
222

223
    public virtual void BreakAllLinksBetween(DataAccessCredentials credentials, ITableInfo tableInfo)
224
    {
NEW
225
        if (!CredentialsDictionary.TryGetValue(tableInfo, out var credentialsMap))
×
226
            return;
×
227

NEW
228
        var toRemove = credentialsMap.Where(v => Equals(v.Value, credentials)).Select(k => k.Key)
×
229
            .ToArray();
×
230

231
        foreach (var context in toRemove)
×
NEW
232
            credentialsMap.Remove(context);
×
233
    }
×
234

235
    public DataAccessCredentials GetCredentialsIfExistsFor(ITableInfo tableInfo, DataAccessContext context)
236
    {
237
        if (!CredentialsDictionary.TryGetValue(tableInfo, out var credentialsList)) return null;
68✔
238
        if (credentialsList.TryGetValue(context, out var credentials))
8✔
239
            return credentials;
4✔
240
        return credentialsList.TryGetValue(DataAccessContext.Any, out credentials) ? credentials : null;
4!
241
    }
242

243
    public Dictionary<DataAccessContext, DataAccessCredentials> GetCredentialsIfExistsFor(ITableInfo tableInfo) =>
244
        CredentialsDictionary.TryGetValue(tableInfo, out var credential) ? credential : null;
×
245

246
    public Dictionary<ITableInfo, List<DataAccessCredentialUsageNode>> GetAllCredentialUsagesBy(
247
        DataAccessCredentials[] allCredentials, ITableInfo[] allTableInfos)
248
    {
249
        var toreturn = new Dictionary<ITableInfo, List<DataAccessCredentialUsageNode>>();
638✔
250

251
        foreach (var kvp in CredentialsDictionary)
1,276!
252
        {
253
            toreturn.Add(kvp.Key, new List<DataAccessCredentialUsageNode>());
×
254

255
            foreach (var forNode in kvp.Value)
×
256
                toreturn[kvp.Key].Add(new DataAccessCredentialUsageNode(forNode.Value, kvp.Key, forNode.Key));
×
257
        }
258

259
        return toreturn;
638✔
260
    }
261

262
    public Dictionary<DataAccessContext, List<ITableInfo>> GetAllTablesUsingCredentials(
263
        DataAccessCredentials credentials)
264
    {
265
        var toreturn = Enum.GetValues(typeof(DataAccessContext)).Cast<DataAccessContext>()
6✔
266
            .ToDictionary(context => context, _ => new List<ITableInfo>());
66✔
267

268
        //add the keys
269

270
        foreach (var kvp in CredentialsDictionary)
20✔
271
            foreach (var forNode in kvp.Value)
16✔
272
                toreturn[forNode.Key].Add(kvp.Key);
4✔
273

274
        return toreturn;
6✔
275
    }
276

277
    public DataAccessCredentials GetCredentialByUsernameAndPasswordIfExists(string username, string password)
278
    {
279
        return GetAllObjects<DataAccessCredentials>().FirstOrDefault(c =>
2✔
280
            Equals(c.Username, username) && Equals(c.GetDecryptedPassword(), password));
2!
281
    }
282

283
    #endregion
284

285
    #region IAggregateForcedJoin
286

287
    protected Dictionary<AggregateConfiguration, HashSet<ITableInfo>> ForcedJoins { get; set; } = new();
556✔
288

289
    public ITableInfo[] GetAllForcedJoinsFor(AggregateConfiguration configuration)
290
    {
291
        var everyone =
64!
292
            // join with everyone? .... what do you mean everyone? EVERYONE!!!!
64✔
293
            UserSettings.AlwaysJoinEverything
64✔
294
                ? configuration.Catalogue.GetTableInfosIdeallyJustFromMainTables()
64✔
295
                : Enumerable.Empty<ITableInfo>();
64✔
296

297
        return !ForcedJoins.TryGetValue(configuration, out var forced) ? everyone.ToArray()
64✔
298
            : forced.Union(everyone).ToArray();
64✔
299
    }
300

301
    public virtual void BreakLinkBetween([NotNull] AggregateConfiguration configuration, ITableInfo tableInfo)
302
    {
NEW
303
        if (ForcedJoins.TryGetValue(configuration, out var value)) value.Remove(tableInfo);
×
304
    }
×
305

306
    public virtual void CreateLinkBetween([NotNull] AggregateConfiguration configuration, ITableInfo tableInfo)
307
    {
308
        if (!ForcedJoins.TryGetValue(configuration,out var forced))
4✔
309
            ForcedJoins.Add(configuration, forced=new HashSet<ITableInfo>());
4✔
310

311
        forced.Add(tableInfo);
4✔
312
    }
4✔
313

314
    #endregion
315

316
    #region ICohortContainerLinker
317

318
    protected Dictionary<CohortAggregateContainer, HashSet<CohortContainerContent>> CohortContainerContents =
434✔
319
        new();
434✔
320

321
    public CohortAggregateContainer GetParent(AggregateConfiguration child)
322
    {
323
        //if it is in the contents of a container
324
        return CohortContainerContents.Any(kvp => kvp.Value.Select(c => c.Orderable).Contains(child))
540✔
325
            ? CohortContainerContents.Single(kvp => kvp.Value.Select(c => c.Orderable).Contains(child)).Key
324✔
326
            : null;
160✔
327
    }
328

329
    public virtual void Add(CohortAggregateContainer parent, AggregateConfiguration child, int order)
330
    {
331
        //make sure we know about the container
332
        if (!CohortContainerContents.ContainsKey(parent))
70✔
333
            CohortContainerContents.Add(parent, new HashSet<CohortContainerContent>());
46✔
334

335
        CohortContainerContents[parent].Add(new CohortContainerContent(child, order));
70✔
336
    }
70✔
337

338
    public virtual void Remove(CohortAggregateContainer parent, AggregateConfiguration child)
339
    {
340
        var toRemove = CohortContainerContents[parent].Single(c => c.Orderable.Equals(child));
38✔
341
        CohortContainerContents[parent].Remove(toRemove);
14✔
342
    }
14✔
343

344
    public class CohortContainerContent
345
    {
346
        public IOrderable Orderable { get; private set; }
3,334✔
347

348
        public int Order { get; set; }
1,592✔
349

350
        public CohortContainerContent(IOrderable orderable, int order)
98✔
351
        {
352
            Orderable = orderable;
98✔
353
            Order = order;
98✔
354
        }
98✔
355
    }
356

357
    public int? GetOrderIfExistsFor(AggregateConfiguration configuration)
358
    {
359
        var o = CohortContainerContents.SelectMany(kvp => kvp.Value)
898✔
360
            .SingleOrDefault(c => c.Orderable.Equals(configuration));
1,136✔
361

362
        return o?.Order;
142✔
363
    }
364

365
    public IOrderable[] GetChildren(CohortAggregateContainer parent)
366
    {
367
        return !CohortContainerContents.TryGetValue(parent, out var cohortContainerContents) ?
1,752✔
368
            Array.Empty<IOrderable>()
1,752✔
369
            : cohortContainerContents.OrderBy(static o => o.Order).Select(static o => o.Orderable).ToArray();
4,560✔
370
    }
371

372
    public CohortAggregateContainer GetParent(CohortAggregateContainer child)
373
    {
374
        var match = CohortContainerContents.Where(k => k.Value.Any(hs => Equals(hs.Orderable, child)))
744✔
375
            .Select(static kvp => kvp.Key).ToArray();
56✔
376
        return match.Length > 0 ? match.Single() : null;
40✔
377
    }
378

379
    public virtual void Remove(CohortAggregateContainer parent, CohortAggregateContainer child)
380
    {
381
        CohortContainerContents[parent].RemoveWhere(c => Equals(c.Orderable, child));
×
382
    }
×
383

384
    public virtual void SetOrder(AggregateConfiguration child, int newOrder)
385
    {
386
        var parent = GetParent(child);
12✔
387

388
        if (parent != null && CohortContainerContents.TryGetValue(parent, out var cohortContainerContent))
12✔
389
        {
390
            var record = cohortContainerContent.SingleOrDefault(o => o.Orderable.Equals(child));
26✔
391
            if (record != null)
12✔
392
                record.Order = newOrder;
12✔
393
        }
394
    }
12✔
395

396
    public virtual void Add(CohortAggregateContainer parent, CohortAggregateContainer child)
397
    {
398
        if (!CohortContainerContents.ContainsKey(parent))
24✔
399
            CohortContainerContents.Add(parent, new HashSet<CohortContainerContent>());
22✔
400

401
        CohortContainerContents[parent].Add(new CohortContainerContent(child, child.Order));
24✔
402
    }
24✔
403

404
    #endregion
405

406

407
    #region IFilterContainerManager
408

409
    protected Dictionary<IContainer, HashSet<IContainer>> WhereSubContainers { get; set; } = new();
964✔
410

411
    [NotNull]
412
    public IContainer[] GetSubContainers(IContainer container) =>
413
        !WhereSubContainers.TryGetValue(container, out var containers)
438✔
414
            ? Array.Empty<IContainer>()
438✔
415
        : containers.ToArray();
438✔
416

417
    public virtual void MakeIntoAnOrphan(IContainer container)
418
    {
419
        foreach (var contents in WhereSubContainers)
32✔
420
            contents.Value.Remove(container);
4✔
421
    }
12✔
422

423
    [CanBeNull]
424
    public IContainer GetParentContainerIfAny(IContainer container)
425
    {
426
        return WhereSubContainers.FirstOrDefault(k => k.Value.Contains(container)).Key;
22✔
427
    }
428

429
    public IFilter[] GetFilters(IContainer container)
430
    {
431
        return GetAllObjects<IFilter>().Where(f => f is not ExtractionFilter && f.FilterContainer_ID == container.ID)
1,758✔
432
            .ToArray();
444✔
433
    }
434

435
    public void AddChild(IContainer container, IFilter filter)
436
    {
437
        filter.FilterContainer_ID = container.ID;
78✔
438
        filter.SaveToDatabase();
78✔
439
    }
78✔
440

441
    public virtual void AddSubContainer(IContainer parent, IContainer child)
442
    {
443
        if (!WhereSubContainers.ContainsKey(parent))
16✔
444
            WhereSubContainers.Add(parent, new HashSet<IContainer>());
10✔
445

446
        WhereSubContainers[parent].Add(child);
16✔
447
    }
16✔
448

449
    #endregion
450

451
    #region IGovernanceManager
452

453
    protected Dictionary<GovernancePeriod, HashSet<ICatalogue>> GovernanceCoverage { get; set; } = new();
1,154✔
454

455
    public virtual void Unlink(GovernancePeriod governancePeriod, ICatalogue catalogue)
456
    {
457
        if (!GovernanceCoverage.ContainsKey(governancePeriod))
2!
458
            GovernanceCoverage.Add(governancePeriod, new HashSet<ICatalogue>());
×
459

460
        GovernanceCoverage[governancePeriod].Remove(catalogue);
2✔
461
    }
2✔
462

463
    public virtual void Link(GovernancePeriod governancePeriod, ICatalogue catalogue)
464
    {
465
        if (!GovernanceCoverage.ContainsKey(governancePeriod))
4✔
466
            GovernanceCoverage.Add(governancePeriod, new HashSet<ICatalogue>());
4✔
467

468
        GovernanceCoverage[governancePeriod].Add(catalogue);
4✔
469
    }
4✔
470

471
    public Dictionary<int, HashSet<int>> GetAllGovernedCataloguesForAllGovernancePeriods()
472
    {
473
        return GovernanceCoverage.ToDictionary(static k => k.Key.ID,
638✔
474
            static v => new HashSet<int>(v.Value.Select(static c => c.ID)));
638✔
475
    }
476

477
    public IEnumerable<ICatalogue> GetAllGovernedCatalogues(GovernancePeriod governancePeriod) =>
478
        !GovernanceCoverage.TryGetValue(governancePeriod, out var governedCatalogues) ? Enumerable.Empty<ICatalogue>()
16✔
479
            : governedCatalogues;
16✔
480

481
    #endregion
482

483
    #region IEncryptionManager
484

485
    public virtual void SetEncryptionKeyPath(string fullName)
486
    {
487
        EncryptionKeyPath = fullName;
×
488
    }
×
489

490
    public string GetEncryptionKeyPath() => EncryptionKeyPath;
676✔
491

492
    public virtual void DeleteEncryptionKeyPath()
493
    {
494
        EncryptionKeyPath = null;
×
495
    }
×
496

497
    #endregion
498

499
    protected override void CascadeDeletes(IMapsDirectlyToDatabaseTable oTableWrapperObject)
500
    {
501
        base.CascadeDeletes(oTableWrapperObject);
510✔
502

503
        switch (oTableWrapperObject)
504
        {
505
            case Catalogue catalogue:
506
                {
507
                    foreach (var ci in catalogue.CatalogueItems) ci.DeleteInDatabase();
616✔
508

509
                    break;
230✔
510
                }
511
            case ExtractionInformation extractionInformation:
512
                extractionInformation.CatalogueItem.ClearAllInjections();
16✔
513
                break;
16✔
514
            // when deleting a TableInfo
515
            case TableInfo t:
516
                {
517
                    // forget about its credentials usages
518
                    CredentialsDictionary.Remove(t);
20✔
519

520
                    foreach (var c in t.ColumnInfos) c.DeleteInDatabase();
112✔
521

522
                    break;
20✔
523
                }
524
            // when deleting a ColumnInfo
525
            case ColumnInfo columnInfo:
526
                {
527
                    foreach (var ci in Objects.Keys.OfType<CatalogueItem>().Where(ci => ci.ColumnInfo_ID == columnInfo.ID))
190✔
528
                    {
529
                        ci.ColumnInfo_ID = null;
14✔
530
                        ci.ClearAllInjections();
14✔
531
                        ci.SaveToDatabase();
14✔
532
                    }
533

534
                    break;
535
                }
536
            case CatalogueItem catalogueItem:
537
                catalogueItem.ExtractionInformation?.DeleteInDatabase();
58✔
538
                break;
539
        }
540
    }
56✔
541

542
    /// <inheritdoc/>
543
    public IEnumerable<ExtendedProperty> GetExtendedProperties(string propertyName, IMapsDirectlyToDatabaseTable obj)
544
    {
545
        return GetAllObjectsWhere<ExtendedProperty>("Name", propertyName)
38✔
546
            .Where(r => r.IsReferenceTo(obj));
56✔
547
    }
548

549
    /// <inheritdoc/>
550
    public IEnumerable<ExtendedProperty> GetExtendedProperties(string propertyName) =>
551
        GetAllObjectsWhere<ExtendedProperty>("Name", propertyName);
638✔
552

553
    /// <inheritdoc/>
554
    public IEnumerable<ExtendedProperty> GetExtendedProperties(IMapsDirectlyToDatabaseTable obj)
555
    {
556
        // First pass use SQL to pull only those with ReferencedObjectID ID that match our object
557
        return GetAllObjectsWhere<ExtendedProperty>("ReferencedObjectID", obj.ID)
12✔
558
            // Second pass make sure the object/repo match
12✔
559
            .Where(r => r.IsReferenceTo(obj));
16✔
560
    }
561
}
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