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

HicServices / RDMP / 16004090609

01 Jul 2025 03:47PM UTC coverage: 57.442% (+0.1%) from 57.314%
16004090609

Pull #2205

github

JFriel
add db change
Pull Request #2205: Multi-Project Catalogues

11417 of 21406 branches covered (53.34%)

Branch coverage included in aggregate %.

71 of 100 new or added lines in 8 files covered. (71.0%)

27 existing lines in 1 file now uncovered.

32373 of 54827 relevant lines covered (59.05%)

8775.92 hits per line

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

51.91
/Rdmp.Core/CommandExecution/GoToCommandFactory.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.Linq;
10
using Rdmp.Core.CommandExecution.AtomicCommands;
11
using Rdmp.Core.Curation.Data;
12
using Rdmp.Core.Curation.Data.Aggregation;
13
using Rdmp.Core.Curation.Data.Cohort;
14
using Rdmp.Core.Curation.Data.Dashboarding;
15
using Rdmp.Core.Curation.Data.DataLoad;
16
using Rdmp.Core.Curation.Data.Governance;
17
using Rdmp.Core.Curation.Data.ImportExport;
18
using Rdmp.Core.DataExport.Data;
19
using Rdmp.Core.Icons.IconProvision;
20
using Rdmp.Core.MapsDirectlyToDatabaseTable;
21
using Rdmp.Core.MapsDirectlyToDatabaseTable.Injection;
22
using Rdmp.Core.Providers;
23
using SixLabors.ImageSharp;
24
using SixLabors.ImageSharp.PixelFormats;
25

26
namespace Rdmp.Core.CommandExecution;
27

