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

HicServices / RDMP / 15871186964

25 Jun 2025 08:21AM UTC coverage: 57.505% (+0.2%) from 57.314%
15871186964

Pull #2203

github

JFriel
fix up help text
Pull Request #2203: Multi-project catalogues

11401 of 21380 branches covered (53.33%)

Branch coverage included in aggregate %.

51 of 58 new or added lines in 6 files covered. (87.93%)

300 existing lines in 5 files now uncovered.

32348 of 54698 relevant lines covered (59.14%)

17534.37 hits per line

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

45.23
/Rdmp.Core/CommandExecution/AtomicCommands/ExecuteCommandCreateNewFilter.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.Linq;
9
using Rdmp.Core.CommandLine.Interactive.Picking;
10
using Rdmp.Core.Curation;
11
using Rdmp.Core.Curation.Data;
12
using Rdmp.Core.Curation.Data.Aggregation;
13
using Rdmp.Core.Curation.FilterImporting;
14
using Rdmp.Core.Curation.FilterImporting.Construction;
15
using Rdmp.Core.Icons.IconProvision;
16
using Rdmp.Core.Repositories.Construction;
17
using Rdmp.Core.ReusableLibraryCode.Icons.IconProvision;
18
using SixLabors.ImageSharp;
19
using SixLabors.ImageSharp.PixelFormats;
20

21
namespace Rdmp.Core.CommandExecution.AtomicCommands;
22

