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

HicServices / RDMP / 18312394996

07 Oct 2025 12:19PM UTC coverage: 57.317% (+0.007%) from 57.31%
18312394996

push

github

JFriel
update rsa

11402 of 21425 branches covered (53.22%)

Branch coverage included in aggregate %.

32365 of 54935 relevant lines covered (58.92%)

17593.11 hits per line

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

45.05
/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.Data.Cohort;
14
using Rdmp.Core.Curation.FilterImporting;
15
using Rdmp.Core.Curation.FilterImporting.Construction;
16
using Rdmp.Core.DataExport.Data;
17
using Rdmp.Core.Icons.IconProvision;
18
using Rdmp.Core.Repositories.Construction;
19
using Rdmp.Core.ReusableLibraryCode.Icons.IconProvision;
20
using SixLabors.ImageSharp;
21
using SixLabors.ImageSharp.PixelFormats;
22

23
namespace Rdmp.Core.CommandExecution.AtomicCommands;
24

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

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

37
    private IFilter[] _offerFilters = [];
6✔
38
    private bool offerCatalogueFilters;
39

40
    public bool OfferCatalogueFilters
41
    {
42
        get => offerCatalogueFilters;
6✔
43
        set
44
        {
45
            offerCatalogueFilters = value;
×
46
        }
×
47
    }
48

49
    private ExecuteCommandCreateNewFilter(IBasicActivateItems activator) : base(activator)
6✔
50
    {
51
        Weight = DEFAULT_WEIGHT;
6✔
52
    }
6✔
53

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

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

95

96
            _factory ??= _container?.GetFilterFactory() ?? _host?.GetFilterFactory();
6!
97

98
            if (_factory == null)
6!
99
                throw new Exception("It was not possible to work out a FilterFactory from the container/host");
×
100
        }
101

102
        // the index that string arguments begin at (Name and WhereSql)
103
        var stringArgsStartAt = 2;
6✔
104

105
        if (picker.Length > 1)
6✔
106
        {
107
            if (IsImpossible)
2!
108
                return;
×
109

110
            if (picker[1].HasValueOfType(typeof(IFilter)))
2!
111
                BasedOn = (IFilter)picker[1].GetValueForParameterOfType(typeof(IFilter));
×
112
            else if (picker[1].HasValueOfType(typeof(ExtractionFilterParameterSet)))
2!
113
                ParameterSet =
×
114
                    (ExtractionFilterParameterSet)picker[1]
×
115
                        .GetValueForParameterOfType(typeof(ExtractionFilterParameterSet));
×
116
            else if (!picker[1].ExplicitNull) stringArgsStartAt = 1;
4✔
117
        }
118

119
        if (picker.Length > stringArgsStartAt) Name = picker[stringArgsStartAt].RawValue;
8✔
120
        if (picker.Length > stringArgsStartAt + 1) WhereSQL = picker[stringArgsStartAt + 1].RawValue;
8✔
121
    }
6✔
122

123

124
    public ExecuteCommandCreateNewFilter(IBasicActivateItems activator, IRootFilterContainerHost host) : this(activator)
×
125
    {
126
        _factory = host.GetFilterFactory();
×
127
        _container = host.RootFilterContainer;
×
128
        _host = host;
×
129
        if (_container == null && _host is AggregateConfiguration ac)
×
130
        {
131
            if (ac.Catalogue.IsApiCall())
×
132
                SetImpossible(ExecuteCommandAddNewFilterContainer.FiltersCannotBeAddedToApiCalls);
×
133

134
            if (ac.OverrideFiltersByUsingParentAggregateConfigurationInstead_ID != null)
×
135
                SetImpossible("Aggregate is set to use another's filter container tree");
×
136
        }
137

138
        SetImpossibleIfReadonly(host);
×
139
    }
×
140

141

142
    public ExecuteCommandCreateNewFilter(IBasicActivateItems activator, CatalogueItem ci) : this(activator)
×
143
    {
144
        if (ci.ExtractionInformation == null)
×
145
        {
146
            SetImpossible(
×
147
                "CatalogueItem is not extractable so cannot have filters. Make this CatalogueItem extractable to add filters.");
×
148
            return;
×
149
        }
150

151
        _factory = new ExtractionFilterFactory(ci.ExtractionInformation);
×
152
    }
×
153

154
    public ExecuteCommandCreateNewFilter(IBasicActivateItems activator, IFilterFactory factory,
155
        IContainer container = null)
156
        : this(activator)
×
157
    {
158
        _factory = factory;
×
159
        _container = container;
×
160

161
        SetImpossibleIfReadonly(container);
×
162
    }
×
163

164
    public ExecuteCommandCreateNewFilter(IBasicActivateItems activator, IContainer container, IFilter basedOn) :
165
        this(activator)
×
166
    {
167
        _container = container;
×
168
        BasedOn = basedOn;
×
169

170
        SetImpossibleIfReadonly(container);
×
171
    }
×
172

173

174
    private ICatalogue GetCatalogue() => _host?.GetCatalogue() ?? _container?.GetCatalogueIfAny();
×
175

176
    public override Image<Rgba32> GetImage(IIconProvider iconProvider) =>
177
        OfferCatalogueFilters
×
178
            ? iconProvider.GetImage(RDMPConcept.Filter, OverlayKind.Import)
×
179
            : iconProvider.GetImage(RDMPConcept.Filter, OverlayKind.Add);
×
180

181
    public override void Execute()
182
    {
183
        base.Execute();
6✔
184

185
        IFilter f;
186
        var container = _container;
6✔
187

188
        if (_host != null && container == null)
6✔
189
        {
190
            if (_host.RootFilterContainer_ID == null)
4✔
191
                _host.CreateRootContainerIfNotExists();
4✔
192

193
            container = _host.RootFilterContainer;
4✔
194
        }
195

196

197
        // if importing an existing filter instead of creating blank
198
        if (BasedOn != null)
6!
199
        {
200
            var wizard = new FilterImportWizard(BasicActivator);
×
201
            f = wizard.Import(container, BasedOn, ParameterSet);
×
202
        }
203
        else if (OfferCatalogueFilters)
6!
204
        {
205

206
            var c = GetCatalogue();
×
207
            _offerFilters = c?.GetAllFilters();
×
208
            if(_host is SelectedDataSets sds)
×
209
            {
210
                var cohort = sds.ExtractionConfiguration.Cohort;
×
211

212
            }
213
            if (_offerFilters == null || !_offerFilters.Any())
×
214
                SetImpossible($"There are no Filters declared in Catalogue '{c?.ToString() ?? "NULL"}'");
×
215

216
            // we want user to make decision about what to import
217
            ImportExistingFilter(container);
×
218
            return;
×
219
        }
220
        else
221
        {
222
            f = _factory.CreateNewFilter($"New Filter {Guid.NewGuid()}");
6✔
223
        }
224

225
        container?.AddChild(f);
6✔
226

227
        if (!string.IsNullOrWhiteSpace(Name)) f.Name = Name;
8✔
228
        if (!string.IsNullOrWhiteSpace(WhereSQL)) f.WhereSQL = WhereSQL;
8✔
229

230
        f.SaveToDatabase();
6✔
231

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

237
        Emphasise(f);
6✔
238
        Activate((DatabaseEntity)f);
6✔
239
    }
6✔
240

241
    private void ImportExistingFilter(IContainer container)
242
    {
243
        var wizard = new FilterImportWizard(BasicActivator);
×
244

245
        var filters = _offerFilters;
×
246
        var import = wizard.ImportManyFromSelection(container, filters).ToArray();
×
247

248
        foreach (var f in import) container.AddChild(f);
×
249

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