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

HicServices / RDMP / 16650670468

31 Jul 2025 01:41PM UTC coverage: 57.469% (+0.008%) from 57.461%
16650670468

push

github

web-flow
Merge pull request #2219 from HicServices/task/prep-9.0.1

Prep V9.0.1

11429 of 21415 branches covered (53.37%)

Branch coverage included in aggregate %.

32397 of 54845 relevant lines covered (59.07%)

17632.8 hits per line

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

45.27
/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 = [];
6✔
36
    private bool offerCatalogueFilters;
37

38

39

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

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

54

55
            offerCatalogueFilters = value;
×
56
        }
×
57
    }
58

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

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

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

105

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

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

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

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

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

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

133

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

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

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

149
        SetImpossibleIfReadonly(host);
×
150
    }
×
151

152

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

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

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

172
        SetImpossibleIfReadonly(container);
×
173
    }
×
174

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

181
        SetImpossibleIfReadonly(container);
×
182
    }
×
183

184

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

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

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

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

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

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

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

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

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

229
        f.SaveToDatabase();
6✔
230

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

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

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

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

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

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