23
public class ExecuteCommandCreateNewFilter : BasicCommandExecution, IAtomicCommand
24
{
25
    private IFilterFactory _factory;
26
    private IContainer _container;
27
    private IRootFilterContainerHost _host;
28
    private const float DEFAULT_WEIGHT = 0.1f;
29

30
    public IFilter BasedOn { get; set; }
6✔
31
    public ExtractionFilterParameterSet ParameterSet { get; set; }
×
32
    public string Name { get; }
8✔
33
    public string WhereSQL { get; }
8✔
34

35
    private IFilter[] _offerFilters;
36
    private bool offerCatalogueFilters;
37

38
    public bool OfferCatalogueFilters
39
    {
40
        get => offerCatalogueFilters;
6✔
41
        set
42
        {
UNCOV
43
            if (value)
×
44
            {
UNCOV
45
                var c = GetCatalogue();
×
UNCOV
46
                _offerFilters = c?.GetAllFilters();
×
47

UNCOV
48
                if (_offerFilters == null || !_offerFilters.Any())
×
49
                    SetImpossible($"There are no Filters declared in Catalogue '{c?.ToString() ?? "NULL"}'");
×
50
            }
51

52

53
            offerCatalogueFilters = value;
×
UNCOV
54
        }
×
55
    }
56

57

58
    private ExecuteCommandCreateNewFilter(IBasicActivateItems activator) : base(activator)
6✔
59
    {
60
        Weight = DEFAULT_WEIGHT;
6✔
61
    }
6✔
62

63
    [UseWithCommandLine(
64
        ParameterHelpList = "<into> <basedOn> <name> <where>",
65
        ParameterHelpBreakdown =
66
            @"into        A WHERE filter container or IRootFilterContainerHost (e.g. AggregateConfiguration)
67
basedOn    Optional ExtractionFilter to copy or ExtractionFilterParameterSet
68
name    Optional name to set for the new filter
69
where    Optional SQL to set for the filter.  If <basedOn> is not null this will overwrite it")]
70
    public ExecuteCommandCreateNewFilter(IBasicActivateItems activator,
71
        CommandLineObjectPicker picker) : this(activator)
6✔
72
    {
73
        if (picker.Length == 0)
6!
UNCOV
74
            throw new ArgumentException(
×
UNCOV
75
                "You must supply at least one argument to this command (where you want to create the filter)");
×
76

77
        if (picker.Length > 0)
6✔
78
        {
79
            if (picker[0].HasValueOfType(typeof(ExtractionInformation)))
6✔
80
            {
81
                // create a top level Catalogue level filter for reuse later on
82
                var ei = (ExtractionInformation)picker[0].GetValueForParameterOfType(typeof(ExtractionInformation));
2✔
83
                _factory = new ExtractionFilterFactory(ei);
2✔
84
            }
85
            else if (picker[0].HasValueOfType(typeof(IContainer)))
4!
86
            {
87
                // create a filter in this container
UNCOV
88
                _container = (IContainer)picker[0].GetValueForParameterOfType(typeof(IContainer));
×
UNCOV
89
                SetImpossibleIfReadonly(_container);
×
90
            }
91
            else if (picker[0].HasValueOfType(typeof(IRootFilterContainerHost)))
4!
92
            {
93
                // create a container (if none) then add filter to root container of the object
94
                _host = (IRootFilterContainerHost)picker[0]
4✔
95
                    .GetValueForParameterOfType(typeof(IRootFilterContainerHost));
4✔
96
                SetImpossibleIfReadonly(_host);
4✔
97
            }
98
            else
99
            {
UNCOV
100
                throw new ArgumentException(
×
UNCOV
101
                    $"First argument must be {nameof(IContainer)} or  {nameof(IRootFilterContainerHost)} but it was '{picker[0].RawValue}'");
×
102
            }
103

104

105
            _factory ??= _container?.GetFilterFactory() ?? _host?.GetFilterFactory();
6!
106

107
            if (_factory == null)
6!
UNCOV
108
                throw new Exception("It was not possible to work out a FilterFactory from the container/host");
×
109
        }
110

111
        // the index that string arguments begin at (Name and WhereSql)
112
        var stringArgsStartAt = 2;
6✔
113

114
        if (picker.Length > 1)
6✔
115
        {
116
            if (IsImpossible)
2!
117
                return;
×
118

119
            if (picker[1].HasValueOfType(typeof(IFilter)))
2!
UNCOV
120
                BasedOn = (IFilter)picker[1].GetValueForParameterOfType(typeof(IFilter));
×
121
            else if (picker[1].HasValueOfType(typeof(ExtractionFilterParameterSet)))
2!
UNCOV
122
                ParameterSet =
×
UNCOV
123
                    (ExtractionFilterParameterSet)picker[1]
×
UNCOV
124
                        .GetValueForParameterOfType(typeof(ExtractionFilterParameterSet));
×
125
            else if (!picker[1].ExplicitNull) stringArgsStartAt = 1;
4✔
126
        }
127

128
        if (picker.Length > stringArgsStartAt) Name = picker[stringArgsStartAt].RawValue;
8✔
129
        if (picker.Length > stringArgsStartAt + 1) WhereSQL = picker[stringArgsStartAt + 1].RawValue;
8✔
130
    }
6✔
131

132

UNCOV
133
    public ExecuteCommandCreateNewFilter(IBasicActivateItems activator, IRootFilterContainerHost host) : this(activator)
×
134
    {
UNCOV
135
        _factory = host.GetFilterFactory();
×
UNCOV
136
        _container = host.RootFilterContainer;
×
137
        _host = host;
×
138

139
        if (_container == null && _host is AggregateConfiguration ac)
×
140
        {
141
            if (ac.Catalogue.IsApiCall())
×
UNCOV
142
                SetImpossible(ExecuteCommandAddNewFilterContainer.FiltersCannotBeAddedToApiCalls);
×
143

UNCOV
144
            if (ac.OverrideFiltersByUsingParentAggregateConfigurationInstead_ID != null)
×
UNCOV
145
                SetImpossible("Aggregate is set to use another's filter container tree");
×
146
        }
147

UNCOV
148
        SetImpossibleIfReadonly(host);
×
UNCOV
149
    }
×
150

151

152
    public ExecuteCommandCreateNewFilter(IBasicActivateItems activator, CatalogueItem ci) : this(activator)
×
153
    {
154
        if (ci.ExtractionInformation == null)
×
155
        {
156
            SetImpossible(
×
UNCOV
157
                "CatalogueItem is not extractable so cannot have filters. Make this CatalogueItem extractable to add filters.");
×
158
            return;
×
159
        }
160

161
        _factory = new ExtractionFilterFactory(ci.ExtractionInformation);
×
162
    }
×
163

164
    public ExecuteCommandCreateNewFilter(IBasicActivateItems activator, IFilterFactory factory,
165
        IContainer container = null)
166
        : this(activator)
×
167
    {
UNCOV
168
        _factory = factory;
×
169
        _container = container;
×
170

171
        SetImpossibleIfReadonly(container);
×
UNCOV
172
    }
×
173

174
    public ExecuteCommandCreateNewFilter(IBasicActivateItems activator, IContainer container, IFilter basedOn) :
175
        this(activator)
×
176
    {
UNCOV
177
        _container = container;
×
178
        BasedOn = basedOn;
×
179

UNCOV
180
        SetImpossibleIfReadonly(container);
×
UNCOV
181
    }
×
182

183

UNCOV
184
    private ICatalogue GetCatalogue() => _host?.GetCatalogue() ?? _container?.GetCatalogueIfAny();
×
185

186
    public override Image<Rgba32> GetImage(IIconProvider iconProvider) =>
UNCOV
187
        OfferCatalogueFilters
×
188
            ? iconProvider.GetImage(RDMPConcept.Filter, OverlayKind.Import)
×
189
            : iconProvider.GetImage(RDMPConcept.Filter, OverlayKind.Add);
×
190

191
    public override void Execute()
192
    {
193
        base.Execute();
6✔
194

195
        IFilter f;
196
        var container = _container;
6✔
197

198
        if (_host != null && container == null)
6✔
199
        {
200
            if (_host.RootFilterContainer_ID == null)
4✔
201
                _host.CreateRootContainerIfNotExists();
4✔
202

203
            container = _host.RootFilterContainer;
4✔
204
        }
205

206
        // if importing an existing filter instead of creating blank
207
        if (BasedOn != null)
6!
208
        {
UNCOV
209
            var wizard = new FilterImportWizard(BasicActivator);
×
UNCOV
210
            f = wizard.Import(container, BasedOn, ParameterSet);
×
211
        }
212
        else if (OfferCatalogueFilters)
6!
213
        {
214
            // we want user to make decision about what to import
UNCOV
215
            ImportExistingFilter(container);
×
UNCOV
216
            return;
×
217
        }
218
        else
219
        {
220
            f = _factory.CreateNewFilter($"New Filter {Guid.NewGuid()}");
6✔
221
        }
222

223
        container?.AddChild(f);
6✔
224

225
        if (!string.IsNullOrWhiteSpace(Name)) f.Name = Name;
8✔
226
        if (!string.IsNullOrWhiteSpace(WhereSQL)) f.WhereSQL = WhereSQL;
8✔
227

228
        f.SaveToDatabase();
6✔
229

230
        if (f is ExtractionFilter ef)
6✔
231
            Publish(ef.ExtractionInformation);
2✔
232
        else
233
            Publish((DatabaseEntity)container ?? (DatabaseEntity)f);
4!
234

235
        Emphasise(f);
6✔
236
        Activate((DatabaseEntity)f);
6✔
237
    }
6✔
238

239
    private void ImportExistingFilter(IContainer container)
240
    {
UNCOV
241
        var wizard = new FilterImportWizard(BasicActivator);
×
242

UNCOV
243
        var import = wizard.ImportManyFromSelection(container, _offerFilters).ToArray();
×
244

UNCOV
245
        foreach (var f in import) container.AddChild(f);
×
246

UNCOV
247
        if (import.Length > 0)
×
248
        {
UNCOV
249
            Publish((DatabaseEntity)container);
×
UNCOV
250
            Emphasise((DatabaseEntity)import.Last());
×
251
        }
UNCOV
252
    }
×
253
}
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