28
/// <summary>
29
/// Builds the "Go To" submenu for travelling between objects in an RDMP database (e.g. Catalogue to extractions using the Catalogue)
30
/// </summary>
31
public class GoToCommandFactory : CommandFactoryBase
32
{
33
    private readonly IBasicActivateItems _activator;
34
    public const string GoTo = "Go To";
35

36
    public GoToCommandFactory(IBasicActivateItems activator)
99✔
37
    {
38
        _activator = activator;
99✔
39
    }
99✔
40

41
    public IEnumerable<IAtomicCommand> GetCommands(object forObject)
42
    {
43
        //forget old values, get them up to the minute
44
        if (Is(forObject, out IInjectKnown ii))
99✔
45
            ii.ClearAllInjections();
45✔
46

47
        if (Is(forObject, out IMapsDirectlyToDatabaseTable mt))
99✔
48
        {
49
            // Go to import / export definitions
50
            var export = _activator.RepositoryLocator.CatalogueRepository.GetReferencesTo<ObjectExport>(mt)
96✔
51
                .FirstOrDefault();
96✔
52

53
            if (export != null)
96!
54
                yield return new ExecuteCommandShow(_activator, export, 0, true)
×
55
                { OverrideCommandName = "Show Export Definition" };
×
56

57
            var import = _activator.RepositoryLocator.CatalogueRepository.GetReferencesTo<ObjectImport>(mt)
96✔
58
                .FirstOrDefault();
96✔
59
            if (import != null)
96!
60
                yield return new ExecuteCommandShow(_activator, import, 0)
×
61
                { OverrideCommandName = "Show Import Definition" };
×
62

63
            if (SupportsReplacement(forObject))
96✔
64
                yield return new ExecuteCommandShow(_activator, () => GetReplacementIfAny(mt))
95✔
65
                { OverrideCommandName = "Replacement" };
95✔
66

67

68
            yield return new ExecuteCommandSimilar(_activator, mt, false) { GoTo = true };
96✔
69
        }
70

71
        // cic => associated projects
72
        if (Is(forObject, out CohortIdentificationConfiguration cic))
99✔
73
            yield return new ExecuteCommandShow(_activator, () =>
1✔
74
            {
1✔
75
                return _activator.CoreChildProvider is DataExportChildProvider { AllProjectAssociatedCics: not null } dx
×
76
                    ? dx.AllProjectAssociatedCics.Where(a => a.CohortIdentificationConfiguration_ID == cic.ID)
×
77
                        .Select(a => a.Project).Distinct()
×
78
                    : Array.Empty<CohortIdentificationConfiguration>();
×
79
            })
1✔
80
            {
1✔
81
                OverrideCommandName = "Project(s)",
1✔
82
                OverrideIcon = GetImage(RDMPConcept.Project)
1✔
83
            };
1✔
84

85
        if (Is(forObject, out ColumnInfo columnInfo))
99✔
86
        {
87
            yield return new ExecuteCommandSimilar(_activator, columnInfo, true)
2✔
88
            {
2✔
89
                OverrideCommandName = "Different",
2✔
90
                GoTo = true,
2✔
91
                OverrideIcon = GetImage(RDMPConcept.ColumnInfo)
2✔
92
            };
2✔
93

94
            yield return new ExecuteCommandShow(_activator, columnInfo.TableInfo_ID, typeof(TableInfo))
2✔
95
            {
2✔
96
                OverrideCommandName = "Table Info",
2✔
97
                OverrideIcon = GetImage(RDMPConcept.TableInfo)
2✔
98
            };
2✔
99
            yield return new ExecuteCommandShow(_activator,
2✔
100
                () => _activator.CoreChildProvider.AllCatalogueItems.Where(catItem =>
×
101
                    catItem.ColumnInfo_ID == columnInfo.ID))
×
102
            {
2✔
103
                OverrideCommandName = "Catalogue Item(s)",
2✔
104
                OverrideIcon = GetImage(RDMPConcept.CatalogueItem)
2✔
105
            };
2✔
106

107
            yield return new ExecuteCommandShow(_activator, columnInfo.ANOTable_ID, typeof(ANOTable))
2✔
108
            {
2✔
109
                OverrideCommandName = "ANO Table",
2✔
110
                OverrideIcon = GetImage(RDMPConcept.ANOTable)
2✔
111
            };
2✔
112
        }
113

114
        if (Is(forObject, out ExtractionInformation ei))
99✔
115
        {
116
            yield return new ExecuteCommandShow(_activator, ei.CatalogueItem?.Catalogue_ID, typeof(Catalogue))
1!
117
            {
1✔
118
                OverrideCommandName = "Catalogue",
1✔
119
                OverrideIcon = GetImage(RDMPConcept.Catalogue)
1✔
120
            };
1✔
121
            yield return new ExecuteCommandShow(_activator, ei.CatalogueItem_ID, typeof(CatalogueItem))
1✔
122
            {
1✔
123
                OverrideCommandName = "Catalogue Item",
1✔
124
                OverrideIcon = GetImage(RDMPConcept.CatalogueItem)
1✔
125
            };
1✔
126
            yield return new ExecuteCommandShow(_activator, ei.ColumnInfo, 0, true)
1✔
127
            {
1✔
128
                OverrideCommandName = "Column Info",
1✔
129
                OverrideIcon = GetImage(RDMPConcept.ColumnInfo)
1✔
130
            };
1✔
131
        }
132

133
        if (Is(forObject, out CatalogueItem ci))
99✔
134
        {
135
            yield return new ExecuteCommandShow(_activator, ci.Catalogue_ID, typeof(Catalogue))
7✔
136
            {
7✔
137
                OverrideCommandName = "Catalogue",
7✔
138
                OverrideIcon = GetImage(RDMPConcept.Catalogue)
7✔
139
            };
7✔
140
            yield return new ExecuteCommandShow(_activator, ci.ExtractionInformation, 0, true)
7✔
141
            {
7✔
142
                OverrideCommandName = "Extraction Information",
7✔
143
                OverrideIcon = GetImage(RDMPConcept.ExtractionInformation)
7✔
144
            };
7✔
145
            yield return new ExecuteCommandShow(_activator, ci.ColumnInfo, 0, true)
7✔
146
            {
7✔
147
                OverrideCommandName = "Column Info",
7✔
148
                OverrideIcon = GetImage(RDMPConcept.ColumnInfo)
7✔
149
            };
7✔
150
        }
151

152
        if (Is(forObject, out ExtractableDataSet eds))
99!
153
        {
154
            yield return new ExecuteCommandShow(_activator, eds.Catalogue_ID, typeof(Catalogue))
×
155
            {
×
156
                OverrideCommandName = "Catalogue",
×
157
                OverrideIcon = GetImage(RDMPConcept.Catalogue)
×
158
            };
×
159

160
            yield return new ExecuteCommandShow(_activator, () =>
×
161
            {
×
162
                return _activator.CoreChildProvider is DataExportChildProvider dx
×
163
                    ? dx.SelectedDataSets.Where(s => s.ExtractableDataSet_ID == eds.ID)
×
164
                        .Select(s => s.ExtractionConfiguration)
×
165
                    : Array.Empty<SelectedDataSets>();
×
166
            })
×
167
            {
×
168
                OverrideCommandName = "Extraction Configuration(s)",
×
169
                OverrideIcon = GetImage(RDMPConcept.ExtractionConfiguration)
×
170
            };
×
171
        }
172

173
        if (Is(forObject, out GovernancePeriod period))
99✔
174
            yield return new ExecuteCommandShow(_activator, () => period.GovernedCatalogues)
1✔
175
            { OverrideCommandName = "Catalogue(s)", OverrideIcon = GetImage(RDMPConcept.Catalogue) };
1✔
176

177
        if (Is(forObject, out JoinInfo j))
99!
178
            yield return new ExecuteCommandShow(_activator, j.ForeignKey_ID, typeof(ColumnInfo))
×
179
            { OverrideCommandName = "Foreign Key", OverrideIcon = GetImage(RDMPConcept.ColumnInfo) };
×
180

181
        if (Is(forObject, out Lookup lookup))
99✔
182
        {
183
            yield return new ExecuteCommandShow(_activator, lookup.Description.TableInfo_ID, typeof(TableInfo));
3✔
184
            yield return new ExecuteCommandShow(_activator, lookup.ForeignKey_ID, typeof(ColumnInfo))
3✔
185
            { OverrideCommandName = "Foreign Key", OverrideIcon = GetImage(RDMPConcept.ColumnInfo) };
3✔
186
        }
187

188
        if (Is(forObject, out ExtractionFilter masterFilter))
99!
189
        {
190
            yield return new ExecuteCommandShow(_activator, () =>
×
191
                _activator.RepositoryLocator.CatalogueRepository
×
192
                    .GetAllObjectsWhere<AggregateFilter>("ClonedFromExtractionFilter_ID", masterFilter.ID)
×
193
                    .Select(f => f.GetAggregate())
×
194
                    .Where(a => a != null).Distinct()
×
195
            )
×
196
            { OverrideCommandName = "Usages (in Cohort Builder)" };
×
197

198

199
            yield return new ExecuteCommandShow(_activator, () =>
×
200
                _activator.RepositoryLocator.DataExportRepository
×
201
                    .GetAllObjectsWhere<DeployedExtractionFilter>("ClonedFromExtractionFilter_ID", masterFilter.ID)
×
202
                    .Select(f => f.GetDataset()?.ExtractionConfiguration)
×
203
                    .Where(c => c != null).Distinct()
×
204
            )
×
205
            { OverrideCommandName = "Usages (in Extractions)" };
×
206
        }
207

208
        if (Is(forObject, out IFilter filter) && filter.ClonedFromExtractionFilter_ID.HasValue)
99!
209
        {
210
            ExtractionFilter parent = null;
×
211

212
            try
213
            {
214
                parent = _activator.RepositoryLocator.CatalogueRepository.GetObjectByID<ExtractionFilter>(
×
215
                    filter.ClonedFromExtractionFilter_ID.Value);
×
216
            }
×
217
            catch (KeyNotFoundException)
×
218
            {
219
                // new ImpossibleCommand("Parent filter has been deleted") { OverrideCommandName = "Parent Filter" };
220
            }
×
221

222
            if (parent != null)
×
223
                yield return new ExecuteCommandShow(_activator, parent, 0)
×
224
                { OverrideCommandName = "Parent Filter", OverrideIcon = GetImage(RDMPConcept.Filter) };
×
225
        }
226

227
        if (Is(forObject, out SelectedDataSets selectedDataSet))
99✔
228
        {
229
            yield return new ExecuteCommandShow(_activator, selectedDataSet.ExtractableDataSet.Catalogue_ID,
7✔
230
                typeof(Catalogue))
7✔
231
            {
7✔
232
                OverrideCommandName = "Catalogue",
7✔
233
                OverrideIcon = GetImage(RDMPConcept.Catalogue)
7✔
234
            };
7✔
235

236
            var ep = selectedDataSet.ExtractionProgressIfAny;
7✔
237
            if (ep != null) yield return new ExecuteCommandShow(_activator, ep, 0, true);
7!
238
        }
239

240
        if (Is(forObject, out TableInfo tableInfo))
99✔
241
            yield return new ExecuteCommandShow(_activator,
2✔
242
                () => tableInfo.ColumnInfos.SelectMany(c =>
×
243
                    _activator.CoreChildProvider.AllCatalogueItems.Where(catItem => catItem.ColumnInfo_ID == c.ID)
×
244
                        .Select(catItem => catItem.Catalogue)).Distinct())
×
245
            {
2✔
246
                OverrideCommandName = "Catalogue(s)",
2✔
247
                OverrideIcon = GetImage(RDMPConcept.Catalogue)
2✔
248
            };
2✔
249

250
        if (Is(forObject, out AggregateConfiguration aggregate))
99✔
251
        {
252
            yield return new ExecuteCommandShow(_activator, aggregate.GetCohortIdentificationConfigurationIfAny()?.ID,
7!
253
                typeof(CohortIdentificationConfiguration))
7✔
254
            {
7✔
255
                OverrideCommandName = "Cohort Identification Configuration",
7✔
256
                OverrideIcon = GetImage(RDMPConcept.CohortIdentificationConfiguration)
7✔
257
            };
7✔
258
            yield return new ExecuteCommandShow(_activator, aggregate.Catalogue_ID, typeof(Catalogue))
7✔
259
            {
7✔
260
                OverrideCommandName = "Catalogue",
7✔
261
                OverrideIcon = GetImage(RDMPConcept.Catalogue)
7✔
262
            };
7✔
263
        }
264

265
        if (Is(forObject, out Catalogue catalogue))
99✔
266
        {
267
            foreach (var lmd in catalogue.LoadMetadatas())
36!
268
            {
269
                yield return new ExecuteCommandShow(_activator, lmd.ID, typeof(LoadMetadata))
×
270
                { OverrideCommandName = $"Data Load ({lmd.Name})", OverrideIcon = GetImage(RDMPConcept.LoadMetadata) };
×
271
            }
272
            if (catalogue.LoadMetadatas().Length == 0)
18✔
273
            {
274
                yield return new ExecuteCommandShow(_activator, null, typeof(LoadMetadata))
18✔
275
                { OverrideCommandName = "No Data Load", OverrideIcon = GetImage(RDMPConcept.LoadMetadata) };
18✔
276
            }
277

278

279
            if (_activator.CoreChildProvider is DataExportChildProvider exp)
18✔
280
            {
281
                var cataEds = exp.ExtractableDataSets.Where(d => d.Catalogue_ID == catalogue.ID);
18✔
282

283
                if (cataEds != null)
18!
284
                {
285
                    yield return new ExecuteCommandShow(_activator,
18✔
NEW
286
                         () => (cataEds.Select(c => c.Project_ID).Select(p => _activator.RepositoryLocator.DataExportRepository.GetObjectByID<Project>(p.Value))))
×
287
                    {
18✔
288
                        OverrideCommandName = "Associated Projects",
18✔
289
                        OverrideIcon = GetImage(RDMPConcept.Project)
18✔
290
                    };
18✔
291
                    yield return new ExecuteCommandShow(_activator,
18✔
NEW
292
                          () => (cataEds.SelectMany(c => c.ExtractionConfigurations.Select(e => e.Project))))
×
293
                    {
18✔
294
                        OverrideCommandName = "Extracted In (Project)",
18✔
295
                        OverrideIcon = GetImage(RDMPConcept.Project)
18✔
296
                    };
18✔
297
                    yield return new ExecuteCommandShow(_activator, () => cataEds.SelectMany(c => c.ExtractionConfigurations))
18✔
298
                    {
18✔
299
                        OverrideCommandName = $"Extracted In (Extraction Configuration)",
18✔
300
                        OverrideIcon = GetImage(RDMPConcept.ExtractionConfiguration)
18✔
301
                    };
18✔
302
                }
303
                else
304
                {
305
                    //no values, show disabled options
UNCOV
306
                    yield return new ExecuteCommandShow(_activator,
×
UNCOV
307
                          () =>
×
UNCOV
308
                          {
×
309
                              return new Project[] { };
×
UNCOV
310
                          }
×
UNCOV
311
                      )
×
UNCOV
312
                    {
×
UNCOV
313
                        OverrideCommandName = "No Associated Project",
×
UNCOV
314
                        OverrideIcon = GetImage(RDMPConcept.Project)
×
UNCOV
315
                    };
×
UNCOV
316
                    yield return new ExecuteCommandShow(_activator,
×
UNCOV
317
                                             () =>
×
UNCOV
318
                                             {
×
319
                                                 return new Project[] { };
×
UNCOV
320
                                             }
×
UNCOV
321
                                         )
×
UNCOV
322
                    {
×
UNCOV
323
                        OverrideCommandName = "Not Extracted In (Project)",
×
UNCOV
324
                        OverrideIcon = GetImage(RDMPConcept.Project)
×
UNCOV
325
                    };
×
UNCOV
326
                    yield return new ExecuteCommandShow(_activator,
×
UNCOV
327
                        () =>
×
UNCOV
328
                        {
×
329
                            return new ExtractionConfiguration[] { };
×
UNCOV
330
                        }
×
UNCOV
331
                    )
×
UNCOV
332
                    {
×
UNCOV
333
                        OverrideCommandName = "Not Extracted In (Extraction Configuration)",
×
UNCOV
334
                        OverrideIcon = GetImage(RDMPConcept.ExtractionConfiguration)
×
UNCOV
335
                    };
×
336
                }
337
            }
18✔
338

339
            yield return new ExecuteCommandShow(_activator, () => catalogue.GetTableInfoList(true))
18✔
340
            { OverrideCommandName = "Table(s)", OverrideIcon = GetImage(RDMPConcept.TableInfo) };
18✔
341

342
            yield return new ExecuteCommandShow(_activator,
18✔
343
                () =>
18✔
344
                    _activator
×
345
                        .CoreChildProvider
×
346
                        .AllAggregateConfigurations.Where(ac =>
×
347
                            ac.IsCohortIdentificationAggregate && ac.Catalogue_ID == catalogue.ID)
×
348
                        .Select(ac => ac.GetCohortIdentificationConfigurationIfAny())
×
349
                        .Where(cataCic => cataCic != null)
×
350
                        .Distinct())
×
351
            {
18✔
352
                OverrideCommandName = "Cohort Identification Configuration(s)",
18✔
353
                OverrideIcon = GetImage(RDMPConcept.CohortIdentificationConfiguration)
18✔
354
            };
18✔
355

356

357
            yield return new ExecuteCommandShow(_activator,
18✔
358
                () => _activator.CoreChildProvider.AllGovernancePeriods.Where(p =>
×
359
                    p.GovernedCatalogues.Contains(catalogue)))
×
360
            {
18✔
361
                OverrideCommandName = "Governance",
18✔
362
                OverrideIcon = GetImage(RDMPConcept.GovernancePeriod)
18✔
363
            };
18✔
364
        }
365

366
        if (Is(forObject, out ExtractableCohort cohort))
99!
367
        {
368
            yield return new ExecuteCommandShow(_activator, () =>
×
369
            {
×
370
                return _activator.CoreChildProvider is DataExportChildProvider dx
×
371
                    ? dx.ExtractionConfigurations.Where(ec => ec.Cohort_ID == cohort.ID)
×
372
                    : (IEnumerable<IMapsDirectlyToDatabaseTable>)Array.Empty<ExtractionConfiguration>();
×
373
            })
×
374
            {
×
375
                OverrideCommandName = "Extraction Configuration(s)",
×
376
                OverrideIcon = GetImage(RDMPConcept.ExtractionConfiguration)
×
377
            };
×
378

379
            yield return new ExecuteCommandShow(_activator, () =>
×
380
            {
×
381
                return _activator.CoreChildProvider is DataExportChildProvider dx
×
382
                    ? dx.Projects.Where(p => p.ProjectNumber == cohort.ExternalProjectNumber)
×
383
                    : (IEnumerable<IMapsDirectlyToDatabaseTable>)Array.Empty<Project>();
×
384
            })
×
385
            {
×
386
                OverrideCommandName = "Project(s)",
×
387
                OverrideIcon = GetImage(RDMPConcept.Project)
×
388
            };
×
389

390
            var obj = ExtractableCohortAuditLogBuilder.GetObjectIfAny(cohort, _activator.RepositoryLocator);
×
391
            if (obj is not null && obj is CohortIdentificationConfiguration configuration)
×
392
            {
393
                yield return new ExecuteCommandShow(_activator, () =>
×
394
                {
×
395
                    return [configuration];
×
396
                })
×
397
                {
×
398
                    OverrideCommandName = "Cohort Identification Configuration(s)",
×
399
                    OverrideIcon = GetImage(RDMPConcept.CohortIdentificationConfiguration)
×
400
                };
×
401
            }
402

403
        }
×
404

405
        //if it is a masquerader and masquerading as a DatabaseEntity then add a goto the object
406
        if (forObject is IMasqueradeAs masqueraderIfAny)
99!
407
            if (masqueraderIfAny.MasqueradingAs() is DatabaseEntity m)
×
408
                yield return new ExecuteCommandShow(_activator, m, 0, true)
×
409
                { OverrideIcon = _activator.CoreIconProvider.GetImage(m) };
×
410
    }
99✔
411

412
    private static bool SupportsReplacement(object o) => o is not DashboardLayout;
96✔
413

414
    private IEnumerable<IMapsDirectlyToDatabaseTable> GetReplacementIfAny(IMapsDirectlyToDatabaseTable mt)
415
    {
416
        var replacement = _activator.RepositoryLocator.CatalogueRepository
×
417
            .GetAllObjectsWhere<ExtendedProperty>("Name", ExtendedProperty.ReplacedBy)
×
418
            .FirstOrDefault(r => r.IsReferenceTo(mt));
×
419

420
        return replacement == null
×
421
            ? Enumerable.Empty<IMapsDirectlyToDatabaseTable>()
×
422
            : new[] { mt.Repository.GetObjectByID(mt.GetType(), int.Parse(replacement.Value)) };
×
423
    }
424

425
    private Image<Rgba32> GetImage(RDMPConcept concept) => _activator.CoreIconProvider.GetImage(concept);
186✔
426
}
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