diff --git a/Application/ResearchDataManagementPlatform/Menus/RDMPTopMenuStripUI.cs b/Application/ResearchDataManagementPlatform/Menus/RDMPTopMenuStripUI.cs index 8f395baf54..430a7f6809 100644 --- a/Application/ResearchDataManagementPlatform/Menus/RDMPTopMenuStripUI.cs +++ b/Application/ResearchDataManagementPlatform/Menus/RDMPTopMenuStripUI.cs @@ -445,10 +445,11 @@ private void openToolStripMenuItem_Click(object sender, EventArgs e) private void newFindToolStripMenuItem_Click(object sender, EventArgs e) { - var focusItem = _windowManager.GetAllWindows().Where(c => c.ContainsFocus).FirstOrDefault(); - var nf = new NewfindUI(Activator, false,focusItem); + var focusItem = _windowManager.GetAllWindows().FirstOrDefault(c => c.ContainsFocus); + var nf = new NewfindUI(Activator, false, focusItem); nf.ShowDialog(); } + private void newReplaceToolStripMenuItem_Click(object sender, EventArgs e) { var nf = new NewfindUI(Activator, true); diff --git a/Application/ResearchDataManagementPlatform/WindowManagement/ActivateItems.cs b/Application/ResearchDataManagementPlatform/WindowManagement/ActivateItems.cs index 97de70ad39..ff4dac1ea5 100644 --- a/Application/ResearchDataManagementPlatform/WindowManagement/ActivateItems.cs +++ b/Application/ResearchDataManagementPlatform/WindowManagement/ActivateItems.cs @@ -387,11 +387,11 @@ private T Activate(T2 databaseObject, Image tabImage) var floatable = WindowFactory.Create(this, RefreshBus, uiInstance, tabImage, databaseObject); int? insertIndex = null; - var panel = _mainDockPanel.Panes.Where(p => p.IsActiveDocumentPane).SingleOrDefault(); + var panel = _mainDockPanel.Panes.SingleOrDefault(static p => p.IsActiveDocumentPane); if (panel is not null) { var contents = panel.Contents; - insertIndex = contents.IndexOf(panel.ActiveContent)+1; + insertIndex = contents.IndexOf(panel.ActiveContent) + 1; } floatable.Show(_mainDockPanel, DockState.Document); diff --git a/Application/ResearchDataManagementPlatform/WindowManagement/WindowArranging/WindowArranger.cs b/Application/ResearchDataManagementPlatform/WindowManagement/WindowArranging/WindowArranger.cs index 712016bcef..43508e6e13 100644 --- a/Application/ResearchDataManagementPlatform/WindowManagement/WindowArranging/WindowArranger.cs +++ b/Application/ResearchDataManagementPlatform/WindowManagement/WindowArranging/WindowArranger.cs @@ -17,7 +17,7 @@ namespace ResearchDataManagementPlatform.WindowManagement.WindowArranging; /// -public class WindowArranger : IArrangeWindows +public partial class WindowArranger : IArrangeWindows { private readonly IActivateItems _activator; private readonly WindowManager _windowManager; @@ -57,10 +57,12 @@ public void Setup(WindowLayout target) private static bool AreBasicallyTheSameLayout(string oldXml, string newXml) { - var patStripActive = @"Active.*=[""\-\d]*"; - oldXml = Regex.Replace(oldXml, patStripActive, ""); - newXml = Regex.Replace(newXml, patStripActive, ""); + oldXml = StripActive().Replace(oldXml, ""); + newXml = StripActive().Replace(newXml, ""); - return oldXml.Equals(newXml, StringComparison.CurrentCultureIgnoreCase); + return oldXml.Equals(newXml, StringComparison.OrdinalIgnoreCase); } + + [GeneratedRegex(@"Active.*=[""\-\d]*")] + private static partial Regex StripActive(); } \ No newline at end of file diff --git a/Documentation/CodeTutorials/DoubleClickAndDragDrop.md b/Documentation/CodeTutorials/DoubleClickAndDragDrop.md index 0c8c63bdcb..70f2dc4706 100644 --- a/Documentation/CodeTutorials/DoubleClickAndDragDrop.md +++ b/Documentation/CodeTutorials/DoubleClickAndDragDrop.md @@ -72,9 +72,7 @@ If you find you cannot use Visual Studio Designer to edit your control because o ```csharp [TypeDescriptionProvider(typeof(AbstractControlDescriptionProvider))] -public abstract class ANOTableUI_Design : RDMPSingleDatabaseObjectControl -{ -} +public abstract class ANOTableUI_Design : RDMPSingleDatabaseObjectControl; ``` # Drop diff --git a/Documentation/CodeTutorials/Validation.md b/Documentation/CodeTutorials/Validation.md index 1955de1ce8..9442f4367a 100644 --- a/Documentation/CodeTutorials/Validation.md +++ b/Documentation/CodeTutorials/Validation.md @@ -88,10 +88,10 @@ RDMP features a viewer which renders the By Date and By Column tables as graphs. ## Plugin Constraints -You can write new validation rules by inheriting from `HIC.Common.Validation.Constraints.Secondary.PluginSecondaryConstraint`. Implement the Validate method returning null if validation passed or a `ValidationFailure` if it didn't. Public properties will be rendered as CheckBoxes, TextBoxes etc. +You can write new validation rules by inheriting from `HIC.Common.Validation.Constraints.Secondary.SecondaryConstraint`. Implement the Validate method returning null if validation passed or a `ValidationFailure` if it didn't. Public properties will be rendered as CheckBoxes, TextBoxes etc. ```csharp -public class NoFishConstraint : PluginSecondaryConstraint +public class NoFishConstraint : SecondaryConstraint { //Will be exposed in user interface public bool IgnoreCaps { get; set; } diff --git a/Rdmp.Core.Tests/Caching/Unit/TestIFileDataFlowComponents.cs b/Rdmp.Core.Tests/Caching/Unit/TestIFileDataFlowComponents.cs index 776d933c7a..467b3faa87 100644 --- a/Rdmp.Core.Tests/Caching/Unit/TestIFileDataFlowComponents.cs +++ b/Rdmp.Core.Tests/Caching/Unit/TestIFileDataFlowComponents.cs @@ -15,9 +15,7 @@ namespace Rdmp.Core.Tests.Caching.Unit; -public interface IFileDataFlowDestination : TestIFileDataFlowComponent -{ -} +public interface IFileDataFlowDestination : TestIFileDataFlowComponent; public interface TestIFileDataFlowComponent { diff --git a/Rdmp.Core.Tests/CohortCreation/CohortMandatoryFilterImportingTests.cs b/Rdmp.Core.Tests/CohortCreation/CohortMandatoryFilterImportingTests.cs index 20a060749e..e25d52ecfc 100644 --- a/Rdmp.Core.Tests/CohortCreation/CohortMandatoryFilterImportingTests.cs +++ b/Rdmp.Core.Tests/CohortCreation/CohortMandatoryFilterImportingTests.cs @@ -92,7 +92,7 @@ public void ImportCatalogueWithMandatoryFilter() [TestCase(false)] public void ImportCatalogueWithSingleFilterThatHasAParameter(bool createAGlobalOverrideBeforeHand) { - var parameterSQL = "DECLARE @dragonCount as varchar(100)"; + const string parameterSQL = "DECLARE @dragonCount as varchar(100)"; var filter = new ExtractionFilter(CatalogueRepository, "MyMandatoryFilter", testData.extractionInformations[0]) { diff --git a/Rdmp.Core.Tests/CommandExecution/ExecuteCommandCloneLoadMetadataTests.cs b/Rdmp.Core.Tests/CommandExecution/ExecuteCommandCloneLoadMetadataTests.cs index f3ae07b43d..2a0efbeba0 100644 --- a/Rdmp.Core.Tests/CommandExecution/ExecuteCommandCloneLoadMetadataTests.cs +++ b/Rdmp.Core.Tests/CommandExecution/ExecuteCommandCloneLoadMetadataTests.cs @@ -1,17 +1,14 @@ using NUnit.Framework; using Rdmp.Core.Curation.Data.DataLoad; using Rdmp.Core.Curation.Data; -using Rdmp.Core.Repositories; using Tests.Common; using Rdmp.Core.DataLoad.Modules.Attachers; -using Rdmp.Core.MapsDirectlyToDatabaseTable; using System.Linq; namespace Rdmp.Core.Tests.CommandExecution { - public class ExecuteCommandCloneLoadMetadataTests: DatabaseTests + public class ExecuteCommandCloneLoadMetadataTests : DatabaseTests { - [Test] public void TestCloneLoadMetadata() { @@ -31,15 +28,17 @@ public void TestCloneLoadMetadata() }; pt1.SaveToDatabase(); - pt1.CreateArgumentsForClassIfNotExists(typeof(AnySeparatorFileAttacher)); - var pta = pt1.ProcessTaskArguments.Single(pt => pt.Name == "Separator"); + pt1.CreateArgumentsForClassIfNotExists(); + var pta = pt1.ProcessTaskArguments.Single(static pt => pt.Name == "Separator"); pta.SetValue(","); pta.SaveToDatabase(); - LoadMetadata clonedLmd; - clonedLmd = lmd1.Clone(); - Assert.That(clonedLmd.ProcessTasks.Count(), Is.EqualTo(1)); - Assert.That(clonedLmd.Description, Is.EqualTo(lmd1.Description)); - Assert.That(clonedLmd.ProcessTasks.First().ProcessTaskArguments.First().Value, Is.EqualTo(lmd1.ProcessTasks.First().ProcessTaskArguments.First().Value)); + var clonedLmd = lmd1.Clone(); + Assert.Multiple(() => + { + Assert.That(clonedLmd.ProcessTasks.Count(), Is.EqualTo(1)); + Assert.That(clonedLmd.Description, Is.EqualTo(lmd1.Description)); + Assert.That(clonedLmd.ProcessTasks.First().ProcessTaskArguments.First().Value, Is.EqualTo(lmd1.ProcessTasks.First().ProcessTaskArguments.First().Value)); + }); } } } diff --git a/Rdmp.Core.Tests/CommandExecution/ExecuteCommandCreateLoadMetadataVersionTests.cs b/Rdmp.Core.Tests/CommandExecution/ExecuteCommandCreateLoadMetadataVersionTests.cs index 2354444a6a..7d2706893d 100644 --- a/Rdmp.Core.Tests/CommandExecution/ExecuteCommandCreateLoadMetadataVersionTests.cs +++ b/Rdmp.Core.Tests/CommandExecution/ExecuteCommandCreateLoadMetadataVersionTests.cs @@ -1,10 +1,8 @@ using NUnit.Framework; using Rdmp.Core.Curation.Data.DataLoad; using Rdmp.Core.Curation.Data; -using Rdmp.Core.Repositories; using Tests.Common; using Rdmp.Core.DataLoad.Modules.Attachers; -using Rdmp.Core.MapsDirectlyToDatabaseTable; using System.Linq; namespace Rdmp.Core.Tests.CommandExecution @@ -31,16 +29,18 @@ public void TestCreateLoadMetadataVersion() }; pt1.SaveToDatabase(); - pt1.CreateArgumentsForClassIfNotExists(typeof(AnySeparatorFileAttacher)); - var pta = pt1.ProcessTaskArguments.Single(pt => pt.Name == "Separator"); + pt1.CreateArgumentsForClassIfNotExists(); + var pta = pt1.ProcessTaskArguments.Single(static pt => pt.Name == "Separator"); pta.SetValue(","); pta.SaveToDatabase(); - LoadMetadata clonedLmd; - clonedLmd = (LoadMetadata)lmd1.SaveNewVersion(); - Assert.That(clonedLmd.ProcessTasks.Count(), Is.EqualTo(1)); - Assert.That(clonedLmd.RootLoadMetadata_ID, Is.EqualTo(lmd1.ID)); - Assert.That(clonedLmd.Description, Is.EqualTo(lmd1.Description)); - Assert.That(clonedLmd.ProcessTasks.First().ProcessTaskArguments.First().Value, Is.EqualTo(lmd1.ProcessTasks.First().ProcessTaskArguments.First().Value)); + var clonedLmd = (LoadMetadata)lmd1.SaveNewVersion(); + Assert.Multiple(() => + { + Assert.That(clonedLmd.ProcessTasks.Count(), Is.EqualTo(1)); + Assert.That(clonedLmd.RootLoadMetadata_ID, Is.EqualTo(lmd1.ID)); + Assert.That(clonedLmd.Description, Is.EqualTo(lmd1.Description)); + Assert.That(clonedLmd.ProcessTasks.First().ProcessTaskArguments.First().Value, Is.EqualTo(lmd1.ProcessTasks.First().ProcessTaskArguments.First().Value)); + }); } } } diff --git a/Rdmp.Core.Tests/CommandExecution/ExecuteCommandPerformRegexRedactionOnCatalogueTests.cs b/Rdmp.Core.Tests/CommandExecution/ExecuteCommandPerformRegexRedactionOnCatalogueTests.cs index 263c688428..2624312888 100644 --- a/Rdmp.Core.Tests/CommandExecution/ExecuteCommandPerformRegexRedactionOnCatalogueTests.cs +++ b/Rdmp.Core.Tests/CommandExecution/ExecuteCommandPerformRegexRedactionOnCatalogueTests.cs @@ -9,7 +9,6 @@ using Rdmp.Core.CommandExecution.AtomicCommands; using Rdmp.Core.Curation.DataHelper.RegexRedaction; using System.Text.RegularExpressions; -using Rdmp.Core.CommandLine.Interactive; using Rdmp.Core.ReusableLibraryCode.Checks; using System.Data; using FAnsi.Discovery; @@ -105,8 +104,8 @@ public void OneTimeTearDown() [Test] public void Redaction_BasicRedactionTest() { - _dt.Rows.Add(new object[] { DateTime.Now, '1', "1234TEST1234" }); - _dt.Rows.Add(new object[] { DateTime.Now, '2', "1234TEST1234" }); + _dt.Rows.Add(DateTime.Now, '1', "1234TEST1234"); + _dt.Rows.Add(DateTime.Now, '2', "1234TEST1234"); (_catalogue, var columnInfos) = CreateTable(_db, _dt); var regexConfiguration = new RegexRedactionConfiguration(CatalogueRepository, "TestReplacer", new Regex("TEST"), "GG", "Replace TEST with GG"); @@ -126,8 +125,8 @@ public void Redaction_BasicRedactionTest() [Test] public void Redaction_BasicRedactionTestWithLimit() { - _dt.Rows.Add(new object[] { DateTime.Now, '1', "1234TEST1234" }); - _dt.Rows.Add(new object[] { DateTime.Parse("10-10-2010"), '2', "1234TEST1234" }); + _dt.Rows.Add(DateTime.Now, '1', "1234TEST1234"); + _dt.Rows.Add(DateTime.Parse("10-10-2010"), '2', "1234TEST1234"); (_catalogue, var columnInfos) = CreateTable(_db, _dt, new[] { true, true, false }); var regexConfiguration = new RegexRedactionConfiguration(CatalogueRepository, "TestReplacer", new Regex("TEST"), "GG", "Replace TEST with GG"); @@ -147,7 +146,7 @@ public void Redaction_BasicRedactionTestWithLimit() [Test] public void Redaction_OddStringLength() { - _dt.Rows.Add(new object[] { DateTime.Now, '1', "1234TESTT1234" }); + _dt.Rows.Add(DateTime.Now, '1', "1234TESTT1234"); (_catalogue, var columnInfos) = CreateTable(_db, _dt); var regexConfiguration = new RegexRedactionConfiguration(CatalogueRepository, "TestReplacer", new Regex("TESTT"), "GG", "Replace TEST with GG"); regexConfiguration.SaveToDatabase(); @@ -161,7 +160,7 @@ public void Redaction_OddStringLength() [Test] public void Redaction_RedactionTooLong() { - _dt.Rows.Add(new object[] { DateTime.Now, '1', "1234TEST1234" }); + _dt.Rows.Add(DateTime.Now, '1', "1234TEST1234"); var (catalogue, columnInfos) = CreateTable(_db, _dt); var regexConfiguration = new RegexRedactionConfiguration(CatalogueRepository, "TestReplacer", new Regex("TEST"), "FARTOOLONG", "Replace TEST with GG"); regexConfiguration.SaveToDatabase(); @@ -173,7 +172,7 @@ public void Redaction_RedactionTooLong() [Test] public void Redaction_RedactAPK() { - _dt.Rows.Add(new object[] { DateTime.Now, '1', "1234TEST1234" }); + _dt.Rows.Add(DateTime.Now, '1', "1234TEST1234"); (_catalogue, var columnInfos) = CreateTable(_db, _dt, new[] { true,true,true}); var regexConfiguration = new RegexRedactionConfiguration(CatalogueRepository, "TestReplacer", new Regex("TEST"), "GG", "Replace TEST with GG"); regexConfiguration.SaveToDatabase(); @@ -187,7 +186,7 @@ public void Redaction_RedactAPK() [Test] public void Redaction_NoPKS() { - _dt.Rows.Add(new object[] { DateTime.Now, '1', "1234TEST1234" }); + _dt.Rows.Add(DateTime.Now, '1', "1234TEST1234"); (_catalogue, var columnInfos) = CreateTable(_db, _dt, new[] { false, false, false }); var regexConfiguration = new RegexRedactionConfiguration(CatalogueRepository, "TestReplacer", new Regex("TEST"), "GG", "Replace TEST with GG"); regexConfiguration.SaveToDatabase(); @@ -199,7 +198,7 @@ public void Redaction_NoPKS() [Test] public void Redaction_MultipleInOneCell() { - _dt.Rows.Add(new object[] { DateTime.Now, '1', "1234TEST1234TEST1234" }); + _dt.Rows.Add(DateTime.Now, '1', "1234TEST1234TEST1234"); (_catalogue, var columnInfos) = CreateTable(_db, _dt); var regexConfiguration = new RegexRedactionConfiguration(CatalogueRepository, "TestReplacer", new Regex("TEST"), "DB", "Replace TEST with GG"); regexConfiguration.SaveToDatabase(); diff --git a/Rdmp.Core.Tests/CommandExecution/ExecuteCommandRestoreLoadMetadataTests.cs b/Rdmp.Core.Tests/CommandExecution/ExecuteCommandRestoreLoadMetadataTests.cs index 888b67bf31..58cafa9e6e 100644 --- a/Rdmp.Core.Tests/CommandExecution/ExecuteCommandRestoreLoadMetadataTests.cs +++ b/Rdmp.Core.Tests/CommandExecution/ExecuteCommandRestoreLoadMetadataTests.cs @@ -1,14 +1,10 @@ using NUnit.Framework; using Rdmp.Core.Curation.Data.DataLoad; using Rdmp.Core.Curation.Data; -using Rdmp.Core.Repositories; using Tests.Common; using Rdmp.Core.DataLoad.Modules.Attachers; -using Rdmp.Core.MapsDirectlyToDatabaseTable; using System.Linq; using Rdmp.Core.CommandExecution.AtomicCommands; -using Rdmp.Core.CommandLine.Interactive; -using Rdmp.Core.ReusableLibraryCode.Checks; using Rdmp.Core.CommandExecution; namespace Rdmp.Core.Tests.CommandExecution @@ -35,16 +31,18 @@ public void TestRestoreLoadMetadataVersion() }; pt1.SaveToDatabase(); - pt1.CreateArgumentsForClassIfNotExists(typeof(AnySeparatorFileAttacher)); - var pta = pt1.ProcessTaskArguments.Single(pt => pt.Name == "Separator"); + pt1.CreateArgumentsForClassIfNotExists(); + var pta = pt1.ProcessTaskArguments.Single(static pt => pt.Name == "Separator"); pta.SetValue(","); pta.SaveToDatabase(); - LoadMetadata clonedLmd; - clonedLmd = (LoadMetadata)lmd1.SaveNewVersion(); - Assert.That(clonedLmd.ProcessTasks.Count(), Is.EqualTo(1)); - Assert.That(clonedLmd.RootLoadMetadata_ID, Is.EqualTo(lmd1.ID)); - Assert.That(clonedLmd.Description, Is.EqualTo(lmd1.Description)); - Assert.That(clonedLmd.ProcessTasks.First().ProcessTaskArguments.First().Value, Is.EqualTo(lmd1.ProcessTasks.First().ProcessTaskArguments.First().Value)); + var clonedLmd = (LoadMetadata)lmd1.SaveNewVersion(); + Assert.Multiple(() => + { + Assert.That(clonedLmd.ProcessTasks.Count(), Is.EqualTo(1)); + Assert.That(clonedLmd.RootLoadMetadata_ID, Is.EqualTo(lmd1.ID)); + Assert.That(clonedLmd.Description, Is.EqualTo(lmd1.Description)); + Assert.That(clonedLmd.ProcessTasks.First().ProcessTaskArguments.First().Value, Is.EqualTo(lmd1.ProcessTasks.First().ProcessTaskArguments.First().Value)); + }); pt1.DeleteInDatabase(); var fetchedlmd = CatalogueRepository.GetObjectByID(lmd1.ID); Assert.That(fetchedlmd.ProcessTasks.Count(), Is.EqualTo(0)); diff --git a/Rdmp.Core.Tests/CommandExecution/ExecuteCommandRestoreRegexRedactedValueInCatalogueTests.cs b/Rdmp.Core.Tests/CommandExecution/ExecuteCommandRestoreRegexRedactedValueInCatalogueTests.cs index 32ae4b05e3..f102f73db7 100644 --- a/Rdmp.Core.Tests/CommandExecution/ExecuteCommandRestoreRegexRedactedValueInCatalogueTests.cs +++ b/Rdmp.Core.Tests/CommandExecution/ExecuteCommandRestoreRegexRedactedValueInCatalogueTests.cs @@ -46,19 +46,18 @@ private DataTable GetRedactionTestDataTable() var ei = new ExtractionInformation(CatalogueRepository, ci, columnInfo, ""); ei.SaveToDatabase(); } + return (catalogue, _columnInfos); } - private DataTable Retrieve(DiscoveredDatabase db) + private static DataTable Retrieve(DiscoveredDatabase db) { - var retrieveSQL = @"select [Condition2] from [RedactionTest]"; + const string retrieveSQL = @"select [Condition2] from [RedactionTest]"; var dt = new DataTable(); dt.BeginLoadData(); - using (var fetchCmd = db.Server.GetCommand(retrieveSQL, db.Server.GetConnection())) - { - using var da = db.Server.GetDataAdapter(fetchCmd); - da.Fill(dt); - } + using var fetchCmd = db.Server.GetCommand(retrieveSQL, db.Server.GetConnection()); + using var da = db.Server.GetDataAdapter(fetchCmd); + da.Fill(dt); return dt; } @@ -67,13 +66,13 @@ public void RedactionRestore_BasicTest() { var db = GetCleanedServer(DatabaseType.MicrosoftSQLServer); var dt = GetRedactionTestDataTable(); - dt.Rows.Add(new object[] { DateTime.Now, '1', "1234TEST1234" }); - (Catalogue catalogue, ColumnInfo[] _columnInfos) = CreateTable(db, dt); - + dt.Rows.Add(DateTime.Now, '1', "1234TEST1234"); + var (catalogue, columnInfos) = CreateTable(db, dt); + var activator = new ConsoleInputManager(RepositoryLocator, ThrowImmediatelyCheckNotifier.Quiet); var regexConfiguration = new RegexRedactionConfiguration(CatalogueRepository, "TestReplacer", new Regex("TEST"), "GG", "Replace TEST with GG"); regexConfiguration.SaveToDatabase(); - var cmd = new ExecuteCommandPerformRegexRedactionOnCatalogue(activator, catalogue, regexConfiguration, _columnInfos.Where(c => c.GetRuntimeName() == "Condition2").ToList()); + var cmd = new ExecuteCommandPerformRegexRedactionOnCatalogue(activator, catalogue, regexConfiguration, columnInfos.Where(c => c.GetRuntimeName() == "Condition2").ToList()); Assert.DoesNotThrow(() => cmd.Execute()); dt = Retrieve(db); Assert.That(dt.Rows.Count, Is.EqualTo(1)); @@ -92,8 +91,8 @@ public void RedactionRestore_RestoreTwice() { var db = GetCleanedServer(DatabaseType.MicrosoftSQLServer); var dt = GetRedactionTestDataTable(); - dt.Rows.Add(new object[] { DateTime.Now, '1', "1234TEST1234" }); - (Catalogue catalogue, ColumnInfo[] _columnInfos) = CreateTable(db, dt); + dt.Rows.Add(DateTime.Now, '1', "1234TEST1234"); + (var catalogue, var _columnInfos) = CreateTable(db, dt); var activator = new ConsoleInputManager(RepositoryLocator, ThrowImmediatelyCheckNotifier.Quiet); var regexConfiguration = new RegexRedactionConfiguration(CatalogueRepository, "TestReplacer", new Regex("TEST"), "GG", "Replace TEST with GG"); @@ -132,8 +131,8 @@ public void RedactionRestore_MultipleInOneCell() { var db = GetCleanedServer(DatabaseType.MicrosoftSQLServer); var dt = GetRedactionTestDataTable(); - dt.Rows.Add(new object[] { DateTime.Now, '1', "1234TEST1234TEST1234" }); - (Catalogue catalogue, ColumnInfo[] _columnInfos) = CreateTable(db, dt); + dt.Rows.Add(DateTime.Now, '1', "1234TEST1234TEST1234"); + (var catalogue, var _columnInfos) = CreateTable(db, dt); var activator = new ConsoleInputManager(RepositoryLocator, ThrowImmediatelyCheckNotifier.Quiet); var regexConfiguration = new RegexRedactionConfiguration(CatalogueRepository, "TestReplacer", new Regex("TEST"), "DB", "Replace TEST with DB"); diff --git a/Rdmp.Core.Tests/CommandExecution/ExecuteCommandUpdateCatalogueDataLocationTests.cs b/Rdmp.Core.Tests/CommandExecution/ExecuteCommandUpdateCatalogueDataLocationTests.cs index 5f448b810e..bae1693c09 100644 --- a/Rdmp.Core.Tests/CommandExecution/ExecuteCommandUpdateCatalogueDataLocationTests.cs +++ b/Rdmp.Core.Tests/CommandExecution/ExecuteCommandUpdateCatalogueDataLocationTests.cs @@ -37,17 +37,15 @@ private void CreateDatabase() { RemoteDatabase = DiscoveredServerICanCreateRandomDatabasesAndTablesOn.ExpectDatabase(RemoteDatabaseName); RemoteDatabase.Create(true); - using (var dt = new DataTable()) - { - dt.Columns.Add("Column1", typeof(string)); - dt.Columns.Add("Column2", typeof(int)); - - var dr = dt.NewRow(); - dr["Column1"] = "d"; - dr["Column2"] = 100; - dt.Rows.Add(dr); - RemoteTable = RemoteDatabase.CreateTable("SomeTable", dt); - } + using var dt = new DataTable(); + dt.Columns.Add("Column1", typeof(string)); + dt.Columns.Add("Column2", typeof(int)); + + var dr = dt.NewRow(); + dr["Column1"] = "d"; + dr["Column2"] = 100; + dt.Rows.Add(dr); + RemoteTable = RemoteDatabase.CreateTable("SomeTable", dt); } private void CreateCatalogue() diff --git a/Rdmp.Core.Tests/CommandExecution/TestExecuteCommandImportTableInfo.cs b/Rdmp.Core.Tests/CommandExecution/TestExecuteCommandImportTableInfo.cs index 7a9d3c98d1..031f536804 100644 --- a/Rdmp.Core.Tests/CommandExecution/TestExecuteCommandImportTableInfo.cs +++ b/Rdmp.Core.Tests/CommandExecution/TestExecuteCommandImportTableInfo.cs @@ -36,8 +36,7 @@ public void Test_ImportTableInfo_MalformedArgument() [Test] public void Test_ImportTableInfo_NoTable() { - var tbl = - "Table:MyTable:DatabaseType:MicrosoftSQLServer:Server=myServerAddress;Database=myDataBase;Trusted_Connection=True"; + const string tbl = "Table:MyTable:DatabaseType:MicrosoftSQLServer:Server=myServerAddress;Database=myDataBase;Trusted_Connection=True"; var ex = Assert.Throws(() => GetInvoker().ExecuteCommand(typeof(ExecuteCommandImportTableInfo), new CommandLineObjectPicker(new string[] { tbl, "true" }, GetActivator()))); diff --git a/Rdmp.Core.Tests/Curation/Anonymisation/ANOMigrationTests.cs b/Rdmp.Core.Tests/Curation/Anonymisation/ANOMigrationTests.cs index 4983d223c3..e59ff4b7eb 100644 --- a/Rdmp.Core.Tests/Curation/Anonymisation/ANOMigrationTests.cs +++ b/Rdmp.Core.Tests/Curation/Anonymisation/ANOMigrationTests.cs @@ -140,17 +140,16 @@ public void ConvertPrimaryKeyColumn() } - [Test] + /*[Test] [Order(3)] [TestCase("Condition2")] [TestCase("Condition3")] - [TestCase("Condition4")] - public void ConvertNonPrimaryKeyColumn(string conditionColumn) + [TestCase("Condition4")]*/ + private void ConvertNonPrimaryKeyColumn(string conditionColumn) { // TODO: This test doesn't ever seem to work! - return; -/* + /* //Value and a list of the rows in which it was found on (e.g. the value 'Fish' was found on row 11, 31, 52 and 501 /* Dictionary> rowsObjectFoundIn = new Dictionary>(); diff --git a/Rdmp.Core.Tests/Curation/DublinCoreTests.cs b/Rdmp.Core.Tests/Curation/DublinCoreTests.cs index 8a8b31df01..6d836b7670 100644 --- a/Rdmp.Core.Tests/Curation/DublinCoreTests.cs +++ b/Rdmp.Core.Tests/Curation/DublinCoreTests.cs @@ -72,60 +72,61 @@ public void TestWritingDocument() [Test] public void TestReadingDocument() { - var xml = - @" - - - - - UKOLN - - - UK Office for Library and Information Networking - - - national centre, network information support, library - community, awareness, research, information services,public - library networking, bibliographic management, distributed - library systems, metadata, resource discovery, - conferences,lectures, workshops - - - 062 - - - 061(410) - - - UKOLN is a national focus of expertise in digital information - management. It provides policy, research and awareness services - to the UK library, information and cultural heritage communities. - UKOLN is based at the University of Bath. - - - UKOLN est un centre national d'expertise dans la gestion de l'information - digitale. - - - UKOLN, University of Bath - - - http://www.bath.ac.uk/ - - - http://www.ukoln.ac.uk/ - - - 2001-07-18 - - - text/html - -"; + const string xml = """ + + + + + + UKOLN + + + UK Office for Library and Information Networking + + + national centre, network information support, library + community, awareness, research, information services,public + library networking, bibliographic management, distributed + library systems, metadata, resource discovery, + conferences,lectures, workshops + + + 062 + + + 061(410) + + + UKOLN is a national focus of expertise in digital information + management. It provides policy, research and awareness services + to the UK library, information and cultural heritage communities. + UKOLN is based at the University of Bath. + + + UKOLN est un centre national d'expertise dans la gestion de l'information + digitale. + + + UKOLN, University of Bath + + + http://www.bath.ac.uk/ + + + http://www.ukoln.ac.uk/ + + + 2001-07-18 + + + text/html + + + """; var fi = new FileInfo(Path.Combine(TestContext.CurrentContext.TestDirectory, "dublinTestReading.xml")); File.WriteAllText(fi.FullName, xml); diff --git a/Rdmp.Core.Tests/Curation/Integration/FilterImportingTests/ParameterCreatorTests.cs b/Rdmp.Core.Tests/Curation/Integration/FilterImportingTests/ParameterCreatorTests.cs index 87b58f6fe1..22059b5be0 100644 --- a/Rdmp.Core.Tests/Curation/Integration/FilterImportingTests/ParameterCreatorTests.cs +++ b/Rdmp.Core.Tests/Curation/Integration/FilterImportingTests/ParameterCreatorTests.cs @@ -182,40 +182,42 @@ public void SingleParameterTest_Template_TemplateValuesUsed() b=@b")] public void ReplaceParametersSQL(string haystack, string needle, string replacement, string expectedOutput) { - var output = ParameterCreator.RenameParameterInSQL(haystack, needle, replacement); - Assert.That(output, Is.EqualTo(expectedOutput)); + var output = ParameterCreator.RenameParameterInSQL(haystack, needle, replacement); + Assert.That(output, Is.EqualTo(expectedOutput)); } [Test] public void SequentialReplacementSQL() { - var haystack = - @"/*Paracetamol*/ -[test]..[prescribing].[approved_name] LIKE @drugName -OR -/*Ketamine*/ -[test]..[prescribing].[approved_name] LIKE @drugName2 -OR -/*Approved Name Like*/ -[test]..[prescribing].[approved_name] LIKE @drugName3"; - - - var newString = ParameterCreator.RenameParameterInSQL(haystack, "@drugName", "@drugName_2"); - newString = ParameterCreator.RenameParameterInSQL(newString, "@drugName2", "@drugName2_2"); - newString = ParameterCreator.RenameParameterInSQL(newString, "@drugName3", "@drugName3_2"); - - - var expectedoutput = - @"/*Paracetamol*/ -[test]..[prescribing].[approved_name] LIKE @drugName_2 -OR -/*Ketamine*/ -[test]..[prescribing].[approved_name] LIKE @drugName2_2 -OR -/*Approved Name Like*/ -[test]..[prescribing].[approved_name] LIKE @drugName3_2"; - - - Assert.That(newString, Is.EqualTo(expectedoutput)); + const string haystack = """ + /*Paracetamol*/ + [test]..[prescribing].[approved_name] LIKE @drugName + OR + /*Ketamine*/ + [test]..[prescribing].[approved_name] LIKE @drugName2 + OR + /*Approved Name Like*/ + [test]..[prescribing].[approved_name] LIKE @drugName3 + """; + + + var newString = ParameterCreator.RenameParameterInSQL(haystack, "@drugName", "@drugName_2"); + newString = ParameterCreator.RenameParameterInSQL(newString, "@drugName2", "@drugName2_2"); + newString = ParameterCreator.RenameParameterInSQL(newString, "@drugName3", "@drugName3_2"); + + + const string expectedoutput = """ + /*Paracetamol*/ + [test]..[prescribing].[approved_name] LIKE @drugName_2 + OR + /*Ketamine*/ + [test]..[prescribing].[approved_name] LIKE @drugName2_2 + OR + /*Approved Name Like*/ + [test]..[prescribing].[approved_name] LIKE @drugName3_2 + """; + + + Assert.That(newString, Is.EqualTo(expectedoutput)); } } \ No newline at end of file diff --git a/Rdmp.Core.Tests/Curation/Integration/PasswordEncryptionKeyLocationTests.cs b/Rdmp.Core.Tests/Curation/Integration/PasswordEncryptionKeyLocationTests.cs index ddfa9cec62..64f4388a6d 100644 --- a/Rdmp.Core.Tests/Curation/Integration/PasswordEncryptionKeyLocationTests.cs +++ b/Rdmp.Core.Tests/Curation/Integration/PasswordEncryptionKeyLocationTests.cs @@ -62,7 +62,7 @@ public void CreateKeyFile() [Test] public void Encrypt() { - var value = "MyPieceOfText"; + const string value = "MyPieceOfText"; Console.WriteLine($"String is:{value}"); diff --git a/Rdmp.Core.Tests/Curation/Integration/TableValuedFunctionTests/ImportAndTestTests.cs b/Rdmp.Core.Tests/Curation/Integration/TableValuedFunctionTests/ImportAndTestTests.cs index 979d5e405a..6928242a5f 100644 --- a/Rdmp.Core.Tests/Curation/Integration/TableValuedFunctionTests/ImportAndTestTests.cs +++ b/Rdmp.Core.Tests/Curation/Integration/TableValuedFunctionTests/ImportAndTestTests.cs @@ -133,8 +133,7 @@ public void TestDiscovery() [Test] public void Synchronization_ExtraParameter() { - var expectedMessage = - "MyAwesomeFunction is a Table Valued Function, in the Catalogue it has a parameter called @fish but this parameter no longer appears in the underlying database"; + const string expectedMessage = "MyAwesomeFunction is a Table Valued Function, in the Catalogue it has a parameter called @fish but this parameter no longer appears in the underlying database"; var excessParameter = new AnyTableSqlParameter(CatalogueRepository, _function.TableInfoCreated, "DECLARE @fish as int"); @@ -166,11 +165,10 @@ public void Synchronization_ExtraParameter() [Test] public void Synchronization_MissingParameter() { - var expectedMessage = - "MyAwesomeFunction is a Table Valued Function but it does not have a record of the parameter @startNumber which appears in the underlying database"; + const string expectedMessage = "MyAwesomeFunction is a Table Valued Function but it does not have a record of the parameter @startNumber which appears in the underlying database"; var parameter = (AnyTableSqlParameter)_function.TableInfoCreated.GetAllParameters() - .Single(p => p.ParameterName.Equals("@startNumber")); + .Single(static p => p.ParameterName.Equals("@startNumber")); parameter.DeleteInDatabase(); var syncer = new TableInfoSynchronizer(_function.TableInfoCreated); @@ -194,11 +192,10 @@ public void Synchronization_MissingParameter() [Test] public void Synchronization_ParameterDefinitionChanged() { - var expectedMessage = - "Parameter @startNumber is declared as 'DECLARE @startNumber AS int;' but in the Catalogue it appears as 'DECLARE @startNumber AS datetime;'"; + const string expectedMessage = "Parameter @startNumber is declared as 'DECLARE @startNumber AS int;' but in the Catalogue it appears as 'DECLARE @startNumber AS datetime;'"; var parameter = (AnyTableSqlParameter)_function.TableInfoCreated.GetAllParameters() - .Single(p => p.ParameterName.Equals("@startNumber")); + .Single(static p => p.ParameterName.Equals("@startNumber")); parameter.ParameterSQL = "DECLARE @startNumber AS datetime;"; parameter.SaveToDatabase(); diff --git a/Rdmp.Core.Tests/Curation/Integration/TriggerTests.cs b/Rdmp.Core.Tests/Curation/Integration/TriggerTests.cs index 8d2053222c..91a8565b51 100644 --- a/Rdmp.Core.Tests/Curation/Integration/TriggerTests.cs +++ b/Rdmp.Core.Tests/Curation/Integration/TriggerTests.cs @@ -73,7 +73,7 @@ public void CreateWithPks_Valid(DatabaseType dbType) { CreateTable(dbType); - _table.CreatePrimaryKey(new[] { _table.DiscoverColumn("name") }); + _table.CreatePrimaryKey(_table.DiscoverColumn("name")); GetImplementer().CreateTrigger(ThrowImmediatelyCheckNotifier.Quiet); Assert.Multiple(() => diff --git a/Rdmp.Core.Tests/Curation/JsonSerializationTests/JsonSerializationTests.cs b/Rdmp.Core.Tests/Curation/JsonSerializationTests/JsonSerializationTests.cs index 01e8681284..96e50582e5 100644 --- a/Rdmp.Core.Tests/Curation/JsonSerializationTests/JsonSerializationTests.cs +++ b/Rdmp.Core.Tests/Curation/JsonSerializationTests/JsonSerializationTests.cs @@ -37,7 +37,7 @@ public void TestSerialization_Catalogue() var asString = JsonConvert.SerializeObject(mySerializeable, dbConverter, lazyConverter); var mySerializeableAfter = (MySerializeableTestClass)JsonConvert.DeserializeObject(asString, - typeof(MySerializeableTestClass), new JsonConverter[] { dbConverter, lazyConverter }); + typeof(MySerializeableTestClass), dbConverter, lazyConverter); Assert.That(mySerializeableAfter, Is.Not.SameAs(mySerializeable)); Assert.That(mySerializeableAfter.SelectedCatalogue, Is.EqualTo(mySerializeable.SelectedCatalogue)); diff --git a/Rdmp.Core.Tests/Curation/Unit/ObjectConstructorTests.cs b/Rdmp.Core.Tests/Curation/Unit/ObjectConstructorTests.cs index bbe5a14b51..ba3caea844 100644 --- a/Rdmp.Core.Tests/Curation/Unit/ObjectConstructorTests.cs +++ b/Rdmp.Core.Tests/Curation/Unit/ObjectConstructorTests.cs @@ -92,9 +92,7 @@ public void GetRepositoryConstructor_AllDatabaseEntities_OneWinningConstructor() Console.WriteLine($"Found compatible constructors on {countCompatible} objects"); } - private class TestClassDefaultConstructor - { - } + private class TestClassDefaultConstructor; private class TestClass1 @@ -161,11 +159,7 @@ private class TestArg public string Text { get; set; } } - private class TestArg2 : TestArg - { - } + private class TestArg2 : TestArg; - private class TestArg3 : TestArg2 - { - } + private class TestArg3 : TestArg2; } \ No newline at end of file diff --git a/Rdmp.Core.Tests/Curation/Unit/PreInitializeTests.cs b/Rdmp.Core.Tests/Curation/Unit/PreInitializeTests.cs index 971de5aae0..77c5906cab 100644 --- a/Rdmp.Core.Tests/Curation/Unit/PreInitializeTests.cs +++ b/Rdmp.Core.Tests/Curation/Unit/PreInitializeTests.cs @@ -65,8 +65,8 @@ public void TestNoObjects() { var fishUser = new SpecificFishUser(); var ex = Assert.Throws(() => - context.PreInitialize(ThrowImmediatelyDataLoadEventListener.Quiet, fishUser, Array.Empty())); - Assert.That(ex.Message, Does.Contain("The following expected types were not passed to PreInitialize:Fish")); + context.PreInitialize(ThrowImmediatelyDataLoadEventListener.Quiet, fishUser)); + Assert.That(ex?.Message, Does.Contain("The following expected types were not passed to PreInitialize:Fish")); } [Test] diff --git a/Rdmp.Core.Tests/DataExport/CustomData/CustomDataImportingTests.cs b/Rdmp.Core.Tests/DataExport/CustomData/CustomDataImportingTests.cs index ae40f4bbfb..a10493248f 100644 --- a/Rdmp.Core.Tests/DataExport/CustomData/CustomDataImportingTests.cs +++ b/Rdmp.Core.Tests/DataExport/CustomData/CustomDataImportingTests.cs @@ -100,8 +100,8 @@ public void Extract_ProjectSpecificCatalogue_AppendedColumn() dt.Columns.Add("Name"); dt.Columns.Add("DateOfBirth"); - dt.Rows.Add(new object[] { "Priv_12345", "Bob", "2001-01-01" }); - dt.Rows.Add(new object[] { "Priv_wtf11", "Frank", "2001-10-29" }); + dt.Rows.Add("Priv_12345", "Bob", "2001-01-01"); + dt.Rows.Add("Priv_wtf11", "Frank", "2001-10-29"); blk.Upload(dt); } @@ -179,8 +179,8 @@ public void Extract_ProjectSpecificCatalogue_FilterReference() dt.Columns.Add("Name"); dt.Columns.Add("DateOfBirth"); - dt.Rows.Add(new object[] { "Priv_12345", "Bob", "2001-01-01" }); - dt.Rows.Add(new object[] { "Priv_wtf11", "Frank", "2001-10-29" }); + dt.Rows.Add("Priv_12345", "Bob", "2001-01-01"); + dt.Rows.Add("Priv_wtf11", "Frank", "2001-10-29"); blk.Upload(dt); } diff --git a/Rdmp.Core.Tests/DataExport/DataExtraction/ExecuteFullExtractionToDatabaseMSSqlDestinationReExtractionTest.cs b/Rdmp.Core.Tests/DataExport/DataExtraction/ExecuteFullExtractionToDatabaseMSSqlDestinationReExtractionTest.cs index df28b536ba..c81a3bb654 100644 --- a/Rdmp.Core.Tests/DataExport/DataExtraction/ExecuteFullExtractionToDatabaseMSSqlDestinationReExtractionTest.cs +++ b/Rdmp.Core.Tests/DataExport/DataExtraction/ExecuteFullExtractionToDatabaseMSSqlDestinationReExtractionTest.cs @@ -107,8 +107,8 @@ public void ReExtractToADatabaseWithNoNewData() agg1.SaveToDatabase(); var CohortDatabaseName = TestDatabaseNames.GetConsistentName("CohortDatabase"); - var cohortTableName = "Cohort"; - var definitionTableName = "CohortDefinition"; + const string cohortTableName = "Cohort"; + const string definitionTableName = "CohortDefinition"; var ExternalCohortTableNameInCatalogue = "CohortTests"; const string ReleaseIdentifierFieldName = "ReleaseId"; const string DefinitionTableForeignKeyField = "cohortDefinition_id"; @@ -334,9 +334,9 @@ public void ReExtractToADatabaseWithNewDataAndNoPKs() agg1.SaveToDatabase(); var CohortDatabaseName = TestDatabaseNames.GetConsistentName("CohortDatabase"); - var cohortTableName = "Cohort"; - var definitionTableName = "CohortDefinition"; - var ExternalCohortTableNameInCatalogue = "CohortTests"; + const string cohortTableName = "Cohort"; + const string definitionTableName = "CohortDefinition"; + const string ExternalCohortTableNameInCatalogue = "CohortTests"; const string ReleaseIdentifierFieldName = "ReleaseId"; const string DefinitionTableForeignKeyField = "cohortDefinition_id"; var _cohortDatabase = DiscoveredServerICanCreateRandomDatabasesAndTablesOn.ExpectDatabase(CohortDatabaseName); @@ -596,9 +596,9 @@ public void ReExtractToADatabaseWithNewDataAndSinglePK() agg1.SaveToDatabase(); var CohortDatabaseName = TestDatabaseNames.GetConsistentName("CohortDatabase"); - var cohortTableName = "Cohort"; - var definitionTableName = "CohortDefinition"; - var ExternalCohortTableNameInCatalogue = "CohortTests"; + const string cohortTableName = "Cohort"; + const string definitionTableName = "CohortDefinition"; + const string ExternalCohortTableNameInCatalogue = "CohortTests"; const string ReleaseIdentifierFieldName = "ReleaseId"; const string DefinitionTableForeignKeyField = "cohortDefinition_id"; var _cohortDatabase = DiscoveredServerICanCreateRandomDatabasesAndTablesOn.ExpectDatabase(CohortDatabaseName); @@ -1120,9 +1120,9 @@ public void ExtractToDatabaseUseTriggers() agg1.SaveToDatabase(); var CohortDatabaseName = TestDatabaseNames.GetConsistentName("CohortDatabase"); - var cohortTableName = "Cohort"; - var definitionTableName = "CohortDefinition"; - var ExternalCohortTableNameInCatalogue = "CohortTests"; + const string cohortTableName = "Cohort"; + const string definitionTableName = "CohortDefinition"; + const string ExternalCohortTableNameInCatalogue = "CohortTests"; const string ReleaseIdentifierFieldName = "ReleaseId"; const string DefinitionTableForeignKeyField = "cohortDefinition_id"; var _cohortDatabase = DiscoveredServerICanCreateRandomDatabasesAndTablesOn.ExpectDatabase(CohortDatabaseName); diff --git a/Rdmp.Core.Tests/DataExport/DataExtraction/ExecutePkSynthesizerDatasetExtractionSourceTests.cs b/Rdmp.Core.Tests/DataExport/DataExtraction/ExecutePkSynthesizerDatasetExtractionSourceTests.cs index 9e79e915b7..2c94031a05 100644 --- a/Rdmp.Core.Tests/DataExport/DataExtraction/ExecutePkSynthesizerDatasetExtractionSourceTests.cs +++ b/Rdmp.Core.Tests/DataExport/DataExtraction/ExecutePkSynthesizerDatasetExtractionSourceTests.cs @@ -159,7 +159,7 @@ private void SetupJoin() dt.Columns.Add("Name"); dt.Columns.Add("Description"); - dt.Rows.Add(new object[] { "Dave", "Is a maniac" }); + dt.Rows.Add("Dave", "Is a maniac"); var tbl = Database.CreateTable("SimpleJoin", dt, new[] @@ -190,7 +190,7 @@ private void SetupLookupTable() dt.Columns.Add("Name"); dt.Columns.Add("Description"); - dt.Rows.Add(new object[] { "Dave", "Is a maniac" }); + dt.Rows.Add("Dave", "Is a maniac"); var tbl = Database.CreateTable("SimpleLookup", dt, new[] { new DatabaseColumnRequest("Name", new DatabaseTypeRequest(typeof(string), 50)) }); @@ -221,7 +221,7 @@ private ExtractDatasetCommand SetupExtractDatasetCommand(string testTableName, s dt.PrimaryKey = dt.Columns.Cast().Where(col => pkColumnInfos.Contains(col.ColumnName)).ToArray(); - dt.Rows.Add(new object[] { _cohortKeysGenerated.Keys.First(), "Dave", "2001-01-01" }); + dt.Rows.Add(_cohortKeysGenerated.Keys.First(), "Dave", "2001-01-01"); var tbl = Database.CreateTable(testTableName, dt, diff --git a/Rdmp.Core.Tests/DataLoad/Engine/Integration/CoalescerTests.cs b/Rdmp.Core.Tests/DataLoad/Engine/Integration/CoalescerTests.cs index b1aca56222..af408c1762 100644 --- a/Rdmp.Core.Tests/DataLoad/Engine/Integration/CoalescerTests.cs +++ b/Rdmp.Core.Tests/DataLoad/Engine/Integration/CoalescerTests.cs @@ -47,34 +47,34 @@ public void TestCoalescer_RampantNullness(DatabaseType type, bool useCustomNamer var randInt = r.Next(250); var randCompleteness = r.Next(4); - dt.Rows.Add(new object[] { randInt, randInt, randInt, randInt, randInt }); - dt.Rows.Add(new object[] { randInt, DBNull.Value, DBNull.Value, DBNull.Value, randInt }); - dt.Rows.Add(new object[] { randInt, DBNull.Value, DBNull.Value, randInt, DBNull.Value }); - dt.Rows.Add(new object[] { randInt, DBNull.Value, DBNull.Value, randInt, randInt }); + dt.Rows.Add(randInt, randInt, randInt, randInt, randInt); + dt.Rows.Add(randInt, DBNull.Value, DBNull.Value, DBNull.Value, randInt); + dt.Rows.Add(randInt, DBNull.Value, DBNull.Value, randInt, DBNull.Value); + dt.Rows.Add(randInt, DBNull.Value, DBNull.Value, randInt, randInt); if (randCompleteness >= 1) { - dt.Rows.Add(new object[] { randInt, DBNull.Value, randInt, DBNull.Value, DBNull.Value }); - dt.Rows.Add(new object[] { randInt, DBNull.Value, randInt, DBNull.Value, randInt }); - dt.Rows.Add(new object[] { randInt, DBNull.Value, randInt, randInt, DBNull.Value }); - dt.Rows.Add(new object[] { randInt, DBNull.Value, randInt, randInt, randInt }); + dt.Rows.Add(randInt, DBNull.Value, randInt, DBNull.Value, DBNull.Value); + dt.Rows.Add(randInt, DBNull.Value, randInt, DBNull.Value, randInt); + dt.Rows.Add(randInt, DBNull.Value, randInt, randInt, DBNull.Value); + dt.Rows.Add(randInt, DBNull.Value, randInt, randInt, randInt); } if (randCompleteness >= 2) { - dt.Rows.Add(new object[] { randInt, randInt, DBNull.Value, DBNull.Value, DBNull.Value }); - dt.Rows.Add(new object[] { randInt, randInt, DBNull.Value, DBNull.Value, randInt }); - dt.Rows.Add(new object[] { randInt, randInt, DBNull.Value, randInt, DBNull.Value }); - dt.Rows.Add(new object[] { randInt, randInt, DBNull.Value, randInt, randInt }); + dt.Rows.Add(randInt, randInt, DBNull.Value, DBNull.Value, DBNull.Value); + dt.Rows.Add(randInt, randInt, DBNull.Value, DBNull.Value, randInt); + dt.Rows.Add(randInt, randInt, DBNull.Value, randInt, DBNull.Value); + dt.Rows.Add(randInt, randInt, DBNull.Value, randInt, randInt); } if (randCompleteness >= 3) { - dt.Rows.Add(new object[] { randInt, randInt, randInt, DBNull.Value, DBNull.Value }); - dt.Rows.Add(new object[] { randInt, randInt, randInt, DBNull.Value, randInt }); - dt.Rows.Add(new object[] { randInt, randInt, randInt, randInt, DBNull.Value }); - dt.Rows.Add(new object[] { randInt, DBNull.Value, DBNull.Value, DBNull.Value, DBNull.Value }); + dt.Rows.Add(randInt, randInt, randInt, DBNull.Value, DBNull.Value); + dt.Rows.Add(randInt, randInt, randInt, DBNull.Value, randInt); + dt.Rows.Add(randInt, randInt, randInt, randInt, DBNull.Value); + dt.Rows.Add(randInt, DBNull.Value, DBNull.Value, DBNull.Value, DBNull.Value); } } diff --git a/Rdmp.Core.Tests/DataLoad/Engine/Integration/CrossDatabaseTypeTests/CrossDatabaseDataLoadTests.cs b/Rdmp.Core.Tests/DataLoad/Engine/Integration/CrossDatabaseTypeTests/CrossDatabaseDataLoadTests.cs index 404e8ce21d..0029785705 100644 --- a/Rdmp.Core.Tests/DataLoad/Engine/Integration/CrossDatabaseTypeTests/CrossDatabaseDataLoadTests.cs +++ b/Rdmp.Core.Tests/DataLoad/Engine/Integration/CrossDatabaseTypeTests/CrossDatabaseDataLoadTests.cs @@ -14,7 +14,6 @@ using FAnsi.Discovery; using FAnsi.Discovery.TableCreation; using NUnit.Framework; -using Rdmp.Core.CommandExecution; using Rdmp.Core.Curation.Data; using Rdmp.Core.Curation.Data.DataLoad; using Rdmp.Core.Curation.Data.Defaults; diff --git a/Rdmp.Core.Tests/DataLoad/Engine/Integration/CrossDatabaseTypeTests/CrossDatabaseMergeCommandTest.cs b/Rdmp.Core.Tests/DataLoad/Engine/Integration/CrossDatabaseTypeTests/CrossDatabaseMergeCommandTest.cs index fc3bae814d..4be9ddf9bd 100644 --- a/Rdmp.Core.Tests/DataLoad/Engine/Integration/CrossDatabaseTypeTests/CrossDatabaseMergeCommandTest.cs +++ b/Rdmp.Core.Tests/DataLoad/Engine/Integration/CrossDatabaseTypeTests/CrossDatabaseMergeCommandTest.cs @@ -44,11 +44,11 @@ public void TestMerge(DatabaseType databaseType) dt.Columns.Add("Postcode", typeof(string)); //Data in live awaiting toTbl be updated - dt.Rows.Add(new object[] { "Dave", 18, "DD3 1AB" }); - dt.Rows.Add(new object[] { "Dave", 25, "DD1 1XS" }); - dt.Rows.Add(new object[] { "Mango", 32, DBNull.Value }); - dt.Rows.Add(new object[] { "Filli", 32, "DD3 78L" }); - dt.Rows.Add(new object[] { "Mandrake", 32, DBNull.Value }); + dt.Rows.Add("Dave", 18, "DD3 1AB"); + dt.Rows.Add("Dave", 25, "DD1 1XS"); + dt.Rows.Add("Mango", 32, DBNull.Value); + dt.Rows.Add("Filli", 32, "DD3 78L"); + dt.Rows.Add("Mandrake", 32, DBNull.Value); dt.PrimaryKey = new[] { colName, colAge }; @@ -64,12 +64,12 @@ public void TestMerge(DatabaseType databaseType) dt.Rows.Clear(); //new data being loaded - dt.Rows.Add(new object[] { "Dave", 25, "DD1 1PS" }); //update toTbl change postcode toTbl "DD1 1PS" - dt.Rows.Add(new object[] { "Chutney", 32, DBNull.Value }); //new insert Chutney - dt.Rows.Add(new object[] { "Mango", 32, DBNull.Value }); //ignored because already present in dataset - dt.Rows.Add(new object[] { "Filli", 32, DBNull.Value }); //update from "DD3 78L" null - dt.Rows.Add(new object[] { "Mandrake", 32, "DD1 1PS" }); //update from null toTbl "DD1 1PS" - dt.Rows.Add(new object[] { "Mandrake", 31, "DD1 1PS" }); // insert because Age is unique (and part of pk) + dt.Rows.Add("Dave", 25, "DD1 1PS"); //update toTbl change postcode toTbl "DD1 1PS" + dt.Rows.Add("Chutney", 32, DBNull.Value); //new insert Chutney + dt.Rows.Add("Mango", 32, DBNull.Value); //ignored because already present in dataset + dt.Rows.Add("Filli", 32, DBNull.Value); //update from "DD3 78L" null + dt.Rows.Add("Mandrake", 32, "DD1 1PS"); //update from null toTbl "DD1 1PS" + dt.Rows.Add("Mandrake", 31, "DD1 1PS"); // insert because Age is unique (and part of pk) var fromTbl = From.CreateTable($"{DatabaseName}_ToTable_STAGING", dt); diff --git a/Rdmp.Core.Tests/DataLoad/Engine/Integration/CrossDatabaseTypeTests/HowDoWeAchieveMd5Test.cs b/Rdmp.Core.Tests/DataLoad/Engine/Integration/CrossDatabaseTypeTests/HowDoWeAchieveMd5Test.cs index 94a9e00580..49d4ff738f 100644 --- a/Rdmp.Core.Tests/DataLoad/Engine/Integration/CrossDatabaseTypeTests/HowDoWeAchieveMd5Test.cs +++ b/Rdmp.Core.Tests/DataLoad/Engine/Integration/CrossDatabaseTypeTests/HowDoWeAchieveMd5Test.cs @@ -20,7 +20,7 @@ public void TestMd5String(DatabaseType type) { var dt = new DataTable(); dt.Columns.Add("F"); - dt.Rows.Add(new[] { "Fish" }); + dt.Rows.Add("Fish"); var db = GetCleanedServer(type); var tbl = db.CreateTable("MD5Test", dt); @@ -50,7 +50,7 @@ public void TestMd5Date(DatabaseType type) { var dt = new DataTable(); dt.Columns.Add("F"); - dt.Rows.Add(new[] { "2001-01-01" }); + dt.Rows.Add("2001-01-01"); var db = GetCleanedServer(type); var tbl = db.CreateTable("MD5Test", dt); diff --git a/Rdmp.Core.Tests/DataLoad/Engine/Integration/DataTableUploadDestinationTests.cs b/Rdmp.Core.Tests/DataLoad/Engine/Integration/DataTableUploadDestinationTests.cs index ffe63b1da1..8199da7695 100644 --- a/Rdmp.Core.Tests/DataLoad/Engine/Integration/DataTableUploadDestinationTests.cs +++ b/Rdmp.Core.Tests/DataLoad/Engine/Integration/DataTableUploadDestinationTests.cs @@ -7,7 +7,6 @@ using System; using System.Collections.Generic; using System.Data; -using System.Data.Common; using System.Linq; using FAnsi; using FAnsi.Discovery; @@ -37,22 +36,21 @@ public void DataTableChangesLengths_NoReAlter() var dt1 = new DataTable(); dt1.Columns.Add("name", typeof(string)); - dt1.Rows.Add(new[] { "Fish" }); + dt1.Rows.Add("Fish"); dt1.TableName = "DataTableUploadDestinationTests"; var dt2 = new DataTable(); dt2.Columns.Add("name", typeof(string)); - dt2.Rows.Add(new[] { "BigFish" }); + dt2.Rows.Add("BigFish"); dt2.TableName = "DataTableUploadDestinationTests"; destination.ProcessPipelineData(dt1, toConsole, token); var ex = Assert.Throws(() => destination.ProcessPipelineData(dt2, toConsole, token)); - var expectedText = - "BulkInsert failed on data row 1 the complaint was about source column <> which had value <> destination data type was <>"; + const string expectedText = "BulkInsert failed on data row 1 the complaint was about source column <> which had value <> destination data type was <>"; - Assert.That(ex.InnerException, Is.Not.Null); - Assert.That(ex.InnerException.Message, Does.Contain(expectedText)); + Assert.That(ex?.InnerException, Is.Not.Null); + Assert.That(ex?.InnerException?.Message, Does.Contain(expectedText)); destination.Dispose(ThrowImmediatelyDataLoadEventListener.Quiet, ex); } @@ -171,15 +169,17 @@ public void DataTableChangesLengths_DropColumns() if (tbl.Exists()) tbl.Drop(); - var sql = @"CREATE TABLE DroppedColumnsTable ( -name varchar(50), -color varchar(50), -age varchar(50) -) + const string sql = """ + CREATE TABLE DroppedColumnsTable ( + name varchar(50), + color varchar(50), + age varchar(50) + ) + + ALTER TABLE DroppedColumnsTable Drop column color + ALTER TABLE DroppedColumnsTable add color varchar(1) -ALTER TABLE DroppedColumnsTable Drop column color -ALTER TABLE DroppedColumnsTable add color varchar(1) -"; + """; Console.Write($"About to execute:{sql}"); @@ -187,7 +187,8 @@ ALTER TABLE DroppedColumnsTable add color varchar(1) using (var con = db.Server.GetConnection()) { con.Open(); - db.Server.GetCommand(sql, con).ExecuteNonQuery(); + using var cmd = db.Server.GetCommand(sql, con); + cmd.ExecuteNonQuery(); } //the bulk insert is @@ -274,12 +275,12 @@ public void DataTableChangesLengths_AllowAlter() var dt1 = new DataTable(); dt1.Columns.Add("name", typeof(string)); - dt1.Rows.Add(new[] { "Fish" }); + dt1.Rows.Add("Fish"); dt1.TableName = "DataTableUploadDestinationTests"; var dt2 = new DataTable(); dt2.Columns.Add("name", typeof(string)); - dt2.Rows.Add(new[] { "BigFish" }); + dt2.Rows.Add("BigFish"); dt2.TableName = "DataTableUploadDestinationTests"; destination.ProcessPipelineData(dt1, toConsole, token); @@ -308,11 +309,11 @@ public void DoubleResizingBetweenIntAndDouble() var dt1 = new DataTable(); dt1.Columns.Add("mynum", typeof(double)); - dt1.Rows.Add(new object[] { 1 }); - dt1.Rows.Add(new object[] { 5 }); - dt1.Rows.Add(new object[] { 15 }); - dt1.Rows.Add(new object[] { 2.5 }); - dt1.Rows.Add(new object[] { 5 }); + dt1.Rows.Add(1); + dt1.Rows.Add(5); + dt1.Rows.Add(15); + dt1.Rows.Add(2.5); + dt1.Rows.Add(5); dt1.TableName = "DataTableUploadDestinationTests"; @@ -342,7 +343,7 @@ public void BatchResizing(string expectedDatatypeInDatabase, object batch1Value, var dt1 = new DataTable(); dt1.Columns.Add("mycol"); - dt1.Rows.Add(new[] { batch1Value }); + dt1.Rows.Add(batch1Value); dt1.TableName = "DataTableUploadDestinationTests"; try @@ -351,7 +352,7 @@ public void BatchResizing(string expectedDatatypeInDatabase, object batch1Value, var dt2 = new DataTable(); dt2.Columns.Add("mycol"); - dt2.Rows.Add(new object[] { batch2Value }); + dt2.Rows.Add(batch2Value); destination.ProcessPipelineData(dt2, toConsole, token); destination.Dispose(toConsole, null); @@ -379,7 +380,7 @@ public void BatchResizing_WithExplicitWriteTypes(string expectedDatatypeInDataba var dt1 = new DataTable(); dt1.Columns.Add("mycol"); - dt1.Rows.Add(new[] { batch1Value }); + dt1.Rows.Add(batch1Value); dt1.TableName = "DataTableUploadDestinationTests"; try @@ -389,7 +390,7 @@ public void BatchResizing_WithExplicitWriteTypes(string expectedDatatypeInDataba var dt2 = new DataTable(); dt2.Columns.Add("mycol"); - dt2.Rows.Add(new object[] { batch2Value }); + dt2.Rows.Add(batch2Value); destination.ProcessPipelineData(dt2, toConsole, token); destination.Dispose(toConsole, null); @@ -422,7 +423,7 @@ public void VeryLongStringIsVarcharMax() var dt1 = new DataTable(); dt1.Columns.Add("myText"); - dt1.Rows.Add(new object[] { longBitOfText }); + dt1.Rows.Add(longBitOfText); dt1.TableName = "DataTableUploadDestinationTests"; @@ -454,17 +455,17 @@ public void DecimalResizing(bool negative) var dt1 = new DataTable(); dt1.Columns.Add("mynum", typeof(string)); - dt1.Rows.Add(new[] { "1.51" }); + dt1.Rows.Add("1.51"); dt1.TableName = "DataTableUploadDestinationTests"; var dt2 = new DataTable(); dt2.Columns.Add("mynum", typeof(string)); - dt2.Rows.Add(new[] { negative ? "-999.99" : "999.99" }); - dt2.Rows.Add(new[] { "00000.00000" }); - dt2.Rows.Add(new[] { "0" }); + dt2.Rows.Add(negative ? "-999.99" : "999.99"); + dt2.Rows.Add("00000.00000"); + dt2.Rows.Add("0"); dt2.Rows.Add(new string[] { null }); - dt2.Rows.Add(new[] { "" }); - dt2.Rows.Add(new[] { DBNull.Value }); + dt2.Rows.Add(""); + dt2.Rows.Add(DBNull.Value); dt2.TableName = "DataTableUploadDestinationTests"; destination.ProcessPipelineData(dt1, toConsole, token); @@ -522,7 +523,7 @@ public void DataTypeEstimation(string expectedDatatypeInDatabase, object[] rowVa dt1.Columns.Add("myCol", typeof(string)); foreach (var rowValue in rowValues) - dt1.Rows.Add(new[] { rowValue }); + dt1.Rows.Add(rowValue); dt1.TableName = "DataTableUploadDestinationTests"; @@ -565,10 +566,10 @@ public void DecimalZeros(bool sendTheZero) var dt1 = new DataTable(); dt1.Columns.Add("mynum", typeof(string)); - dt1.Rows.Add(new[] { "0.000742548000424313" }); + dt1.Rows.Add("0.000742548000424313"); if (sendTheZero) - dt1.Rows.Add(new[] { "0" }); + dt1.Rows.Add("0"); dt1.TableName = "DataTableUploadDestinationTests"; @@ -779,7 +780,7 @@ public void DodgyTypes() dt1.Columns.Add("col4", typeof(byte)); dt1.Columns.Add("col5", typeof(byte[])); - dt1.Rows.Add(new object[] { 0.425, 0.451, true, (byte)2, new byte[] { 0x5, 0xA } }); + dt1.Rows.Add(0.425, 0.451, true, (byte)2, new byte[] { 0x5, 0xA }); dt1.TableName = "DataTableUploadDestinationTests"; @@ -820,12 +821,12 @@ public void TypeAlteringlResizing() var dt1 = new DataTable(); dt1.Columns.Add("mynum", typeof(string)); - dt1.Rows.Add(new[] { "true" }); + dt1.Rows.Add("true"); dt1.TableName = "DataTableUploadDestinationTests"; var dt2 = new DataTable(); dt2.Columns.Add("mynum", typeof(string)); - dt2.Rows.Add(new[] { "999" }); + dt2.Rows.Add("999"); dt2.TableName = "DataTableUploadDestinationTests"; destination.ProcessPipelineData(dt1, toConsole, token); @@ -868,7 +869,7 @@ public void MySqlTest_Simple() var now = DateTime.Now; now = new DateTime(now.Year, now.Month, now.Day, now.Hour, now.Minute, now.Second); - dt.Rows.Add(new object[] { "Anhoy there \"mates\"", "999", "2001-01-01", now, null }); + dt.Rows.Add("Anhoy there \"mates\"", "999", "2001-01-01", now, null); dt.TableName = "DataTableUploadDestinationTests"; destination.ProcessPipelineData(dt, toConsole, token); @@ -917,12 +918,12 @@ public void MySqlTest_Resize() var dt1 = new DataTable(); dt1.Columns.Add("mynum", typeof(string)); - dt1.Rows.Add(new[] { "true" }); + dt1.Rows.Add("true"); dt1.TableName = "DataTableUploadDestinationTests"; var dt2 = new DataTable(); dt2.Columns.Add("mynum", typeof(string)); - dt2.Rows.Add(new[] { "999" }); + dt2.Rows.Add("999"); dt2.TableName = "DataTableUploadDestinationTests"; destination.ProcessPipelineData(dt1, toConsole, token); @@ -971,7 +972,7 @@ public void TestDestinationAlreadyExistingIsOk(bool targetTableIsEmpty) //upload a single row var dtAlreadyThereData = new DataTable(); dtAlreadyThereData.Columns.Add("Name"); - dtAlreadyThereData.Rows.Add(new[] { "Bob" }); + dtAlreadyThereData.Rows.Add("Bob"); using var bulk = tbl.BeginBulkInsert(); bulk.Upload(dtAlreadyThereData); @@ -987,9 +988,9 @@ public void TestDestinationAlreadyExistingIsOk(bool targetTableIsEmpty) //create the simulated chunk that will be dispatched var dt = new DataTable("TestDestinationAlreadyExistingIsOk"); dt.Columns.Add("Name"); - dt.Rows.Add(new[] { "Bob" }); - dt.Rows.Add(new[] { "Frank" }); - dt.Rows.Add(new[] { "I've got a lovely bunch of coconuts" }); + dt.Rows.Add("Bob"); + dt.Rows.Add("Frank"); + dt.Rows.Add("I've got a lovely bunch of coconuts"); var listener = ThrowImmediatelyDataLoadEventListener.Quiet; @@ -1075,7 +1076,7 @@ public void TestDestinationAlreadyExisting_ColumnSubset() var dtAlreadyThereData = new DataTable(); dtAlreadyThereData.Columns.Add("Name"); dtAlreadyThereData.Columns.Add("Age"); - dtAlreadyThereData.Rows.Add(new object[] { "Bob", 5 }); + dtAlreadyThereData.Rows.Add("Bob", 5); using (var bulk = tbl.BeginBulkInsert()) { @@ -1092,9 +1093,9 @@ public void TestDestinationAlreadyExisting_ColumnSubset() //create the simulated chunk that will be dispatched var dt = new DataTable("TestDestinationAlreadyExisting_ColumnSubset"); dt.Columns.Add("Name"); - dt.Rows.Add(new[] { "Bob" }); - dt.Rows.Add(new[] { "Frank" }); - dt.Rows.Add(new[] { "I've got a lovely bunch of coconuts" }); + dt.Rows.Add("Bob"); + dt.Rows.Add("Frank"); + dt.Rows.Add("I've got a lovely bunch of coconuts"); var listener = ThrowImmediatelyDataLoadEventListener.Quiet; @@ -1239,7 +1240,7 @@ public void TwoBatch_BooleanResizingTest(DatabaseType dbType, bool giveNullValue var dt1 = new DataTable(); dt1.Columns.Add("TestedCol", typeof(string)); dt1.Columns.Add("OtherCol", typeof(string)); - dt1.Rows.Add(new[] { giveNullValuesOnly ? null : "true", "1.51" }); + dt1.Rows.Add(giveNullValuesOnly ? null : "true", "1.51"); dt1.TableName = "DataTableUploadDestinationTests"; @@ -1247,7 +1248,7 @@ public void TwoBatch_BooleanResizingTest(DatabaseType dbType, bool giveNullValue dt2.Columns.Add("TestedCol", typeof(string)); dt2.Columns.Add("OtherCol", typeof(string)); - dt2.Rows.Add(new[] { "2001-01-01", "999.99" }); + dt2.Rows.Add("2001-01-01", "999.99"); dt2.TableName = "DataTableUploadDestinationTests"; @@ -1313,7 +1314,7 @@ public void TwoBatch_MiscellaneousTest(DatabaseType dbType, string v1, string v2 var dt1 = new DataTable(); dt1.Columns.Add("TestedCol", typeof(string)); - dt1.Rows.Add(new[] { v1 }); + dt1.Rows.Add(v1); if (v1 != null && v2 != null) dt1.PrimaryKey = dt1.Columns.Cast().ToArray(); @@ -1323,7 +1324,7 @@ public void TwoBatch_MiscellaneousTest(DatabaseType dbType, string v1, string v2 var dt2 = new DataTable(); dt2.Columns.Add("TestedCol", typeof(string)); - dt2.Rows.Add(new[] { v2 }); + dt2.Rows.Add(v2); dt2.TableName = "DataTableUploadDestinationTests"; var tt = db.Server.GetQuerySyntaxHelper().TypeTranslater; @@ -1375,13 +1376,13 @@ public void TwoBatch_ExplicitRealDataType() var dt1 = new DataTable(); dt1.Columns.Add("FloatCol", typeof(string)); - dt1.Rows.Add(new[] { "1.51" }); + dt1.Rows.Add("1.51"); dt1.TableName = "DataTableUploadDestinationTests"; var dt2 = new DataTable(); dt2.Columns.Add("FloatCol", typeof(string)); - dt2.Rows.Add(new[] { "99.9999" }); + dt2.Rows.Add("99.9999"); dt2.TableName = "DataTableUploadDestinationTests"; @@ -1421,7 +1422,7 @@ public void CreateIndex_OK() var dt1 = new DataTable(); dt1.Columns.Add("name", typeof(string)); - dt1.Rows.Add(new[] { "Fish" }); + dt1.Rows.Add("Fish"); dt1.TableName = "DataTableUploadDestinationTests"; try { @@ -1433,15 +1434,14 @@ public void CreateIndex_OK() destination.Dispose(ThrowImmediatelyDataLoadEventListener.Quiet, ex); throw; } - using (var con = db.Server.GetConnection()) - { - con.Open(); - DbCommand cmd = db.Server.GetCommand("select * from sys.indexes where name = 'CreateIndex_OK'", con); - var r = cmd.ExecuteReader(); - Assert.That(r.HasRows); - r.Read(); - Assert.That(r["name"], Is.EqualTo("CreateIndex_OK")); - } + + using var con = db.Server.GetConnection(); + con.Open(); + using var cmd = db.Server.GetCommand("select * from sys.indexes where name = 'CreateIndex_OK'", con); + var r = cmd.ExecuteReader(); + Assert.That(r.HasRows); + r.Read(); + Assert.That(r["name"], Is.EqualTo("CreateIndex_OK")); } [Test] @@ -1460,7 +1460,7 @@ public void CreateIndex_NO_PK() var dt1 = new DataTable(); dt1.Columns.Add("name", typeof(string)); - dt1.Rows.Add(new[] { "Fish" }); + dt1.Rows.Add("Fish"); dt1.TableName = "DataTableUploadDestinationTests"; try @@ -1473,13 +1473,12 @@ public void CreateIndex_NO_PK() destination.Dispose(ThrowImmediatelyDataLoadEventListener.Quiet, ex); throw; } - using (var con = db.Server.GetConnection()) - { - con.Open(); - DbCommand cmd = db.Server.GetCommand("select * from sys.indexes where name = 'CreateIndex_OK'", con); - var r = cmd.ExecuteReader(); - Assert.That(r.HasRows, Is.EqualTo(false)); - } + + using var con = db.Server.GetConnection(); + con.Open(); + using var cmd = db.Server.GetCommand("select * from sys.indexes where name = 'CreateIndex_OK'", con); + var r = cmd.ExecuteReader(); + Assert.That(r.HasRows, Is.EqualTo(false)); } [Test] @@ -1499,7 +1498,7 @@ public void CreateIndex_RecreateExistingFail() var dt1 = new DataTable(); dt1.Columns.Add("name", typeof(string)); - dt1.Rows.Add(new[] { "Fish" }); + dt1.Rows.Add("Fish"); dt1.TableName = "DataTableUploadDestinationTests"; try { @@ -1512,16 +1511,18 @@ public void CreateIndex_RecreateExistingFail() destination.Dispose(ThrowImmediatelyDataLoadEventListener.Quiet, ex); throw; } - using (var con = db.Server.GetConnection()) + + using var con = db.Server.GetConnection(); + con.Open(); + using var cmd = db.Server.GetCommand("select * from sys.indexes where name = 'CreateIndex_OK'", con); + var r = cmd.ExecuteReader(); + Assert.That(r.HasRows); + r.Read(); + Assert.Multiple(() => { - con.Open(); - DbCommand cmd = db.Server.GetCommand("select * from sys.indexes where name = 'CreateIndex_OK'", con); - var r = cmd.ExecuteReader(); - Assert.That(r.HasRows); - r.Read(); Assert.That(r["name"], Is.EqualTo("CreateIndex_OK")); - Assert.That(r.Read(), Is.EqualTo(false));//only 1 row - } + Assert.That(r.Read(), Is.EqualTo(false)); //only 1 row + }); } [Test] @@ -1539,7 +1540,7 @@ public void UseTriggerwithoutPrimaryKey() var dt1 = new DataTable(); dt1.Columns.Add("name", typeof(string)); - dt1.Rows.Add(new[] { "Fish" }); + dt1.Rows.Add("Fish"); dt1.TableName = "DataTableUploadDestinationTests"; try { @@ -1574,7 +1575,7 @@ public void UseTriggerwithPrimaryKey() var dt1 = new DataTable(); dt1.Columns.Add("name", typeof(string)); - dt1.Rows.Add(new[] { "Fish" }); + dt1.Rows.Add("Fish"); dt1.PrimaryKey = new[] { dt1.Columns[0] }; dt1.TableName = "DataTableUploadDestinationTests"; try @@ -1614,7 +1615,7 @@ public void DataTableUploadClashSameRow() var dt1 = new DataTable(); dt1.Columns.Add("name", typeof(string)); dt1.Columns.Add("other", typeof(string)); - dt1.Rows.Add(new[] { "Fish", "Friend" }); + dt1.Rows.Add("Fish", "Friend"); dt1.PrimaryKey = new[] { dt1.Columns[0] }; dt1.TableName = "DataTableUploadDestinationTests"; try @@ -1624,9 +1625,9 @@ public void DataTableUploadClashSameRow() dt1 = new DataTable(); dt1.Columns.Add("name", typeof(string)); dt1.Columns.Add("other", typeof(string)); - dt1.Rows.Add(new[] { "Fish", "Friend" }); + dt1.Rows.Add("Fish", "Friend"); dt1.PrimaryKey = new[] { dt1.Columns[0] }; - dt1.TableName = "DataTableUploadDestinationTests"; ; + dt1.TableName = "DataTableUploadDestinationTests"; Assert.Throws(()=>destination.ProcessPipelineData(dt1, toConsole, token)); destination.Dispose(ThrowImmediatelyDataLoadEventListener.Quiet, null); } @@ -1661,7 +1662,7 @@ public void DataTableUploadClashSameRowWithTrigger() var dt1 = new DataTable(); dt1.Columns.Add("name", typeof(string)); dt1.Columns.Add("other", typeof(string)); - dt1.Rows.Add(new[] { "Fish", "Friend" }); + dt1.Rows.Add("Fish", "Friend"); dt1.PrimaryKey = new[] { dt1.Columns[0] }; dt1.TableName = "DataTableUploadDestinationTests"; try @@ -1671,9 +1672,9 @@ public void DataTableUploadClashSameRowWithTrigger() dt1 = new DataTable(); dt1.Columns.Add("name", typeof(string)); dt1.Columns.Add("other", typeof(string)); - dt1.Rows.Add(new[] { "Fish", "Friend" }); + dt1.Rows.Add("Fish", "Friend"); dt1.PrimaryKey = new[] { dt1.Columns[0] }; - dt1.TableName = "DataTableUploadDestinationTests"; ; + dt1.TableName = "DataTableUploadDestinationTests"; destination.ProcessPipelineData(dt1, toConsole, token); destination.Dispose(ThrowImmediatelyDataLoadEventListener.Quiet, null); } @@ -1707,7 +1708,7 @@ public void DataTableUploadClashUpdateNoTrigger() var dt1 = new DataTable(); dt1.Columns.Add("name", typeof(string)); dt1.Columns.Add("other", typeof(string)); - dt1.Rows.Add(new[] { "Fish", "Friend" }); + dt1.Rows.Add("Fish", "Friend"); dt1.PrimaryKey = new[] { dt1.Columns[0] }; dt1.TableName = "DataTableUploadDestinationTests"; try @@ -1723,7 +1724,7 @@ public void DataTableUploadClashUpdateNoTrigger() dt1 = new DataTable(); dt1.Columns.Add("name", typeof(string)); dt1.Columns.Add("other", typeof(string)); - dt1.Rows.Add(new[] { "Fish", "Enemy" }); + dt1.Rows.Add("Fish", "Enemy"); dt1.PrimaryKey = new[] { dt1.Columns[0] }; dt1.TableName = "DataTableUploadDestinationTests"; destination = new DataTableUploadDestination @@ -1763,7 +1764,7 @@ public void DataTableUploadClashUpdateWithTrigger() var dt1 = new DataTable(); dt1.Columns.Add("name", typeof(string)); dt1.Columns.Add("other", typeof(string)); - dt1.Rows.Add(new[] { "Fish", "Friend" }); + dt1.Rows.Add("Fish", "Friend"); dt1.PrimaryKey = new[] { dt1.Columns[0] }; dt1.TableName = "DataTableUploadDestinationTests"; try @@ -1773,9 +1774,9 @@ public void DataTableUploadClashUpdateWithTrigger() dt1 = new DataTable(); dt1.Columns.Add("name", typeof(string)); dt1.Columns.Add("other", typeof(string)); - dt1.Rows.Add(new[] { "Fish", "Enemy" }); + dt1.Rows.Add("Fish", "Enemy"); dt1.PrimaryKey = new[] { dt1.Columns[0] }; - dt1.TableName = "DataTableUploadDestinationTests"; ; + dt1.TableName = "DataTableUploadDestinationTests"; destination.ProcessPipelineData(dt1, toConsole, token); destination.Dispose(ThrowImmediatelyDataLoadEventListener.Quiet, null); } @@ -1818,7 +1819,7 @@ public void DataTableUploadClashUpdateDropColumnWithTrigger() var dt1 = new DataTable(); dt1.Columns.Add("name", typeof(string)); dt1.Columns.Add("other", typeof(string)); - dt1.Rows.Add(new[] { "Fish", "Friend" }); + dt1.Rows.Add("Fish", "Friend"); dt1.PrimaryKey = new[] { dt1.Columns[0] }; dt1.TableName = "DataTableUploadDestinationTests"; try @@ -1828,9 +1829,9 @@ public void DataTableUploadClashUpdateDropColumnWithTrigger() dt1 = new DataTable(); dt1.Columns.Add("name", typeof(string)); dt1.Columns.Add("other", typeof(string)); - dt1.Rows.Add(new[] { "Fish" }); + dt1.Rows.Add("Fish"); dt1.PrimaryKey = new[] { dt1.Columns[0] }; - dt1.TableName = "DataTableUploadDestinationTests"; ; + dt1.TableName = "DataTableUploadDestinationTests"; destination.ProcessPipelineData(dt1, toConsole, token); destination.Dispose(ThrowImmediatelyDataLoadEventListener.Quiet, null); } diff --git a/Rdmp.Core.Tests/DataLoad/Engine/Integration/DilutionTests/DilutionOperationTests.cs b/Rdmp.Core.Tests/DataLoad/Engine/Integration/DilutionTests/DilutionOperationTests.cs index 9e6ef3f2a2..74a0f21a47 100644 --- a/Rdmp.Core.Tests/DataLoad/Engine/Integration/DilutionTests/DilutionOperationTests.cs +++ b/Rdmp.Core.Tests/DataLoad/Engine/Integration/DilutionTests/DilutionOperationTests.cs @@ -175,12 +175,12 @@ public void Dilution_WithNamer_Test() { var db = GetCleanedServer(DatabaseType.MicrosoftSQLServer); - var dt = new DataTable(); + using var dt = new DataTable(); dt.Columns.Add("Bob"); - dt.Rows.Add(new[] { "Fish" }); + dt.Rows.Add("Fish"); var tbl = db.CreateTable("DilutionNamerTest", dt); - Import(tbl, out var ti, out var cols); + Import(tbl, out var ti, out _); tbl.Rename("AAAA"); var namer = RdmpMockFactory.Mock_INameDatabasesAndTablesDuringLoads(db, "AAAA"); diff --git a/Rdmp.Core.Tests/DataLoad/Engine/Integration/DistincterTests.cs b/Rdmp.Core.Tests/DataLoad/Engine/Integration/DistincterTests.cs index 4efd943765..1d132a40fb 100644 --- a/Rdmp.Core.Tests/DataLoad/Engine/Integration/DistincterTests.cs +++ b/Rdmp.Core.Tests/DataLoad/Engine/Integration/DistincterTests.cs @@ -47,8 +47,8 @@ public void TestDistincter_Duplicates(DatabaseType type) { var randInt = r.Next(int.MaxValue); - dt.Rows.Add(new object[] { randInt, randInt, randInt, randInt, randInt }); - dt.Rows.Add(new object[] { randInt, randInt, randInt, randInt, randInt }); + dt.Rows.Add(randInt, randInt, randInt, randInt, randInt); + dt.Rows.Add(randInt, randInt, randInt, randInt, randInt); } dt.EndLoadData(); @@ -106,8 +106,8 @@ public void TestDistincter_NoDuplicates(DatabaseType type) { var randInt = r.Next(int.MaxValue); - dt.Rows.Add(new object[] { randInt, randInt, randInt, randInt, randInt }); - dt.Rows.Add(new object[] { randInt, randInt, randInt, randInt, randInt + 1 }); + dt.Rows.Add(randInt, randInt, randInt, randInt, randInt); + dt.Rows.Add(randInt, randInt, randInt, randInt, randInt + 1); } dt.EndLoadData(); diff --git a/Rdmp.Core.Tests/DataLoad/Engine/Integration/ExecuteSqlFileRuntimeTaskTests.cs b/Rdmp.Core.Tests/DataLoad/Engine/Integration/ExecuteSqlFileRuntimeTaskTests.cs index 35c01cd343..225c993204 100644 --- a/Rdmp.Core.Tests/DataLoad/Engine/Integration/ExecuteSqlFileRuntimeTaskTests.cs +++ b/Rdmp.Core.Tests/DataLoad/Engine/Integration/ExecuteSqlFileRuntimeTaskTests.cs @@ -35,7 +35,7 @@ public void ExecuteSqlFileRuntimeTask_BasicScript(DatabaseType dbType) { var dt = new DataTable(); dt.Columns.Add("Lawl"); - dt.Rows.Add(new object[] { 2 }); + dt.Rows.Add(2); var db = GetCleanedServer(dbType); @@ -71,7 +71,7 @@ public void ExecuteSqlFileRuntimeTask_InvalidID(DatabaseType dbType) { var dt = new DataTable(); dt.Columns.Add("Lawl"); - dt.Rows.Add(new object[] { 2 }); + dt.Rows.Add(2); var db = GetCleanedServer(dbType); @@ -114,7 +114,7 @@ public void ExecuteSqlRuntimeTask_InvalidID(DatabaseType dbType) { var dt = new DataTable(); dt.Columns.Add("Lawl"); - dt.Rows.Add(new object[] { 2 }); + dt.Rows.Add(2); var db = GetCleanedServer(dbType); @@ -122,7 +122,7 @@ public void ExecuteSqlRuntimeTask_InvalidID(DatabaseType dbType) Import(tbl, out var ti, out var cols); - var sql = @"UPDATE {T:0} Set {C:0} = 1"; + const string sql = @"UPDATE {T:0} Set {C:0} = 1"; var dir = LoadDirectory.CreateDirectoryStructure(new DirectoryInfo(TestContext.CurrentContext.TestDirectory), "ExecuteSqlFileRuntimeTaskTests", true); @@ -169,13 +169,13 @@ public void ExecuteSqlFileRuntimeTask_ValidID_CustomNamer(DatabaseType dbType) { var dt = new DataTable(); dt.Columns.Add("Lawl"); - dt.Rows.Add(new object[] { 2 }); + dt.Rows.Add(2); var db = GetCleanedServer(dbType); var tbl = db.CreateTable("Fish", dt); - var tableName = "AAAAAAA"; + const string tableName = "AAAAAAA"; Import(tbl, out var ti, out var cols); diff --git a/Rdmp.Core.Tests/DataLoad/Engine/Integration/HICPipelineTests.cs b/Rdmp.Core.Tests/DataLoad/Engine/Integration/HICPipelineTests.cs index 8d3090f788..549f704856 100644 --- a/Rdmp.Core.Tests/DataLoad/Engine/Integration/HICPipelineTests.cs +++ b/Rdmp.Core.Tests/DataLoad/Engine/Integration/HICPipelineTests.cs @@ -162,7 +162,7 @@ public void SetUp(DiscoveredServer server) { _server = server; - var databaseToLoadName = "HICPipelineTests"; + const string databaseToLoadName = "HICPipelineTests"; // Create the databases server.ExpectDatabase(databaseToLoadName).Create(true); diff --git a/Rdmp.Core.Tests/DataLoad/Engine/Integration/KVPAttacherTest.cs b/Rdmp.Core.Tests/DataLoad/Engine/Integration/KVPAttacherTest.cs index 09c41eba34..08df14c42e 100644 --- a/Rdmp.Core.Tests/DataLoad/Engine/Integration/KVPAttacherTest.cs +++ b/Rdmp.Core.Tests/DataLoad/Engine/Integration/KVPAttacherTest.cs @@ -45,18 +45,22 @@ public void KVPAttacherTest_Attach(KVPAttacherTestCase testCase) var parentDir = workingDir.CreateSubdirectory("KVPAttacherTestProjectDirectory"); var projectDir = LoadDirectory.CreateDirectoryStructure(parentDir, "KVPAttacherTest", true); - var filepk = "kvpTestFilePK.csv"; - var filepk2 = "kvpTestFilePK2.csv"; - var fileNoPk = "kvpTestFile_NoPK.csv"; + const string filepk = "kvpTestFilePK.csv"; + const string filepk2 = "kvpTestFilePK2.csv"; + const string fileNoPk = "kvpTestFile_NoPK.csv"; if (testCase is KVPAttacherTestCase.OneFileWithPrimaryKey or KVPAttacherTestCase.TwoFilesWithPrimaryKey) CopyToBin(projectDir, filepk); - if (testCase == KVPAttacherTestCase.TwoFilesWithPrimaryKey) - CopyToBin(projectDir, filepk2); - - if (testCase == KVPAttacherTestCase.OneFileWithoutPrimaryKey) - CopyToBin(projectDir, fileNoPk); + switch (testCase) + { + case KVPAttacherTestCase.TwoFilesWithPrimaryKey: + CopyToBin(projectDir, filepk2); + break; + case KVPAttacherTestCase.OneFileWithoutPrimaryKey: + CopyToBin(projectDir, fileNoPk); + break; + } if (tbl.Exists()) tbl.Drop(); diff --git a/Rdmp.Core.Tests/DataLoad/Engine/Integration/PipelineTests/Components/AliasHandlerTests.cs b/Rdmp.Core.Tests/DataLoad/Engine/Integration/PipelineTests/Components/AliasHandlerTests.cs index 009bbb3a6c..26f034fd3e 100644 --- a/Rdmp.Core.Tests/DataLoad/Engine/Integration/PipelineTests/Components/AliasHandlerTests.cs +++ b/Rdmp.Core.Tests/DataLoad/Engine/Integration/PipelineTests/Components/AliasHandlerTests.cs @@ -72,7 +72,7 @@ public void ThrowBecause_ColumnNotInInputDataTable() { var dt = new DataTable(); dt.Columns.Add("cannonballer"); //not the same as the expected input column name - dt.Rows.Add(new object[] { "yes" }); + dt.Rows.Add("yes"); var ex = Assert.Throws(() => _handler.ProcessPipelineData(dt, ThrowImmediatelyDataLoadEventListener.Quiet, @@ -94,7 +94,7 @@ public void ThrowBecause_NameAndAliasSameValue() var dt = new DataTable(); dt.Columns.Add("input"); - dt.Rows.Add(new object[] { "candle" }); + dt.Rows.Add("candle"); var ex = Assert.Throws(() => _handler.ProcessPipelineData(dt, ThrowImmediatelyDataLoadEventListener.Quiet, @@ -116,8 +116,8 @@ public void ThrowBecause_ThreeColumnAliasTable() dt.Columns.Add("input"); dt.Columns.Add("value"); - dt.Rows.Add(new object[] { "dave", 100 }); - dt.Rows.Add(new object[] { "frank", 100 }); + dt.Rows.Add("dave", 100); + dt.Rows.Add("frank", 100); var ex = Assert.Throws(() => _handler.ProcessPipelineData(dt, ThrowImmediatelyDataLoadEventListener.Quiet, @@ -133,8 +133,8 @@ public void NoAliases() dt.Columns.Add("input"); dt.Columns.Add("value"); - dt.Rows.Add(new object[] { "dave", 100 }); - dt.Rows.Add(new object[] { "frank", 100 }); + dt.Rows.Add("dave", 100); + dt.Rows.Add("frank", 100); var result = _handler.ProcessPipelineData(dt, ThrowImmediatelyDataLoadEventListener.Quiet, new GracefulCancellationToken()); @@ -149,7 +149,7 @@ public void CrashStrategy() var dt = new DataTable(); dt.Columns.Add("input"); - dt.Rows.Add(new object[] { "paul" }); + dt.Rows.Add("paul"); Assert.Throws(() => _handler.ProcessPipelineData(dt, ThrowImmediatelyDataLoadEventListener.Quiet, new GracefulCancellationToken())); @@ -166,9 +166,9 @@ public void ResolveTwoNameAlias() dt.Columns.Add("input"); dt.Columns.Add("value2", typeof(int)); - dt.Rows.Add(new object[] { 99, "dave", 100 }); - dt.Rows.Add(new object[] { 199, "frank", 200 }); - dt.Rows.Add(new object[] { 299, "freddie", 300 }); //has a two name alias + dt.Rows.Add(99, "dave", 100); + dt.Rows.Add(199, "frank", 200); + dt.Rows.Add(299, "freddie", 300); //has a two name alias var result = _handler.ProcessPipelineData(dt, ThrowImmediatelyDataLoadEventListener.Quiet, new GracefulCancellationToken()); @@ -197,9 +197,9 @@ public void ResolveThreeNameAlias() dt.Columns.Add("input"); dt.Columns.Add("value2", typeof(int)); - dt.Rows.Add(new object[] { 99, "pepey", 100 }); //has a three name alias - dt.Rows.Add(new object[] { 199, "frank", 200 }); - dt.Rows.Add(new object[] { 299, "anderson", 300 }); + dt.Rows.Add(99, "pepey", 100); //has a three name alias + dt.Rows.Add(199, "frank", 200); + dt.Rows.Add(299, "anderson", 300); var result = _handler.ProcessPipelineData(dt, ThrowImmediatelyDataLoadEventListener.Quiet, new GracefulCancellationToken()); diff --git a/Rdmp.Core.Tests/DataLoad/Engine/Integration/TestTemporalTables.cs b/Rdmp.Core.Tests/DataLoad/Engine/Integration/TestTemporalTables.cs index 1b24eb5da8..f891f32679 100644 --- a/Rdmp.Core.Tests/DataLoad/Engine/Integration/TestTemporalTables.cs +++ b/Rdmp.Core.Tests/DataLoad/Engine/Integration/TestTemporalTables.cs @@ -7,8 +7,8 @@ using System.Data; using System.IO; using System.Linq; +using FAnsi; using NUnit.Framework; -using Rdmp.Core.CommandExecution; using Rdmp.Core.Curation.Data; using Rdmp.Core.Curation.Data.DataLoad; using Rdmp.Core.Curation.Data.Defaults; @@ -48,7 +48,7 @@ INSERT INTO Employee(EmployeeID,Name,Position,Department,Address,AnnualSalary) V [TestCase(false)] public void TestTemporalTable(bool ignoreWithGlobalPattern) { - var dbtype = FAnsi.DatabaseType.MicrosoftSQLServer; + const DatabaseType dbtype = FAnsi.DatabaseType.MicrosoftSQLServer; var db = GetCleanedServer(dbtype); using (var con = db.Server.GetConnection()) diff --git a/Rdmp.Core.Tests/DataLoad/Engine/Unit/ExcelTests.cs b/Rdmp.Core.Tests/DataLoad/Engine/Unit/ExcelTests.cs index 5a97877254..83ddcaa3bc 100644 --- a/Rdmp.Core.Tests/DataLoad/Engine/Unit/ExcelTests.cs +++ b/Rdmp.Core.Tests/DataLoad/Engine/Unit/ExcelTests.cs @@ -352,12 +352,14 @@ public void TestToCSVConverter(bool prefixWithWorkbookName) var contents = File.ReadAllText(file.FullName); Assert.That( -contents.Trim(new[] { ',', '\r', '\n', ' ', '\t' }), Is.EqualTo(@"Participant,Score,IsEvil,DateField,DoubleField,MixedField -Bob,3,yes,2001-01-01,0.1,10:30:00 -Frank,1.1,no,2001-01-01 10:30:00,0.51,11:30:00 -Hank,2.1,no,2002-01-01 11:30:00,0.22,0.1 -Shanker,2,yes,2003-01-01 01:30:00,0.10,0.51 -Bobboy,2,maybe,2015-09-18,15:09:00,00:03:56")); + contents.Trim(',', '\r', '\n', ' ', '\t'), Is.EqualTo(""" + Participant,Score,IsEvil,DateField,DoubleField,MixedField + Bob,3,yes,2001-01-01,0.1,10:30:00 + Frank,1.1,no,2001-01-01 10:30:00,0.51,11:30:00 + Hank,2.1,no,2002-01-01 11:30:00,0.22,0.1 + Shanker,2,yes,2003-01-01 01:30:00,0.10,0.51 + Bobboy,2,maybe,2015-09-18,15:09:00,00:03:56 + """)); file.Delete(); } diff --git a/Rdmp.Core.Tests/DataLoad/Engine/Unit/MDFAttacherTests.cs b/Rdmp.Core.Tests/DataLoad/Engine/Unit/MDFAttacherTests.cs index 89abadb449..3a256be73b 100644 --- a/Rdmp.Core.Tests/DataLoad/Engine/Unit/MDFAttacherTests.cs +++ b/Rdmp.Core.Tests/DataLoad/Engine/Unit/MDFAttacherTests.cs @@ -124,7 +124,7 @@ public void TestLocations_NoNetworkPath() File.WriteAllText(mdf, "fish"); File.WriteAllText(ldf, "fish"); - var serverDatabasePath = @"H:/Program Files/Microsoft SQL Server/MSSQL13.SQLEXPRESS/MSSQL/DATA/"; + const string serverDatabasePath = @"H:/Program Files/Microsoft SQL Server/MSSQL13.SQLEXPRESS/MSSQL/DATA/"; var locations = new MdfFileAttachLocations(new DirectoryInfo(TestContext.CurrentContext.TestDirectory), serverDatabasePath, null); @@ -234,7 +234,7 @@ public void TestLocations_NetworkPath() File.WriteAllText(mdf, "fish"); File.WriteAllText(ldf, "fish"); - var serverDatabasePath = @"H:/Program Files/Microsoft SQL Server/MSSQL13.SQLEXPRESS/MSSQL/DATA/"; + const string serverDatabasePath = @"H:/Program Files/Microsoft SQL Server/MSSQL13.SQLEXPRESS/MSSQL/DATA/"; var locations = new MdfFileAttachLocations(new DirectoryInfo(TestContext.CurrentContext.TestDirectory), serverDatabasePath, @"//MyDbServer1/Share/Database"); diff --git a/Rdmp.Core.Tests/DataLoad/Modules/Attachers/AttacherMEFTest.cs b/Rdmp.Core.Tests/DataLoad/Modules/Attachers/AttacherMEFTest.cs index c85967c52c..0a1b0d17c4 100644 --- a/Rdmp.Core.Tests/DataLoad/Modules/Attachers/AttacherMEFTest.cs +++ b/Rdmp.Core.Tests/DataLoad/Modules/Attachers/AttacherMEFTest.cs @@ -1,13 +1,9 @@ -using NPOI.SS.Formula.Functions; -using NUnit.Framework; +using NUnit.Framework; using Rdmp.Core.DataLoad.Engine.Attachers; using Rdmp.Core.DataLoad.Modules.Attachers; using Rdmp.Core.Repositories; -using System; using System.Collections.Generic; using System.Linq; -using System.Text; -using System.Threading.Tasks; using Tests.Common; namespace Rdmp.Core.Tests.DataLoad.Modules.Attachers diff --git a/Rdmp.Core.Tests/DataLoad/Modules/Mutilators/RegexRedactionMutilatorTests.cs b/Rdmp.Core.Tests/DataLoad/Modules/Mutilators/RegexRedactionMutilatorTests.cs index 13a90ed15b..c17e8bde83 100644 --- a/Rdmp.Core.Tests/DataLoad/Modules/Mutilators/RegexRedactionMutilatorTests.cs +++ b/Rdmp.Core.Tests/DataLoad/Modules/Mutilators/RegexRedactionMutilatorTests.cs @@ -38,7 +38,7 @@ public void RedactionMutilator_BasicTest() if (raw.Exists()) raw.Drop(); - var dleStaging = db.Server.ExpectDatabase($"DLE_STAGING"); + var dleStaging = db.Server.ExpectDatabase("DLE_STAGING"); if (!dleStaging.Exists()) db.Server.CreateDatabase("DLE_STAGING"); @@ -145,7 +145,7 @@ public void RedactionMutilator_OddStringLength() if (raw.Exists()) raw.Drop(); - var dleStaging = db.Server.ExpectDatabase($"DLE_STAGING"); + var dleStaging = db.Server.ExpectDatabase("DLE_STAGING"); if (!dleStaging.Exists()) db.Server.CreateDatabase("DLE_STAGING"); @@ -252,7 +252,7 @@ public void RedactionMutilator_RedactionTooLong() if (raw.Exists()) raw.Drop(); - var dleStaging = db.Server.ExpectDatabase($"DLE_STAGING"); + var dleStaging = db.Server.ExpectDatabase("DLE_STAGING"); if (!dleStaging.Exists()) db.Server.CreateDatabase("DLE_STAGING"); @@ -347,7 +347,7 @@ public void RedactionMutilator_RedactAPK() if (raw.Exists()) raw.Drop(); - var dleStaging = db.Server.ExpectDatabase($"DLE_STAGING"); + var dleStaging = db.Server.ExpectDatabase("DLE_STAGING"); if (!dleStaging.Exists()) db.Server.CreateDatabase("DLE_STAGING"); @@ -442,7 +442,7 @@ public void RedactionMutilator_NoPKS() if (raw.Exists()) raw.Drop(); - var dleStaging = db.Server.ExpectDatabase($"DLE_STAGING"); + var dleStaging = db.Server.ExpectDatabase("DLE_STAGING"); if (!dleStaging.Exists()) db.Server.CreateDatabase("DLE_STAGING"); @@ -537,7 +537,7 @@ public void RedactionMutilator_MultipleInOneCell() if (raw.Exists()) raw.Drop(); - var dleStaging = db.Server.ExpectDatabase($"DLE_STAGING"); + var dleStaging = db.Server.ExpectDatabase("DLE_STAGING"); if (!dleStaging.Exists()) db.Server.CreateDatabase("DLE_STAGING"); @@ -648,7 +648,7 @@ public void RedactionMutilator_SpeedTest() if (raw.Exists()) raw.Drop(); - var dleStaging = db.Server.ExpectDatabase($"DLE_STAGING"); + var dleStaging = db.Server.ExpectDatabase("DLE_STAGING"); if (!dleStaging.Exists()) db.Server.CreateDatabase("DLE_STAGING"); @@ -702,9 +702,11 @@ public void RedactionMutilator_SpeedTest() File.WriteAllText( Path.Combine(projectDirectory.ForLoading.FullName, "LoadMe.csv"), - @$"Name,DateOfBirth,FavouriteColour -MrMurder,2001-01-01,Yella -"); + """ + Name,DateOfBirth,FavouriteColour + MrMurder,2001-01-01,Yella + + """); var data = Enumerable.Repeat("name,2001-01-01,amber", 1000000).ToArray(); diff --git a/Rdmp.Core.Tests/DataQualityEngine/CatalogueConstraintReportTests.cs b/Rdmp.Core.Tests/DataQualityEngine/CatalogueConstraintReportTests.cs index f36d3b233a..ca6836a4e0 100644 --- a/Rdmp.Core.Tests/DataQualityEngine/CatalogueConstraintReportTests.cs +++ b/Rdmp.Core.Tests/DataQualityEngine/CatalogueConstraintReportTests.cs @@ -40,7 +40,7 @@ private DQERepository GetDqeRepository(DatabaseType dbType) [TestCaseSource(typeof(All), nameof(All.DatabaseTypesWithBoolFlags))] public void ValidateBulkTestData(DatabaseType dbType, bool testCancellingValidationEarly) { - var numberOfRecordsToGenerate = 10000; + const int numberOfRecordsToGenerate = 10000; var startTime = DateTime.Now; var testData = new BulkTestsData(CatalogueRepository, GetCleanedServer(DatabaseType.MicrosoftSQLServer), diff --git a/Rdmp.Core.Tests/Logging/FatalErrorLoggingTest.cs b/Rdmp.Core.Tests/Logging/FatalErrorLoggingTest.cs index 23e402abb4..e6a8a961d7 100644 --- a/Rdmp.Core.Tests/Logging/FatalErrorLoggingTest.cs +++ b/Rdmp.Core.Tests/Logging/FatalErrorLoggingTest.cs @@ -56,7 +56,7 @@ public void FataErrorLoggingTest() [Test] public void MD5Test() { - var fileContents = "TestStringThatCouldBeSomethingInAFile"; + const string fileContents = "TestStringThatCouldBeSomethingInAFile"; byte[] hashAsBytes; using var memory = new MemoryStream(); diff --git a/Rdmp.Core.Tests/QueryCaching/CachedAggregateConfigurationResultsManagerTests.cs b/Rdmp.Core.Tests/QueryCaching/CachedAggregateConfigurationResultsManagerTests.cs index 0b8f45cca7..4562d9e8a9 100644 --- a/Rdmp.Core.Tests/QueryCaching/CachedAggregateConfigurationResultsManagerTests.cs +++ b/Rdmp.Core.Tests/QueryCaching/CachedAggregateConfigurationResultsManagerTests.cs @@ -126,12 +126,14 @@ public void Throws_BecauseInceptionCaching() //If this unit test suddenly starts failing you might have changed the value of CachedAggregateConfigurationResultsManager.CachingPrefix (see sql variable below and make it match the const - the unit test is divorced because why would you want to change that eh!, 'Cached:' is very clear) //this is a cache fetch request that we are trying to inception recache - var sql = @"/*Cached:cic_65_People in DMPTestCatalogue*/ - select * from [cache]..[IndexedExtractionIdentifierList_AggregateConfiguration217]"; + const string sql = """ + /*Cached:cic_65_People in DMPTestCatalogue*/ + select * from [cache]..[IndexedExtractionIdentifierList_AggregateConfiguration217] + """; var ex = Assert.Throws(() => _manager.CommitResults(new CacheCommitIdentifierList(_config, sql, dt, _myColSpecification, 30))); - Assert.That(ex.Message, Does.Contain("This is referred to as Inception Caching and isn't allowed")); + Assert.That(ex?.Message, Does.Contain("This is referred to as Inception Caching and isn't allowed")); } [Test] diff --git a/Rdmp.Core.Tests/Reports/CustomMetadataReportTests.cs b/Rdmp.Core.Tests/Reports/CustomMetadataReportTests.cs index bf2a9a163a..0565beda81 100644 --- a/Rdmp.Core.Tests/Reports/CustomMetadataReportTests.cs +++ b/Rdmp.Core.Tests/Reports/CustomMetadataReportTests.cs @@ -1201,9 +1201,11 @@ some more text [Test] public void Test_CustomMetadataElementSeperator_ThrowsWhenNotInForEach() { - var templateCode = @" -$Name -$Comma"; + const string templateCode = """ + + $Name + $Comma + """; Setup2Catalogues(out var c1, out var c2); var template = new FileInfo(Path.Combine(TestContext.CurrentContext.WorkDirectory, "template.md")); @@ -1226,20 +1228,22 @@ public void Test_CustomMetadataElementSeperator_ThrowsWhenNotInForEach() [Test] public void Test_CustomMetadataElementSeperator_JsonExample() { - var templateCode = @"[ -$foreach Catalogue - { - ""Name"": ""$Name"", - ""Columns"": [ -$foreach CatalogueItem - { - ""Name"": ""$Name"" - }$Comma -$end - ] - }$Comma -$end -]"; + const string templateCode = """ + [ + $foreach Catalogue + { + "Name": "$Name", + "Columns": [ + $foreach CatalogueItem + { + "Name": "$Name" + }$Comma + $end + ] + }$Comma + $end + ] + """; Setup2Catalogues(out var c1, out var c2); @@ -1294,20 +1298,22 @@ public void Test_CustomMetadataElementSeperator_JsonExample() [Test] public void Test_CustomMetadataElementSeperator_JsonExample_SemicolonSub() { - var templateCode = @"[ -$foreach Catalogue - { - ""Name"": ""$Name"", - ""Columns"": [ -$foreach CatalogueItem - { - ""Name"": ""$Name"" - }$Comma -$end - ] - }$Comma -$end -]"; + const string templateCode = """ + [ + $foreach Catalogue + { + "Name": "$Name", + "Columns": [ + $foreach CatalogueItem + { + "Name": "$Name" + }$Comma + $end + ] + }$Comma + $end + ] + """; Setup2Catalogues(out var c1, out var c2); @@ -1362,65 +1368,66 @@ public void Test_CustomMetadataElementSeperator_JsonExample_SemicolonSub() [Test] public void TestAllSubs_Catalogue() { - var templateCode = - @"$API_access_URL -$Access_options -$Administrative_contact_address -$Administrative_contact_email -$Administrative_contact_name -$Administrative_contact_telephone -$Attribution_citation -$Background_summary -$Browse_URL -$Bulk_Download_URL -$Contact_details -$Country_of_origin -$Data_standards -$DatasetStartDate -$Description -$Detail_Page_URL -$Ethics_approver -$Explicit_consent -$Geographical_coverage -$Granularity -$ID -$IsColdStorageDataset -$IsDeprecated -$IsInternalDataset -$Last_revision_date -$LoggingDataTask -$Name -$Periodicity -$PivotCategory_ExtractionInformation_ID -$Query_tool_URL -$Resource_owner -$Search_keywords -$Source_URL -$Source_of_data_collection -$SubjectNumbers -$Ticket -$Time_coverage -$Type -$Update_freq -$Update_sched -$Database -$DatabaseType -$IsPrimaryExtractionTable -$IsTableValuedFunction -$IsView -$Schema -$Server -$DQE_CountTotal -$DQE_DateOfEvaluation -$DQE_DateRange -$DQE_EndDate -$DQE_EndDay -$DQE_EndMonth -$DQE_EndYear -$DQE_StartDate -$DQE_StartDay -$DQE_StartMonth -$DQE_StartYear"; + const string templateCode = """ + $API_access_URL + $Access_options + $Administrative_contact_address + $Administrative_contact_email + $Administrative_contact_name + $Administrative_contact_telephone + $Attribution_citation + $Background_summary + $Browse_URL + $Bulk_Download_URL + $Contact_details + $Country_of_origin + $Data_standards + $DatasetStartDate + $Description + $Detail_Page_URL + $Ethics_approver + $Explicit_consent + $Geographical_coverage + $Granularity + $ID + $IsColdStorageDataset + $IsDeprecated + $IsInternalDataset + $Last_revision_date + $LoggingDataTask + $Name + $Periodicity + $PivotCategory_ExtractionInformation_ID + $Query_tool_URL + $Resource_owner + $Search_keywords + $Source_URL + $Source_of_data_collection + $SubjectNumbers + $Ticket + $Time_coverage + $Type + $Update_freq + $Update_sched + $Database + $DatabaseType + $IsPrimaryExtractionTable + $IsTableValuedFunction + $IsView + $Schema + $Server + $DQE_CountTotal + $DQE_DateOfEvaluation + $DQE_DateRange + $DQE_EndDate + $DQE_EndDay + $DQE_EndMonth + $DQE_EndYear + $DQE_StartDate + $DQE_StartDay + $DQE_StartMonth + $DQE_StartYear + """; Setup2Catalogues(out var c1, out var c2); @@ -1454,36 +1461,37 @@ public void TestAllSubs_Catalogue() [Test] public void TestAllSubs_CatalogueItem() { - var templateCode = - @" -$foreach CatalogueItem -$Agg_method -$Comments -$Description -$ID -$Limitations -$Name -$Periodicity -$Research_relevance -$Statistical_cons -$Topic -$Collation -$Data_type -$Digitisation_specs -$Format -$IgnoreInLoads -$IsAutoIncrement -$IsPrimaryKey -$Source -$Status -$DQE_CountCorrect -$DQE_CountDBNull -$DQE_CountInvalidatesRow -$DQE_CountMissing -$DQE_CountTotal -$DQE_CountWrong -$DQE_PercentNull -$end"; + const string templateCode = """ + + $foreach CatalogueItem + $Agg_method + $Comments + $Description + $ID + $Limitations + $Name + $Periodicity + $Research_relevance + $Statistical_cons + $Topic + $Collation + $Data_type + $Digitisation_specs + $Format + $IgnoreInLoads + $IsAutoIncrement + $IsPrimaryKey + $Source + $Status + $DQE_CountCorrect + $DQE_CountDBNull + $DQE_CountInvalidatesRow + $DQE_CountMissing + $DQE_CountTotal + $DQE_CountWrong + $DQE_PercentNull + $end + """; Setup2Catalogues(out var c1, out var c2); diff --git a/Rdmp.Core.Tests/ReusableCodeTests/ExpectedIdenticalStringsExceptionTests.cs b/Rdmp.Core.Tests/ReusableCodeTests/ExpectedIdenticalStringsExceptionTests.cs index a12f894d9b..18c8ab1bbd 100644 --- a/Rdmp.Core.Tests/ReusableCodeTests/ExpectedIdenticalStringsExceptionTests.cs +++ b/Rdmp.Core.Tests/ReusableCodeTests/ExpectedIdenticalStringsExceptionTests.cs @@ -104,12 +104,12 @@ public void VeryLongStringsWithWhitespace() my uncle, in his latter years become credulous of the most superficial impostures? ".Replace("\r", "")); // .Replace above forces Unix-style strings for test consistency - Assert.That(ex.Message, Is.EqualTo($""" - These are different - Strings differ at index 34 - EXPECTED:d be the\nmeaning \nof the que... - ACTUAL :d be the\nmeaning \nif the que... - -----------------------------^ - """)); + Assert.That(ex.Message, Is.EqualTo(""" + These are different + Strings differ at index 34 + EXPECTED:d be the\nmeaning \nof the que... + ACTUAL :d be the\nmeaning \nif the que... + -----------------------------^ + """)); } } \ No newline at end of file diff --git a/Rdmp.Core.Tests/Validation/Constraints/Primary/ValidationTests.cs b/Rdmp.Core.Tests/Validation/Constraints/Primary/ValidationTests.cs index bea8b8a4a8..f1ef85552b 100644 --- a/Rdmp.Core.Tests/Validation/Constraints/Primary/ValidationTests.cs +++ b/Rdmp.Core.Tests/Validation/Constraints/Primary/ValidationTests.cs @@ -8,6 +8,4 @@ namespace Rdmp.Core.Tests.Validation.Constraints.Primary; -internal class ValidationTests : UnitTests -{ -} \ No newline at end of file +internal class ValidationTests : UnitTests; \ No newline at end of file diff --git a/Rdmp.Core/Caching/Pipeline/Sources/ICacheSource.cs b/Rdmp.Core/Caching/Pipeline/Sources/ICacheSource.cs index cc64accbde..68872eac33 100644 --- a/Rdmp.Core/Caching/Pipeline/Sources/ICacheSource.cs +++ b/Rdmp.Core/Caching/Pipeline/Sources/ICacheSource.cs @@ -16,6 +16,4 @@ namespace Rdmp.Core.Caching.Pipeline.Sources; /// attempt to cache data between 9am and 5pm at night) /// public interface ICacheSource : IPipelineRequirement, - IPipelineRequirement -{ -} \ No newline at end of file + IPipelineRequirement; \ No newline at end of file diff --git a/Rdmp.Core/CohortCommitting/Pipeline/ICohortHoldoutLookupRequest.cs b/Rdmp.Core/CohortCommitting/Pipeline/ICohortHoldoutLookupRequest.cs index f3231b14d7..e3d12573f4 100644 --- a/Rdmp.Core/CohortCommitting/Pipeline/ICohortHoldoutLookupRequest.cs +++ b/Rdmp.Core/CohortCommitting/Pipeline/ICohortHoldoutLookupRequest.cs @@ -12,8 +12,5 @@ namespace Rdmp.Core.CohortCommitting.Pipeline; /// /// See CohortHoldoutLookupRequest /// -public interface ICohortHoldoutLookupRequest : ICheckable, IPipelineUseCase -{ - -} +public interface ICohortHoldoutLookupRequest : ICheckable, IPipelineUseCase; diff --git a/Rdmp.Core/CohortCommitting/Pipeline/ICohortPipelineDestination.cs b/Rdmp.Core/CohortCommitting/Pipeline/ICohortPipelineDestination.cs index 79b66722e6..ffb6574745 100644 --- a/Rdmp.Core/CohortCommitting/Pipeline/ICohortPipelineDestination.cs +++ b/Rdmp.Core/CohortCommitting/Pipeline/ICohortPipelineDestination.cs @@ -15,6 +15,4 @@ namespace Rdmp.Core.CohortCommitting.Pipeline; /// identifiers supplied in the DataTable. /// public interface ICohortPipelineDestination : IDataFlowDestination, - IPipelineRequirement -{ -} \ No newline at end of file + IPipelineRequirement; \ No newline at end of file diff --git a/Rdmp.Core/CohortCommitting/Pipeline/IPluginCohortDestination.cs b/Rdmp.Core/CohortCommitting/Pipeline/IPluginCohortDestination.cs index 2b546a2f89..ecc10e9a6b 100644 --- a/Rdmp.Core/CohortCommitting/Pipeline/IPluginCohortDestination.cs +++ b/Rdmp.Core/CohortCommitting/Pipeline/IPluginCohortDestination.cs @@ -13,6 +13,4 @@ namespace Rdmp.Core.CohortCommitting.Pipeline; /// MEF discoverble version of ICohortPipelineDestination (See ICohortPipelineDestination). Implement this interface if you are writing a custom cohort /// storage system and need to populate it with identifiers through the RDMP Cohort Creation Pipeline Processes. /// -public interface IPluginCohortDestination : ICohortPipelineDestination, IPluginDataFlowComponent -{ -} \ No newline at end of file +public interface IPluginCohortDestination : ICohortPipelineDestination, IPluginDataFlowComponent; \ No newline at end of file diff --git a/Rdmp.Core/CohortCommitting/Pipeline/Sources/PatientIdentifierColumnSource.cs b/Rdmp.Core/CohortCommitting/Pipeline/Sources/PatientIdentifierColumnSource.cs index d8a814d305..b78dec7a2a 100644 --- a/Rdmp.Core/CohortCommitting/Pipeline/Sources/PatientIdentifierColumnSource.cs +++ b/Rdmp.Core/CohortCommitting/Pipeline/Sources/PatientIdentifierColumnSource.cs @@ -65,7 +65,7 @@ private DataTable GetDataTable(int timeout, int? topX) using var r = cmd.ExecuteReader(); while (r.Read()) - dt.Rows.Add(new[] { r[colName] }); + dt.Rows.Add(r[colName]); dt.EndLoadData(); return dt; diff --git a/Rdmp.Core/CommandExecution/AtomicCommands/Alter/AlterTableCommandExecution.cs b/Rdmp.Core/CommandExecution/AtomicCommands/Alter/AlterTableCommandExecution.cs index 07d814aac7..481f74c123 100644 --- a/Rdmp.Core/CommandExecution/AtomicCommands/Alter/AlterTableCommandExecution.cs +++ b/Rdmp.Core/CommandExecution/AtomicCommands/Alter/AlterTableCommandExecution.cs @@ -44,7 +44,6 @@ protected AlterTableCommandExecution(IBasicActivateItems activator, ITableInfo t if (Table.TableType != TableType.Table) { SetImpossible($"Table is a {Table.TableType}"); - return; } } diff --git a/Rdmp.Core/CommandExecution/AtomicCommands/CohortCreationCommands/ExecuteCommandCreateNewCohortByExecutingACohortIdentificationConfiguration.cs b/Rdmp.Core/CommandExecution/AtomicCommands/CohortCreationCommands/ExecuteCommandCreateNewCohortByExecutingACohortIdentificationConfiguration.cs index 7a15a2ab2b..39dba10eb1 100644 --- a/Rdmp.Core/CommandExecution/AtomicCommands/CohortCreationCommands/ExecuteCommandCreateNewCohortByExecutingACohortIdentificationConfiguration.cs +++ b/Rdmp.Core/CommandExecution/AtomicCommands/CohortCreationCommands/ExecuteCommandCreateNewCohortByExecutingACohortIdentificationConfiguration.cs @@ -14,7 +14,6 @@ using Rdmp.Core.Providers; using Rdmp.Core.Repositories.Construction; using Rdmp.Core.ReusableLibraryCode.Icons.IconProvision; -using Rdmp.Core.Setting; using SixLabors.ImageSharp; using SixLabors.ImageSharp.PixelFormats; diff --git a/Rdmp.Core/CommandExecution/AtomicCommands/ExecuteCommandAddCohortToExtractionConfiguration.cs b/Rdmp.Core/CommandExecution/AtomicCommands/ExecuteCommandAddCohortToExtractionConfiguration.cs index 7b1fc69523..30b09ff0a9 100644 --- a/Rdmp.Core/CommandExecution/AtomicCommands/ExecuteCommandAddCohortToExtractionConfiguration.cs +++ b/Rdmp.Core/CommandExecution/AtomicCommands/ExecuteCommandAddCohortToExtractionConfiguration.cs @@ -61,7 +61,6 @@ public ExecuteCommandAddCohortToExtractionConfiguration(IBasicActivateItems acti SetImpossible(_targetExtractionConfiguration.Cohort_ID == sourceExtractableCohortComand.Cohort.ID ? "ExtractionConfiguration already uses this cohort" : "ExtractionConfiguration already uses a different cohort (delete the relationship to the old cohort first)"); - return; } } diff --git a/Rdmp.Core/CommandExecution/AtomicCommands/ExecuteCommandAddExtractionProgress.cs b/Rdmp.Core/CommandExecution/AtomicCommands/ExecuteCommandAddExtractionProgress.cs index e2c41c2c5d..cb06615b5f 100644 --- a/Rdmp.Core/CommandExecution/AtomicCommands/ExecuteCommandAddExtractionProgress.cs +++ b/Rdmp.Core/CommandExecution/AtomicCommands/ExecuteCommandAddExtractionProgress.cs @@ -32,7 +32,6 @@ public ExecuteCommandAddExtractionProgress(IBasicActivateItems activator, ISelec if (_sds.GetCatalogue()?.TimeCoverage_ExtractionInformation_ID == null) { SetImpossible("Catalogue does not have a time coverage field configured"); - return; } } diff --git a/Rdmp.Core/CommandExecution/AtomicCommands/ExecuteCommandMakeProjectSpecificCatalogueNormalAgain.cs b/Rdmp.Core/CommandExecution/AtomicCommands/ExecuteCommandMakeProjectSpecificCatalogueNormalAgain.cs index 8a724eef0c..bb35adfe51 100644 --- a/Rdmp.Core/CommandExecution/AtomicCommands/ExecuteCommandMakeProjectSpecificCatalogueNormalAgain.cs +++ b/Rdmp.Core/CommandExecution/AtomicCommands/ExecuteCommandMakeProjectSpecificCatalogueNormalAgain.cs @@ -43,7 +43,6 @@ public ExecuteCommandMakeProjectSpecificCatalogueNormalAgain(IBasicActivateItems if (_extractableDataSet.Project_ID == null) { SetImpossible("Catalogue is not a project specific Catalogue"); - return; } } diff --git a/Rdmp.Core/CommandExecution/AtomicCommands/ExecuteCommandPerformRegexRedactionOnCatalogue.cs b/Rdmp.Core/CommandExecution/AtomicCommands/ExecuteCommandPerformRegexRedactionOnCatalogue.cs index b9c6abcaad..05a86e1e77 100644 --- a/Rdmp.Core/CommandExecution/AtomicCommands/ExecuteCommandPerformRegexRedactionOnCatalogue.cs +++ b/Rdmp.Core/CommandExecution/AtomicCommands/ExecuteCommandPerformRegexRedactionOnCatalogue.cs @@ -6,7 +6,6 @@ using FAnsi.Discovery; using FAnsi.Discovery.QuerySyntax; -using MongoDB.Driver; using Rdmp.Core.Curation.Data; using Rdmp.Core.Curation.DataHelper.RegexRedaction; using Rdmp.Core.QueryBuilding; @@ -16,7 +15,6 @@ using System.Collections.Generic; using System.Data; using System.Linq; -using static System.Linq.Enumerable; namespace Rdmp.Core.CommandExecution.AtomicCommands; diff --git a/Rdmp.Core/CommandExecution/AtomicCommands/ExecuteCommandRunSupportingSql.cs b/Rdmp.Core/CommandExecution/AtomicCommands/ExecuteCommandRunSupportingSql.cs index 9f955fcc08..d8dcdf41e1 100644 --- a/Rdmp.Core/CommandExecution/AtomicCommands/ExecuteCommandRunSupportingSql.cs +++ b/Rdmp.Core/CommandExecution/AtomicCommands/ExecuteCommandRunSupportingSql.cs @@ -36,7 +36,6 @@ public ExecuteCommandRunSupportingSql(IBasicActivateItems activator, if (string.IsNullOrWhiteSpace(SupportingSQLTable.SQL)) { SetImpossible($"No SQL is defined for {SupportingSQLTable}"); - return; } } diff --git a/Rdmp.Core/CommandExecution/AtomicCommands/ExecuteCommandSetAxis.cs b/Rdmp.Core/CommandExecution/AtomicCommands/ExecuteCommandSetAxis.cs index 0500d80cef..8bd1907443 100644 --- a/Rdmp.Core/CommandExecution/AtomicCommands/ExecuteCommandSetAxis.cs +++ b/Rdmp.Core/CommandExecution/AtomicCommands/ExecuteCommandSetAxis.cs @@ -64,7 +64,6 @@ public ExecuteCommandSetAxis(IBasicActivateItems basicActivator, AggregateConfig if (aggregate.GetAxisIfAny() != null) { SetImpossible($"AggregateConfiguration {aggregate} already has an axis"); - return; } } else diff --git a/Rdmp.Core/CommandExecution/AtomicCommands/ExecuteCommandSetPivot.cs b/Rdmp.Core/CommandExecution/AtomicCommands/ExecuteCommandSetPivot.cs index 7d6ee2d97a..9a1a0316b6 100644 --- a/Rdmp.Core/CommandExecution/AtomicCommands/ExecuteCommandSetPivot.cs +++ b/Rdmp.Core/CommandExecution/AtomicCommands/ExecuteCommandSetPivot.cs @@ -52,7 +52,6 @@ public ExecuteCommandSetPivot(IBasicActivateItems basicActivator, AggregateConfi { SetImpossible( $"AggregateConfiguration {aggregate} is a cohort identification aggregate and so cannot have a pivot"); - return; } } else diff --git a/Rdmp.Core/CommandExecution/AtomicCommands/ExecuteCommandUnMergeCohortIdentificationConfiguration.cs b/Rdmp.Core/CommandExecution/AtomicCommands/ExecuteCommandUnMergeCohortIdentificationConfiguration.cs index 93dc72208a..b1bc059b66 100644 --- a/Rdmp.Core/CommandExecution/AtomicCommands/ExecuteCommandUnMergeCohortIdentificationConfiguration.cs +++ b/Rdmp.Core/CommandExecution/AtomicCommands/ExecuteCommandUnMergeCohortIdentificationConfiguration.cs @@ -41,7 +41,7 @@ public ExecuteCommandUnMergeCohortIdentificationConfiguration(IBasicActivateItem return; } - if (_target.GetAggregateConfigurations().Any()) + if (_target.GetAggregateConfigurations().Length != 0) { SetImpossible("Container must contain only subcontainers (i.e. no aggregate sets)"); return; @@ -50,7 +50,6 @@ public ExecuteCommandUnMergeCohortIdentificationConfiguration(IBasicActivateItem if (_target.GetSubContainers().Length <= 1) { SetImpossible("Container must have 2 or more immediate subcontainers for unmerging"); - return; } } diff --git a/Rdmp.Core/CommandExecution/AtomicCommands/ExecuteCommandUpdateCatalogueDataLocation.cs b/Rdmp.Core/CommandExecution/AtomicCommands/ExecuteCommandUpdateCatalogueDataLocation.cs index b4cc3c7b1b..49186fb82b 100644 --- a/Rdmp.Core/CommandExecution/AtomicCommands/ExecuteCommandUpdateCatalogueDataLocation.cs +++ b/Rdmp.Core/CommandExecution/AtomicCommands/ExecuteCommandUpdateCatalogueDataLocation.cs @@ -18,7 +18,7 @@ public class ExecuteCommandUpdateCatalogueDataLocation : BasicCommandExecution, private readonly CatalogueItem[] _selectedCatalogueItems; private readonly string _catalogueMapping; - public readonly string CatalogueMappingIdentifier = "$column"; + private const string CatalogueMappingIdentifier = "$column"; private bool _checksPassed; @@ -108,12 +108,9 @@ private string GenerateNewSQLPath(string path) private TableInfo TableIsAlreadyKnown() { - return _activator.RepositoryLocator.CatalogueRepository.GetAllObjects().Where(ti => - { - return ti.Name == _table.GetFullyQualifiedName() && - ti.Server == _table.Database.Server.Name && - ti.Database == _table.Database.GetRuntimeName(); - }).FirstOrDefault(); + return _activator.RepositoryLocator.CatalogueRepository.GetAllObjects().FirstOrDefault(ti => ti.Name == _table.GetFullyQualifiedName() && + ti.Server == _table.Database.Server.Name && + ti.Database == _table.Database.GetRuntimeName()); } diff --git a/Rdmp.Core/CommandExecution/CommandInvoker.cs b/Rdmp.Core/CommandExecution/CommandInvoker.cs index e340b7bbe8..ae2e6b65d6 100644 --- a/Rdmp.Core/CommandExecution/CommandInvoker.cs +++ b/Rdmp.Core/CommandExecution/CommandInvoker.cs @@ -251,7 +251,6 @@ private void ExecuteCommand(ConstructorInfo constructorInfo, CommandLineObjectPi //the parameters are expected to be consumed by the target constructors so its not really a problem if there are extra complainAboutExtraParameters = false; - continue; } else //if we have argument values specified diff --git a/Rdmp.Core/CommandExecution/GoToCommandFactory.cs b/Rdmp.Core/CommandExecution/GoToCommandFactory.cs index b886012e2b..0a9d9f0b07 100644 --- a/Rdmp.Core/CommandExecution/GoToCommandFactory.cs +++ b/Rdmp.Core/CommandExecution/GoToCommandFactory.cs @@ -272,7 +272,7 @@ public IEnumerable GetCommands(object forObject) if (catalogue.LoadMetadatas().Length == 0) { yield return new ExecuteCommandShow(_activator, null, typeof(LoadMetadata)) - { OverrideCommandName = $"No Data Load", OverrideIcon = GetImage(RDMPConcept.LoadMetadata) }; + { OverrideCommandName = "No Data Load", OverrideIcon = GetImage(RDMPConcept.LoadMetadata) }; } @@ -415,24 +415,19 @@ public IEnumerable GetCommands(object forObject) }; var obj = ExtractableCohortAuditLogBuilder.GetObjectIfAny(cohort, _activator.RepositoryLocator); - if (obj is not null && obj is CohortIdentificationConfiguration configuration) + if (obj is CohortIdentificationConfiguration configuration) { - yield return new ExecuteCommandShow(_activator, () => - { - return [configuration]; - }) + yield return new ExecuteCommandShow(_activator, () => [configuration]) { OverrideCommandName = "Cohort Identification Configuration(s)", OverrideIcon = GetImage(RDMPConcept.CohortIdentificationConfiguration) }; } - } //if it is a masquerader and masquerading as a DatabaseEntity then add a goto the object - if (forObject is IMasqueradeAs masqueraderIfAny) - if (masqueraderIfAny.MasqueradingAs() is DatabaseEntity m) - yield return new ExecuteCommandShow(_activator, m, 0, true) + if (forObject is IMasqueradeAs masqueraderIfAny && masqueraderIfAny.MasqueradingAs() is DatabaseEntity m) + yield return new ExecuteCommandShow(_activator, m, 0, true) { OverrideIcon = _activator.CoreIconProvider.GetImage(m) }; } diff --git a/Rdmp.Core/CommandLine/DatabaseCreation/NightmareDatasets.cs b/Rdmp.Core/CommandLine/DatabaseCreation/NightmareDatasets.cs index d540b5f4ee..20b028d828 100644 --- a/Rdmp.Core/CommandLine/DatabaseCreation/NightmareDatasets.cs +++ b/Rdmp.Core/CommandLine/DatabaseCreation/NightmareDatasets.cs @@ -18,12 +18,12 @@ namespace Rdmp.Core.CommandLine.DatabaseCreation; -internal class NightmareDatasets : DataGenerator +internal class NightmareDatasets(IRDMPPlatformRepositoryServiceLocator repos, DiscoveredDatabase db) + : DataGenerator(new Random(123)) { - private IRDMPPlatformRepositoryServiceLocator _repos; - private string _serverName; - private string _databaseNameWrapped; - private string _databaseNameRuntime; + private readonly string _serverName = db.Server.Name; + private readonly string _databaseNameWrapped = db.GetWrappedName(); + private readonly string _databaseNameRuntime = db.GetRuntimeName(); /// /// Defaults to 1, set to 2 to double the amount of objects generated. @@ -31,23 +31,13 @@ internal class NightmareDatasets : DataGenerator /// public int Factor = 1; - public NightmareDatasets(IRDMPPlatformRepositoryServiceLocator repos, DiscoveredDatabase db) : base(new Random(123)) - { - _repos = repos; - var db1 = db; - _serverName = db1.Server.Name; - _databaseNameWrapped = db1.GetWrappedName(); - _databaseNameRuntime = db1.GetRuntimeName(); - } - - private BucketList Catalogues = new (); - private BucketList ExtractableDatasets = new (); - private BucketList Projects = new (); - private BucketList Tables = new (); - private int TablesCount; + private readonly BucketList Catalogues = new (); + private readonly BucketList ExtractableDatasets = new (); + private readonly BucketList Projects = new (); + private readonly BucketList Tables = new (); + private int _tablesCount; - private BucketList Columns = new(); - private int ColumnsCount; + private int _columnsCount; /// /// Generates a lot of metadata in the RDMP platform databases. This is for testing @@ -60,12 +50,14 @@ public void Create(ExternalCohortTable ect) { // how likely is a given ExtractionInformation to be each of these // categories - var extractionCategories = new BucketList(); - extractionCategories.Add(100, ExtractionCategory.Core); - extractionCategories.Add(10, ExtractionCategory.Internal); - extractionCategories.Add(5, ExtractionCategory.Supplemental); - extractionCategories.Add(10, ExtractionCategory.SpecialApprovalRequired); - extractionCategories.Add(4, ExtractionCategory.Deprecated); + var extractionCategories = new BucketList + { + { 100, ExtractionCategory.Core }, + { 10, ExtractionCategory.Internal }, + { 5, ExtractionCategory.Supplemental }, + { 10, ExtractionCategory.SpecialApprovalRequired }, + { 4, ExtractionCategory.Deprecated } + }; var extractionDir = Path.GetTempPath(); @@ -73,7 +65,7 @@ public void Create(ExternalCohortTable ect) // Based on DLS figures see: https://github.com/HicServices/RDMP/issues/1224 for (var i = 0; i < 500 * Factor; i++) { - var cata = new Catalogue(_repos.CatalogueRepository, $"Catalogue {GetRandomGPCode(r)}") + var cata = new Catalogue(repos.CatalogueRepository, $"Catalogue {GetRandomGPCode(r)}") { Description = GetRandomSentence(r) }; @@ -90,46 +82,45 @@ public void Create(ExternalCohortTable ect) foreach (var col in CreateTable()) { - var ci = new CatalogueItem(_repos.CatalogueRepository, cata, col.Name); + var ci = new CatalogueItem(repos.CatalogueRepository, cata, col.Name); // = 60% of columns are extractable - if (r.Next(10) < 6) + if (r.Next(10) >= 6) continue; + + var ei = new ExtractionInformation(repos.CatalogueRepository, ci, col, col.Name) { - var ei = new ExtractionInformation(_repos.CatalogueRepository, ci, col, col.Name) - { - ExtractionCategory = extractionCategories.GetRandom(r) - }; + ExtractionCategory = extractionCategories.GetRandom(r) + }; + + if (first) + { + hasExtractionIdentifier = r.Next(2) == 0; - if (first) + // make the first field the linkage identifier + // if we are doing that + if (hasExtractionIdentifier) { - hasExtractionIdentifier = r.Next(2) == 0; - - // make the first field the linkage identifier - // if we are doing that - if (hasExtractionIdentifier) - { - ei.IsExtractionIdentifier = true; - ei.ExtractionCategory = ExtractionCategory.Core; - ei.SaveToDatabase(); - } + ei.IsExtractionIdentifier = true; + ei.ExtractionCategory = ExtractionCategory.Core; + ei.SaveToDatabase(); } - - first = false; } + + first = false; } // half of the Catalogues have IsExtractionIdentifier // but let's make only 75% of those extractable datasets if (r.Next(5) > 0 && hasExtractionIdentifier) { - var eds = new ExtractableDataSet(_repos.DataExportRepository, cata); + var eds = new ExtractableDataSet(repos.DataExportRepository, cata); ExtractableDatasets.Add(1, eds); } } // There are 500 tables associated with Catalogues // but also 250 tables that are not linked to any Catalogues - for (var i = 0; i < 250 * Factor; i++) CreateTable(); + for (var i = 0; i < 250 * Factor; i++) _ = CreateTable(); // open a connection to the cohort db for creating external cohorts using var con = ect.Discover().Server.GetManagedConnection(); @@ -137,7 +128,7 @@ public void Create(ExternalCohortTable ect) for (var i = 0; i < 200 * Factor; i++) { // each project - var p = new Project(_repos.DataExportRepository, $"Project {i}") + var p = new Project(repos.DataExportRepository, $"Project {i}") { ProjectNumber = r.Next(50) == 0 ? 5 : i, // it's ok for some projects to have the same number ExtractionDirectory = extractionDir @@ -150,7 +141,7 @@ public void Create(ExternalCohortTable ect) for (var c = 0; c < numberOfConfigs; c++) { - var config = new ExtractionConfiguration(_repos.DataExportRepository, p, + var config = new ExtractionConfiguration(repos.DataExportRepository, p, $"Extraction {GetRandomGPCode(r)}"); if (r.Next(2) == 0) config.RequestTicket = GetRandomGPCode(r); // some have request tickets @@ -167,12 +158,12 @@ public void Create(ExternalCohortTable ect) var request = new CohortCreationRequest(p, new CohortDefinition(null, "Created by NightmareDatasets", 1, p.ProjectNumber.Value, ect), - _repos.DataExportRepository, + repos.DataExportRepository, $"Nightmare dreamed on {DateTime.Now}"); request.PushToServer(con); - var cohort = new ExtractableCohort(_repos.DataExportRepository, ect, + var cohort = new ExtractableCohort(repos.DataExportRepository, ect, request.NewCohortDefinition.ID.Value); config.Cohort_ID = cohort.ID; config.SaveToDatabase(); @@ -196,7 +187,7 @@ public void Create(ExternalCohortTable ect) // 5% have subcontainers if (r.Next(20) == 0) { - var subContainer = new FilterContainer(_repos.DataExportRepository); + var subContainer = new FilterContainer(repos.DataExportRepository); sds.RootFilterContainer.AddChild(subContainer); AddExtractionFiltersTo(subContainer); } @@ -207,12 +198,12 @@ public void Create(ExternalCohortTable ect) // 200 cics for (var i = 0; i < 200 * Factor; i++) { - var cic = new CohortIdentificationConfiguration(_repos.CatalogueRepository, + var cic = new CohortIdentificationConfiguration(repos.CatalogueRepository, $"Cohort Query {GetRandomGPCode(r)}"); // 25% of cics are associated with a specific project if (r.Next(4) == 0) - _ = new ProjectCohortIdentificationConfigurationAssociation(_repos.DataExportRepository, + _ = new ProjectCohortIdentificationConfigurationAssociation(repos.DataExportRepository, Projects.GetRandom(r), cic); } } @@ -222,7 +213,7 @@ private void AddExtractionFiltersTo(IContainer container) var numberOfFilters = GetGaussianInt(0, 2); for (var f = 0; f < numberOfFilters; f++) { - var filter = new DeployedExtractionFilter(_repos.DataExportRepository, + var filter = new DeployedExtractionFilter(repos.DataExportRepository, $"Filter {Guid.NewGuid()}", null) { WhereSQL = "ColX > 0" @@ -238,7 +229,7 @@ private IEnumerable CreateTable() // 762 tables // 18415 columns // = average of 24 columns per table - var ti = new TableInfo(_repos.CatalogueRepository, $"[MyDb].[Table{TablesCount++}]"); + var ti = new TableInfo(repos.CatalogueRepository, $"[MyDb].[Table{_tablesCount++}]"); // let's not set the server name on 1 in 20 so we get all those // horrible null references out in the open @@ -260,7 +251,7 @@ private IEnumerable CreateTable() var numberOfColumns = GetGaussianInt(1, 48); for (var j = 0; j < numberOfColumns; j++) - yield return new ColumnInfo(_repos.CatalogueRepository, $"MyCol{ColumnsCount++}", "varchar(10)", ti); + yield return new ColumnInfo(repos.CatalogueRepository, $"MyCol{_columnsCount++}", "varchar(10)", ti); } // we are not actually interested in these methods, just want to use GetGaussian etc diff --git a/Rdmp.Core/CommandLine/Interactive/ConsoleInputManager.cs b/Rdmp.Core/CommandLine/Interactive/ConsoleInputManager.cs index 19bda3a42c..a3878aec7b 100644 --- a/Rdmp.Core/CommandLine/Interactive/ConsoleInputManager.cs +++ b/Rdmp.Core/CommandLine/Interactive/ConsoleInputManager.cs @@ -147,8 +147,7 @@ public override bool SelectType(DialogArgs args, Type[] available, out Type chos public override IMapsDirectlyToDatabaseTable[] SelectMany(DialogArgs args, Type arrayElementType, IMapsDirectlyToDatabaseTable[] availableObjects) { - var value = ReadLineWithAuto(args, new PickObjectBase[] - { new PickObjectByID(this), new PickObjectByName(this) }); + var value = ReadLineWithAuto(args, new PickObjectByID(this), new PickObjectByName(this)); var unavailable = value.DatabaseEntities.Except(availableObjects).ToArray(); @@ -230,8 +229,7 @@ public override IMapsDirectlyToDatabaseTable SelectOne(DialogArgs args, Console.Write(args.EntryLabel); - var value = ReadLineWithAuto(args, new PickObjectBase[] - { new PickObjectByID(this), new PickObjectByName(this) }); + var value = ReadLineWithAuto(args, new PickObjectByID(this), new PickObjectByName(this)); var chosen = value.DatabaseEntities?.SingleOrDefault(); diff --git a/Rdmp.Core/CommandLine/Runners/ExtractionRunner.cs b/Rdmp.Core/CommandLine/Runners/ExtractionRunner.cs index 97bff632e6..8e8d872d5f 100644 --- a/Rdmp.Core/CommandLine/Runners/ExtractionRunner.cs +++ b/Rdmp.Core/CommandLine/Runners/ExtractionRunner.cs @@ -8,6 +8,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; +using System.Threading; using Rdmp.Core.CommandExecution; using Rdmp.Core.CommandLine.Options; using Rdmp.Core.Curation.Data; @@ -40,7 +41,7 @@ public class ExtractionRunner : ManyRunner private ExtractGlobalsCommand _globalsCommand; private Pipeline _pipeline; private LogManager _logManager; - private object _oLock = new(); + private readonly Lock _oLock = new(); public Dictionary ExtractCommands { get; private set; } public ExtractionRunner(IBasicActivateItems activator, ExtractionOptions extractionOpts) : base(extractionOpts) diff --git a/Rdmp.Core/CommandLine/Runners/ManyRunner.cs b/Rdmp.Core/CommandLine/Runners/ManyRunner.cs index 457b54758c..ecb8e2d243 100644 --- a/Rdmp.Core/CommandLine/Runners/ManyRunner.cs +++ b/Rdmp.Core/CommandLine/Runners/ManyRunner.cs @@ -30,7 +30,7 @@ public abstract class ManyRunner : Runner /// /// Lock for all operations that read or write to . Use it if you want to enumerate / read the results /// - private readonly object _oLock = new(); + private readonly Lock _oLock = new(); protected ManyRunner(ConcurrentRDMPCommandLineOptions options) { diff --git a/Rdmp.Core/CommandLine/Runners/ReleaseRunner.cs b/Rdmp.Core/CommandLine/Runners/ReleaseRunner.cs index ee587d0c24..44200dddde 100644 --- a/Rdmp.Core/CommandLine/Runners/ReleaseRunner.cs +++ b/Rdmp.Core/CommandLine/Runners/ReleaseRunner.cs @@ -113,19 +113,21 @@ protected override ICheckable[] GetCheckables(ICheckNotifier checkNotifier) if (_pipeline == null) { checkNotifier.OnCheckPerformed(new CheckEventArgs("No Pipeline has been picked", CheckResult.Fail)); - return Array.Empty(); + return []; } var useCase = GetReleaseUseCase(checkNotifier); if (useCase != null) { var engine = useCase.GetEngine(_pipeline, ThrowImmediatelyDataLoadEventListener.Quiet); - if (engine.DestinationObject is IInteractiveCheckable) + if (engine.DestinationObject is IInteractiveCheckable checkable) { - ((IInteractiveCheckable)engine.DestinationObject).SetActivator(_activator); + checkable.SetActivator(_activator); } + toReturn.Add(engine); } + return toReturn.ToArray(); } diff --git a/Rdmp.Core/Curation/Data/Catalogue.cs b/Rdmp.Core/Curation/Data/Catalogue.cs index e33c7705bc..80c403f8f6 100644 --- a/Rdmp.Core/Curation/Data/Catalogue.cs +++ b/Rdmp.Core/Curation/Data/Catalogue.cs @@ -899,7 +899,7 @@ public void Check(ICheckNotifier notifier) $"Found {extractionInformations.Length} ExtractionInformation(s), preparing to validate SQL with QueryBuilder", CheckResult.Success)); - var accessContext = DataAccessContext.InternalDataProcessing; + const DataAccessContext accessContext = DataAccessContext.InternalDataProcessing; try { diff --git a/Rdmp.Core/Curation/Data/CatalogueItem.cs b/Rdmp.Core/Curation/Data/CatalogueItem.cs index 0e94917b21..4099266471 100644 --- a/Rdmp.Core/Curation/Data/CatalogueItem.cs +++ b/Rdmp.Core/Curation/Data/CatalogueItem.cs @@ -336,12 +336,12 @@ public CatalogueItem CloneCatalogueItemWithIDIntoCatalogue(Catalogue cataToImpor GetType().GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); //Assign all source property to target object 's properties - foreach (var property in propertyInfo) - //Check whether property can be written to - if (property.CanWrite && !property.Name.Equals("ID") && !property.Name.Equals("Catalogue_ID")) - if (property.PropertyType.IsValueType || property.PropertyType.IsEnum || - property.PropertyType.Equals(typeof(string))) - property.SetValue(clone, property.GetValue(this, null), null); + foreach (var property in propertyInfo + .Where(static property => + (property.CanWrite && !property.Name.Equals("ID") && !property.Name.Equals("Catalogue_ID")) && + (property.PropertyType.IsValueType || property.PropertyType.IsEnum || + property.PropertyType == typeof(string)))) + property.SetValue(clone, property.GetValue(this, null), null); clone.SaveToDatabase(); diff --git a/Rdmp.Core/Curation/Data/DataLoad/LoadMetadata.cs b/Rdmp.Core/Curation/Data/DataLoad/LoadMetadata.cs index 4a33dd877b..c4e9c7ee47 100644 --- a/Rdmp.Core/Curation/Data/DataLoad/LoadMetadata.cs +++ b/Rdmp.Core/Curation/Data/DataLoad/LoadMetadata.cs @@ -11,7 +11,6 @@ using System.Linq; using FAnsi.Discovery; using FAnsi.Discovery.QuerySyntax; -using MongoDB.Driver; using Rdmp.Core.Curation.Data.Cache; using Rdmp.Core.Curation.Data.Defaults; using Rdmp.Core.Curation.Data.ImportExport; diff --git a/Rdmp.Core/Curation/Data/DataLoad/ProcessTask.cs b/Rdmp.Core/Curation/Data/DataLoad/ProcessTask.cs index 1f1bf8825a..69b5a441df 100644 --- a/Rdmp.Core/Curation/Data/DataLoad/ProcessTask.cs +++ b/Rdmp.Core/Curation/Data/DataLoad/ProcessTask.cs @@ -16,7 +16,6 @@ using Rdmp.Core.MapsDirectlyToDatabaseTable; using Rdmp.Core.MapsDirectlyToDatabaseTable.Attributes; using Rdmp.Core.Repositories; -using Rdmp.Core.ReusableLibraryCode; using Rdmp.Core.ReusableLibraryCode.Annotations; using Rdmp.Core.ReusableLibraryCode.Checks; diff --git a/Rdmp.Core/Curation/Data/DemandsNestedInitializationAttribute.cs b/Rdmp.Core/Curation/Data/DemandsNestedInitializationAttribute.cs index 790a3e6ce0..5e87b40b2d 100644 --- a/Rdmp.Core/Curation/Data/DemandsNestedInitializationAttribute.cs +++ b/Rdmp.Core/Curation/Data/DemandsNestedInitializationAttribute.cs @@ -12,6 +12,4 @@ namespace Rdmp.Core.Curation.Data; /// Used by classes to indicate that a complex POCO property should have all its properties initialized from a ProcessTaskArgument /// [AttributeUsage(AttributeTargets.Property)] -public class DemandsNestedInitializationAttribute : Attribute -{ -} \ No newline at end of file +public class DemandsNestedInitializationAttribute : Attribute; \ No newline at end of file diff --git a/Rdmp.Core/Curation/Data/EntityNaming/FixedStagingDatabaseNamer.cs b/Rdmp.Core/Curation/Data/EntityNaming/FixedStagingDatabaseNamer.cs index d1fdf67c7a..835a633a84 100644 --- a/Rdmp.Core/Curation/Data/EntityNaming/FixedStagingDatabaseNamer.cs +++ b/Rdmp.Core/Curation/Data/EntityNaming/FixedStagingDatabaseNamer.cs @@ -44,12 +44,12 @@ public override string GetDatabaseName(string rootDatabaseName, LoadBubble stage /// /// /// - protected static string EnsureValueIsNotWrapped(string s) + private static string EnsureValueIsNotWrapped(string s) { if (s == null) return null; - var toReturn = s.Trim(new char[] { '[', ']', '`', '"' }); + var toReturn = s.Trim('[', ']', '`', '"'); return toReturn.Contains('[') || toReturn.Contains(']') || diff --git a/Rdmp.Core/Curation/Data/JoinInfo.cs b/Rdmp.Core/Curation/Data/JoinInfo.cs index eead3c2e4a..e404dd5a96 100644 --- a/Rdmp.Core/Curation/Data/JoinInfo.cs +++ b/Rdmp.Core/Curation/Data/JoinInfo.cs @@ -158,10 +158,10 @@ public JoinInfo(ICatalogueRepository repository, ColumnInfo foreignKey, ColumnIn ExtractionJoinType type, string collation) { if (foreignKey.ID == primaryKey.ID) - throw new ArgumentException("Joink Key 1 and Join Key 2 cannot be the same"); + throw new ArgumentException("Join Key 1 and Join Key 2 cannot be the same"); if (foreignKey.TableInfo_ID == primaryKey.TableInfo_ID) - throw new ArgumentException("Joink Key 1 and Join Key 2 are from the same table, this is not cool"); + throw new ArgumentException("Join Key 1 and Join Key 2 must be from different tables"); repository.InsertAndHydrate(this, new Dictionary { diff --git a/Rdmp.Core/Curation/Data/LoadModuleAssembly.cs b/Rdmp.Core/Curation/Data/LoadModuleAssembly.cs index 837a20354a..12a9418004 100644 --- a/Rdmp.Core/Curation/Data/LoadModuleAssembly.cs +++ b/Rdmp.Core/Curation/Data/LoadModuleAssembly.cs @@ -117,17 +117,14 @@ private static Dictionary HandlePluginVersioning() /// internal static IEnumerable PluginFiles() { - if (Directory.EnumerateFiles(AppDomain.CurrentDomain.BaseDirectory, "*.rdmp").Count() > 0) - { - //use the modern .RDMP plugins - var plugins = HandlePluginVersioning(); - return plugins.Values.ToArray(); - - } - return File.Exists(PluginsList) - ? File.ReadAllLines(PluginsList) - .Select(static name => Path.Combine(AppDomain.CurrentDomain.BaseDirectory, name)) - : Directory.EnumerateFiles(AppDomain.CurrentDomain.BaseDirectory, "*.nupkg"); + if (!Directory.EnumerateFiles(AppDomain.CurrentDomain.BaseDirectory, "*.rdmp").Any()) + return File.Exists(PluginsList) + ? File.ReadAllLines(PluginsList) + .Select(static name => Path.Combine(AppDomain.CurrentDomain.BaseDirectory, name)) + : Directory.EnumerateFiles(AppDomain.CurrentDomain.BaseDirectory, "*.nupkg"); + //use the modern .RDMP plugins + var plugins = HandlePluginVersioning(); + return plugins.Values.ToArray(); } /// diff --git a/Rdmp.Core/Curation/Data/TableInfo.cs b/Rdmp.Core/Curation/Data/TableInfo.cs index 1b9f64a9f2..63342e9ef6 100644 --- a/Rdmp.Core/Curation/Data/TableInfo.cs +++ b/Rdmp.Core/Curation/Data/TableInfo.cs @@ -389,25 +389,16 @@ public IEnumerable GetColumnsAtStage(LoadStage loa { //if it is AdjustRaw then it will also have the pre load discarded columns if (loadStage <= LoadStage.AdjustRaw) - foreach (var discardedColumn in PreLoadDiscardedColumns.Where(c => + foreach (var discardedColumn in PreLoadDiscardedColumns.Where(static c => c.Destination != DiscardedColumnDestination.Dilute)) yield return discardedColumn; //also add column infos - foreach (var c in ColumnInfos) - if (loadStage <= LoadStage.AdjustRaw && SpecialFieldNames.IsHicPrefixed(c)) - continue; - else if (loadStage <= LoadStage.AdjustStaging && - c.IsAutoIncrement) //auto increment columns do not get created in RAW/STAGING - continue; - else if (loadStage == LoadStage.AdjustStaging && - //these two do not appear in staging - (c.GetRuntimeName().Equals(SpecialFieldNames.DataLoadRunID) || - c.GetRuntimeName().Equals(SpecialFieldNames.ValidFrom)) - ) - continue; - else - yield return c; + foreach (var c in ColumnInfos.Where( + c => loadStage > LoadStage.AdjustRaw || !SpecialFieldNames.IsHicPrefixed(c) || + loadStage > LoadStage.AdjustStaging || !c.IsAutoIncrement || + loadStage == LoadStage.AdjustStaging || !new[] { SpecialFieldNames.DataLoadRunID, SpecialFieldNames.ValidFrom }.Contains(c.GetRuntimeName()))) + yield return c; } /// @@ -505,4 +496,8 @@ public bool Is(DiscoveredTable discoveredTable, bool alsoCheckServer = false) => DatabaseType == discoveredTable.Database.Server.DatabaseType && (!alsoCheckServer || discoveredTable.Database.Server.Name.Equals(Server, StringComparison.CurrentCultureIgnoreCase)); + + public override bool Equals(object o) => base.Equals(o); + + public override int GetHashCode() => Repository.GetHashCode(); } \ No newline at end of file diff --git a/Rdmp.Core/Curation/DataHelper/RegexRedaction/IRegexRedactionConfiguration.cs b/Rdmp.Core/Curation/DataHelper/RegexRedaction/IRegexRedactionConfiguration.cs index dfa257f5d4..8b7b626d69 100644 --- a/Rdmp.Core/Curation/DataHelper/RegexRedaction/IRegexRedactionConfiguration.cs +++ b/Rdmp.Core/Curation/DataHelper/RegexRedaction/IRegexRedactionConfiguration.cs @@ -4,7 +4,6 @@ // 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. // You should have received a copy of the GNU General Public License along with RDMP. If not, see . -using Rdmp.Core.Curation.Data; using Rdmp.Core.MapsDirectlyToDatabaseTable; using Rdmp.Core.Repositories; diff --git a/Rdmp.Core/Curation/DataHelper/RegexRedaction/RegexRedactionHelper.cs b/Rdmp.Core/Curation/DataHelper/RegexRedaction/RegexRedactionHelper.cs index c8491c55ad..0162551333 100644 --- a/Rdmp.Core/Curation/DataHelper/RegexRedaction/RegexRedactionHelper.cs +++ b/Rdmp.Core/Curation/DataHelper/RegexRedaction/RegexRedactionHelper.cs @@ -31,12 +31,12 @@ public enum Constants { RegexRedaction_ID, Value, TEMP_RedactionUpdates - }; + } public static DataTable GenerateRedactionsDataTable() { - DataTable redactionsToSaveTable = new DataTable(); + var redactionsToSaveTable = new DataTable(); redactionsToSaveTable.Columns.Add(nameof(Constants.RedactionConfiguration_ID)); redactionsToSaveTable.Columns.Add(nameof(Constants.ColumnInfo_ID)); redactionsToSaveTable.Columns.Add(nameof(Constants.startingIndex)); @@ -58,19 +58,17 @@ public static DataTable GeneratePKDataTable() public static string ConvertPotentialDateTimeObject(string value, string currentColumnType) { var matchValue = $"'{value}'"; - if (currentColumnType == "datetime2" || currentColumnType == "datetime") - { - var x = DateTime.Parse(value); - var format = "yyyy-MM-dd HH:mm:ss:fff"; - matchValue = $"'{x.ToString(format)}'"; - } + if (currentColumnType is not ("datetime2" or "datetime")) return matchValue; + + var x = DateTime.Parse(value); + const string format = "yyyy-MM-dd HH:mm:ss:fff"; + matchValue = $"'{x.ToString(format)}'"; return matchValue; } - public static string GetRedactionValue(string value, ColumnInfo column, DataRow m, List _cataloguePKs, RegexRedactionConfiguration _redactionConfiguration, DataTable redactionsToSaveTable, DataTable pksToSave, DataTable redactionUpates) + private static string GetRedactionValue(string value, ColumnInfo column, DataRow m, List _cataloguePKs, RegexRedactionConfiguration _redactionConfiguration, DataTable redactionsToSaveTable, DataTable pksToSave, DataTable redactionUpates) { - - Dictionary pkLookup = Enumerable.Range(0, _cataloguePKs.Count).ToDictionary(i => _cataloguePKs[i].ColumnInfo, i => m[i + 1].ToString()); + var pkLookup = Enumerable.Range(0, _cataloguePKs.Count).ToDictionary(i => _cataloguePKs[i].ColumnInfo, i => m[i + 1].ToString()); var matches = Regex.Matches(value, _redactionConfiguration.RegexPattern); var offset = 0; foreach (var match in matches) @@ -84,6 +82,7 @@ public static string GetRedactionValue(string value, ColumnInfo column, DataRow { throw new Exception($"Redaction string '{_redactionConfiguration.RedactionString}' is longer than found match '{foundMatch}'."); } + if (lengthDiff > 0) { var start = (int)Math.Floor(lengthDiff / 2); @@ -91,12 +90,14 @@ public static string GetRedactionValue(string value, ColumnInfo column, DataRow replacementValue = replacementValue.PadLeft(start + replacementValue.Length, '<'); replacementValue = replacementValue.PadRight(end + replacementValue.Length, '>'); } + value = value[..startingIndex] + replacementValue + value[(startingIndex + foundMatch.Length)..]; - redactionsToSaveTable.Rows.Add([_redactionConfiguration.ID, column.ID, startingIndex, replacementValue, foundMatch]); + redactionsToSaveTable.Rows.Add(_redactionConfiguration.ID, column.ID, startingIndex, replacementValue, foundMatch); foreach (var pk in pkLookup) { - pksToSave.Rows.Add([redactionUpates.Rows.Count + offset, pk.Key.ID, pk.Value]); + pksToSave.Rows.Add(redactionUpates.Rows.Count + offset, pk.Key.ID, pk.Value); } + offset++; } diff --git a/Rdmp.Core/Curation/FilterImporting/ParameterCreator.cs b/Rdmp.Core/Curation/FilterImporting/ParameterCreator.cs index d9c12ca758..fe89d86a74 100644 --- a/Rdmp.Core/Curation/FilterImporting/ParameterCreator.cs +++ b/Rdmp.Core/Curation/FilterImporting/ParameterCreator.cs @@ -185,7 +185,7 @@ private static HashSet GetRequiredParamaterNamesForQuery(string whereSql public static string RenameParameterInSQL(string haystack, string parameterName, string parameterNameReplacement) { //Does a zero matching look ahead for anything that isn't a legal parameter name e.g. "@bob)" will match the bracket but will not replace the bracket since the match is zero width - var regexBoundary = @"(?=[^A-Za-z0-9_#@$])"; + const string regexBoundary = @"(?=[^A-Za-z0-9_#@$])"; var patternNeedle = Regex.Escape(parameterName); diff --git a/Rdmp.Core/DataExport/Checks/SelectedDataSetsChecker.cs b/Rdmp.Core/DataExport/Checks/SelectedDataSetsChecker.cs index da6b040089..cc4efbcbfc 100644 --- a/Rdmp.Core/DataExport/Checks/SelectedDataSetsChecker.cs +++ b/Rdmp.Core/DataExport/Checks/SelectedDataSetsChecker.cs @@ -292,8 +292,7 @@ private void ComplainIfUserHasHotSwappedCohort(ICheckNotifier notifier, IExtract } catch (Exception ex) { - notifier.OnCheckPerformed(new CheckEventArgs(ErrorCodes.NoSqlAuditedForExtractionProgress, ex, - new object[] { progress })); + notifier.OnCheckPerformed(new CheckEventArgs(ErrorCodes.NoSqlAuditedForExtractionProgress, ex, progress)); return; } diff --git a/Rdmp.Core/DataExport/DataExtraction/ExtractionTimeTimeCoverageAggregator.cs b/Rdmp.Core/DataExport/DataExtraction/ExtractionTimeTimeCoverageAggregator.cs index c284718491..a88705cd0f 100644 --- a/Rdmp.Core/DataExport/DataExtraction/ExtractionTimeTimeCoverageAggregator.cs +++ b/Rdmp.Core/DataExport/DataExtraction/ExtractionTimeTimeCoverageAggregator.cs @@ -164,7 +164,7 @@ public void ProcessRow(DataRow row) private void ExtendBucketsToEncompas(DateTime key) { var addCount = 0; - var somethingHasGoneWrongIfAddedThisManyBuckets = 100000; + const int somethingHasGoneWrongIfAddedThisManyBuckets = 100000; if (Buckets.Keys.Max() < key) { diff --git a/Rdmp.Core/DataExport/DataExtraction/Pipeline/Sources/ExecuteCrossServerDatasetExtractionSource.cs b/Rdmp.Core/DataExport/DataExtraction/Pipeline/Sources/ExecuteCrossServerDatasetExtractionSource.cs index f6afbc17c4..a1812c8234 100644 --- a/Rdmp.Core/DataExport/DataExtraction/Pipeline/Sources/ExecuteCrossServerDatasetExtractionSource.cs +++ b/Rdmp.Core/DataExport/DataExtraction/Pipeline/Sources/ExecuteCrossServerDatasetExtractionSource.cs @@ -70,7 +70,7 @@ public override DataTable GetChunk(IDataLoadEventListener listener, GracefulCanc private bool _doNotMigrate; private string _tablename; - private object _tableName = new(); + private readonly Lock _tableNameLock = new(); public override string HackExtractionSQL(string sql, IDataLoadEventListener listener) { @@ -146,7 +146,7 @@ public override string HackExtractionSQL(string sql, IDataLoadEventListener list private string GetTableName() { - lock (_tableName) + lock (_tableNameLock) { if (_tablename != null) return _tablename; diff --git a/Rdmp.Core/DataExport/DataExtraction/Pipeline/Sources/ExecuteDatasetExtractionSource.cs b/Rdmp.Core/DataExport/DataExtraction/Pipeline/Sources/ExecuteDatasetExtractionSource.cs index 4442e3fbdf..fe10ee837d 100644 --- a/Rdmp.Core/DataExport/DataExtraction/Pipeline/Sources/ExecuteDatasetExtractionSource.cs +++ b/Rdmp.Core/DataExport/DataExtraction/Pipeline/Sources/ExecuteDatasetExtractionSource.cs @@ -209,7 +209,7 @@ CREATE TEMP TABLE {_uuid} AS """; break; default: - listener.OnNotify(this, new NotifyEventArgs(ProgressEventType.Warning, $"Unable to create temporary table for cohort. Original cohort table will be used")); + listener.OnNotify(this, new NotifyEventArgs(ProgressEventType.Warning, "Unable to create temporary table for cohort. Original cohort table will be used")); return; @@ -223,10 +223,10 @@ CREATE TEMP TABLE {_uuid} AS cmd.ExecuteNonQuery(); } catch (Exception ex) { - listener.OnNotify(this, new NotifyEventArgs(ProgressEventType.Warning, $"Unable to create temporary table for cohort. Original cohort table will be used",ex)); + listener.OnNotify(this, new NotifyEventArgs(ProgressEventType.Warning, "Unable to create temporary table for cohort. Original cohort table will be used",ex)); _uuid = null; } - listener.OnNotify(this, new NotifyEventArgs(ProgressEventType.Information, $"Cohort successfully copied to temporary table")); + listener.OnNotify(this, new NotifyEventArgs(ProgressEventType.Information, "Cohort successfully copied to temporary table")); } @@ -692,7 +692,6 @@ public virtual void Check(ICheckNotifier notifier) if (Request == null) { notifier.OnCheckPerformed(new CheckEventArgs("ExtractionRequest has not been set", CheckResult.Fail)); - return; } } } \ No newline at end of file diff --git a/Rdmp.Core/DataExport/DataRelease/AWSReleaseEngine.cs b/Rdmp.Core/DataExport/DataRelease/AWSReleaseEngine.cs index 8d9dbf06ae..4810831e21 100644 --- a/Rdmp.Core/DataExport/DataRelease/AWSReleaseEngine.cs +++ b/Rdmp.Core/DataExport/DataRelease/AWSReleaseEngine.cs @@ -19,7 +19,6 @@ using System.IO; using System.Linq; using System.Threading.Tasks; -using Terminal.Gui; namespace Rdmp.Core.DataExport.DataRelease; @@ -43,9 +42,8 @@ public AWSReleaseEngine(Project project, ReleaseEngineSettings settings, AWSS3 s public override void DoRelease(Dictionary> toRelease, Dictionary environments, bool isPatch) { - ConfigurationsToRelease = toRelease; - string contentsFileName = "contents.txt"; + const string contentsFileName = "contents.txt"; var auditFilePath = Path.Combine(Path.GetTempPath(), contentsFileName); using (var sw = PrepareAuditFile(auditFilePath)) { diff --git a/Rdmp.Core/DataExport/DataRelease/AWSS3BucketReleaseDestination.cs b/Rdmp.Core/DataExport/DataRelease/AWSS3BucketReleaseDestination.cs index 89ceb6c04b..b2c0d2cacf 100644 --- a/Rdmp.Core/DataExport/DataRelease/AWSS3BucketReleaseDestination.cs +++ b/Rdmp.Core/DataExport/DataRelease/AWSS3BucketReleaseDestination.cs @@ -61,22 +61,16 @@ public class AWSS3BucketReleaseDestination : IPluginDataFlowComponent /// -public interface IDataFlowDestination : IDataFlowComponent -{ -} \ No newline at end of file +public interface IDataFlowDestination : IDataFlowComponent; \ No newline at end of file diff --git a/Rdmp.Core/DataFlowPipeline/IPluginDataFlowComponent.cs b/Rdmp.Core/DataFlowPipeline/IPluginDataFlowComponent.cs index 3e4a776f2b..87089cbc65 100644 --- a/Rdmp.Core/DataFlowPipeline/IPluginDataFlowComponent.cs +++ b/Rdmp.Core/DataFlowPipeline/IPluginDataFlowComponent.cs @@ -13,6 +13,4 @@ namespace Rdmp.Core.DataFlowPipeline; /// state. /// /// -public interface IPluginDataFlowComponent : IDataFlowComponent, ICheckable -{ -} \ No newline at end of file +public interface IPluginDataFlowComponent : IDataFlowComponent, ICheckable; \ No newline at end of file diff --git a/Rdmp.Core/DataFlowPipeline/IPluginDataFlowSource.cs b/Rdmp.Core/DataFlowPipeline/IPluginDataFlowSource.cs index 923d91dd82..65d3f845f8 100644 --- a/Rdmp.Core/DataFlowPipeline/IPluginDataFlowSource.cs +++ b/Rdmp.Core/DataFlowPipeline/IPluginDataFlowSource.cs @@ -12,6 +12,4 @@ namespace Rdmp.Core.DataFlowPipeline; /// MEF discoverable version of IDataFlowSource /// /// -public interface IPluginDataFlowSource : IDataFlowSource, ICheckable -{ -} \ No newline at end of file +public interface IPluginDataFlowSource : IDataFlowSource, ICheckable; \ No newline at end of file diff --git a/Rdmp.Core/DataLoad/Engine/Attachers/IPluginAttacher.cs b/Rdmp.Core/DataLoad/Engine/Attachers/IPluginAttacher.cs index 4dc2ffb39e..9cbbf52b6c 100644 --- a/Rdmp.Core/DataLoad/Engine/Attachers/IPluginAttacher.cs +++ b/Rdmp.Core/DataLoad/Engine/Attachers/IPluginAttacher.cs @@ -9,6 +9,4 @@ namespace Rdmp.Core.DataLoad.Engine.Attachers; /// /// MEF discoverable version of IAttacher (See Attacher). /// -public interface IPluginAttacher : IAttacher -{ -} \ No newline at end of file +public interface IPluginAttacher : IAttacher; \ No newline at end of file diff --git a/Rdmp.Core/DataLoad/Engine/Checks/Checkers/CatalogueLoadChecks.cs b/Rdmp.Core/DataLoad/Engine/Checks/Checkers/CatalogueLoadChecks.cs index 666c64eabb..810fa79871 100644 --- a/Rdmp.Core/DataLoad/Engine/Checks/Checkers/CatalogueLoadChecks.cs +++ b/Rdmp.Core/DataLoad/Engine/Checks/Checkers/CatalogueLoadChecks.cs @@ -178,7 +178,7 @@ private static void CheckTableInfoSynchronization(TableInfo tableInfo, ICheckNot //live is the current data load's (possibly overridden server/database) var tableInfoSynchronizer = new TableInfoSynchronizer(tableInfo); - var problemList = ""; + const string problemList = ""; //synchronize but refuse to apply all fixes, problems are instead added to problemList if (tableInfoSynchronizer.Synchronize(notifier)) @@ -268,12 +268,10 @@ private static void ConfirmStagingAndLiveHaveSameColumns(string tableName, Disco DiscoveredColumn[] liveCols, bool requireSameNumberAndOrder, ICheckNotifier notifier) { //in LIVE but not STAGING - foreach (var missingColumn in liveCols.Select(c => c.GetRuntimeName()) - .Except(stagingCols.Select(c => c.GetRuntimeName()))) + foreach (var missingColumn in liveCols.Select(static c => c.GetRuntimeName()) + .Except(stagingCols.Select(static c => c.GetRuntimeName()))) //column is in live but not in staging, but it is hic_ - if (SpecialFieldNames.IsHicPrefixed(missingColumn)) //this is permitted - continue; - else + if (!SpecialFieldNames.IsHicPrefixed(missingColumn)) //this is permitted notifier.OnCheckPerformed(new CheckEventArgs( $"Column {missingColumn} is missing from STAGING", CheckResult.Fail, null)); diff --git a/Rdmp.Core/DataLoad/Engine/Checks/Checkers/CommandLineParser.cs b/Rdmp.Core/DataLoad/Engine/Checks/Checkers/CommandLineParser.cs index 235d5b4558..982fc6e4e3 100644 --- a/Rdmp.Core/DataLoad/Engine/Checks/Checkers/CommandLineParser.cs +++ b/Rdmp.Core/DataLoad/Engine/Checks/Checkers/CommandLineParser.cs @@ -156,8 +156,6 @@ private void ParseEscapeSequence() ++i; } } - - return; } /// diff --git a/Rdmp.Core/DataLoad/Engine/Checks/Checkers/ProcessTaskChecks.cs b/Rdmp.Core/DataLoad/Engine/Checks/Checkers/ProcessTaskChecks.cs index 7139696cf1..6b5dee3f25 100644 --- a/Rdmp.Core/DataLoad/Engine/Checks/Checkers/ProcessTaskChecks.cs +++ b/Rdmp.Core/DataLoad/Engine/Checks/Checkers/ProcessTaskChecks.cs @@ -49,8 +49,8 @@ public void Check(ProcessTask processTask, ICheckNotifier notifier) var created = RuntimeTaskFactory.Create(processTask, dictionary.LoadArgs[processTask.LoadStage]); - if (created is DataProviderRuntimeTask) - ((DataProviderRuntimeTask)created).SetActivator(_activator); + if (created is DataProviderRuntimeTask task) + task.SetActivator(_activator); created.Check(notifier); } diff --git a/Rdmp.Core/DataLoad/Engine/DataProvider/IPluginDataProvider.cs b/Rdmp.Core/DataLoad/Engine/DataProvider/IPluginDataProvider.cs index 69d548db35..3d1cf92e37 100644 --- a/Rdmp.Core/DataLoad/Engine/DataProvider/IPluginDataProvider.cs +++ b/Rdmp.Core/DataLoad/Engine/DataProvider/IPluginDataProvider.cs @@ -9,6 +9,4 @@ namespace Rdmp.Core.DataLoad.Engine.DataProvider; /// /// MEF discoverable (Plugin) version of IDataProvider /// -public interface IPluginDataProvider : IDataProvider -{ -} \ No newline at end of file +public interface IPluginDataProvider : IDataProvider; \ No newline at end of file diff --git a/Rdmp.Core/DataLoad/Engine/Job/DataLoadJob.cs b/Rdmp.Core/DataLoad/Engine/Job/DataLoadJob.cs index 844ce8a17e..8261d01df4 100644 --- a/Rdmp.Core/DataLoad/Engine/Job/DataLoadJob.cs +++ b/Rdmp.Core/DataLoad/Engine/Job/DataLoadJob.cs @@ -151,7 +151,7 @@ public void LogWarning(string senderName, string message) public void CreateTablesInStage(DatabaseCloner cloner, LoadBubble stage) { - bool allowReservedPrefixColumns = stage == LoadBubble.Raw ? LoadMetadata.AllowReservedPrefix : true; + var allowReservedPrefixColumns = stage != LoadBubble.Raw || LoadMetadata.AllowReservedPrefix; foreach (TableInfo regularTableInfo in RegularTablesToLoad) cloner.CreateTablesInDatabaseFromCatalogueInfo(_listener, regularTableInfo, stage, allowReservedPrefixColumns); diff --git a/Rdmp.Core/DataLoad/Engine/Job/Scheduling/IUpdateLoadProgress.cs b/Rdmp.Core/DataLoad/Engine/Job/Scheduling/IUpdateLoadProgress.cs index fe1039f7b2..d7615eab1e 100644 --- a/Rdmp.Core/DataLoad/Engine/Job/Scheduling/IUpdateLoadProgress.cs +++ b/Rdmp.Core/DataLoad/Engine/Job/Scheduling/IUpdateLoadProgress.cs @@ -9,6 +9,4 @@ namespace Rdmp.Core.DataLoad.Engine.Job.Scheduling; /// /// See UpdateProgressIfLoadsuccessful /// -public interface IUpdateLoadProgress : IDisposeAfterDataLoad -{ -} \ No newline at end of file +public interface IUpdateLoadProgress : IDisposeAfterDataLoad; \ No newline at end of file diff --git a/Rdmp.Core/DataLoad/Engine/LoadExecution/Components/LoadFiles.cs b/Rdmp.Core/DataLoad/Engine/LoadExecution/Components/LoadFiles.cs index 1b13e27c2a..10d35b7ef6 100644 --- a/Rdmp.Core/DataLoad/Engine/LoadExecution/Components/LoadFiles.cs +++ b/Rdmp.Core/DataLoad/Engine/LoadExecution/Components/LoadFiles.cs @@ -45,7 +45,7 @@ public override ExitCodeType Run(IDataLoadJob job, GracefulCancellationToken can if (!((LoadDirectory)job.LoadDirectory).AllSubdirectoriesExist()) { job.OnNotify(this, new NotifyEventArgs(ProgressEventType.Error, - $"One or more of the Load Metadata directories does not exist. Check the following locations exits: {string.Join(", ", [job.LoadDirectory.ForLoading.FullName, job.LoadDirectory.ForArchiving.FullName, job.LoadDirectory.Cache.FullName, job.LoadDirectory.ExecutablesPath.FullName])}")); + $"One or more of the Load Metadata directories does not exist. Check the following locations exits: {string.Join(", ", job.LoadDirectory.ForLoading.FullName, job.LoadDirectory.ForArchiving.FullName, job.LoadDirectory.Cache.FullName, job.LoadDirectory.ExecutablesPath.FullName)}")); return ExitCodeType.Error; } else if (job.LoadDirectory.ForLoading.EnumerateFileSystemInfos().Any()) diff --git a/Rdmp.Core/DataLoad/Engine/LoadExecution/Components/Runtime/DataProviderRuntimeTask.cs b/Rdmp.Core/DataLoad/Engine/LoadExecution/Components/Runtime/DataProviderRuntimeTask.cs index 7918def69d..29ac004374 100644 --- a/Rdmp.Core/DataLoad/Engine/LoadExecution/Components/Runtime/DataProviderRuntimeTask.cs +++ b/Rdmp.Core/DataLoad/Engine/LoadExecution/Components/Runtime/DataProviderRuntimeTask.cs @@ -38,9 +38,9 @@ public DataProviderRuntimeTask(IProcessTask task, RuntimeArgumentCollection args $"Path is blank for ProcessTask '{task}' - it should be a class name of type {nameof(IDataProvider)}"); Provider = MEF.CreateA(classNameToInstantiate); - if(Provider is IInteractiveCheckable) + if (Provider is IInteractiveCheckable checkable) { - ((IInteractiveCheckable)Provider).SetActivator(_activator); + checkable.SetActivator(_activator); } try @@ -62,10 +62,11 @@ public override ExitCodeType Run(IDataLoadJob job, GracefulCancellationToken can job.OnNotify(this, new NotifyEventArgs(ProgressEventType.Information, $"About to fetch data using class {Provider.GetType().FullName}")); - if (Provider is IInteractiveCheckable) + if (Provider is IInteractiveCheckable checkable) { - ((IInteractiveCheckable)Provider).SetActivator(_activator); + checkable.SetActivator(_activator); } + return Provider.Fetch(job, cancellationToken); } @@ -87,10 +88,11 @@ public override void LoadCompletedSoDispose(ExitCodeType exitCode, IDataLoadEven public override void Check(ICheckNotifier checker) { - if (Provider is IInteractiveCheckable) + if (Provider is IInteractiveCheckable checkable) { - ((IInteractiveCheckable)Provider).SetActivator(_activator); + checkable.SetActivator(_activator); } + new MandatoryPropertyChecker(Provider).Check(checker); Provider.Check(checker); } diff --git a/Rdmp.Core/DataLoad/Engine/LoadExecution/Components/Standard/MigrateRAWTableToStaging.cs b/Rdmp.Core/DataLoad/Engine/LoadExecution/Components/Standard/MigrateRAWTableToStaging.cs index 622a054c91..92c98fd1a0 100644 --- a/Rdmp.Core/DataLoad/Engine/LoadExecution/Components/Standard/MigrateRAWTableToStaging.cs +++ b/Rdmp.Core/DataLoad/Engine/LoadExecution/Components/Standard/MigrateRAWTableToStaging.cs @@ -55,7 +55,7 @@ public override ExitCodeType Run(IDataLoadJob job, GracefulCancellationToken can PipelineUsage.LogsToTableLoadInfo); //where we are coming from (source) - var sourceConvention = LoadBubble.Raw; + const LoadBubble sourceConvention = LoadBubble.Raw; var sourceDatabase = _databaseConfiguration.DeployInfo[sourceConvention]; var sourceTableName = _tableInfo.GetRuntimeName(sourceConvention, _databaseConfiguration.DatabaseNamer); @@ -78,7 +78,7 @@ public override ExitCodeType Run(IDataLoadJob job, GracefulCancellationToken can // where we are going to (destination) // ignore any columns that are marked for discard - var destinationConvention = LoadBubble.Staging; + const LoadBubble destinationConvention = LoadBubble.Staging; var destinationDatabase = _databaseConfiguration.DeployInfo[LoadBubble.Staging]; var destinationTableName = _tableInfo.GetRuntimeName(destinationConvention, _databaseConfiguration.DatabaseNamer); diff --git a/Rdmp.Core/DataLoad/Engine/Mutilators/IPluginMutilateDataTables.cs b/Rdmp.Core/DataLoad/Engine/Mutilators/IPluginMutilateDataTables.cs index d4631e37f8..90d48b3e82 100644 --- a/Rdmp.Core/DataLoad/Engine/Mutilators/IPluginMutilateDataTables.cs +++ b/Rdmp.Core/DataLoad/Engine/Mutilators/IPluginMutilateDataTables.cs @@ -9,6 +9,4 @@ namespace Rdmp.Core.DataLoad.Engine.Mutilators; /// /// MEF discoverable version of IMutilateDataTables /// -public interface IPluginMutilateDataTables : IMutilateDataTables -{ -} \ No newline at end of file +public interface IPluginMutilateDataTables : IMutilateDataTables; \ No newline at end of file diff --git a/Rdmp.Core/DataLoad/Engine/Pipeline/Components/Anonymisation/ANOTransformer.cs b/Rdmp.Core/DataLoad/Engine/Pipeline/Components/Anonymisation/ANOTransformer.cs index 64b074e055..f9e85ba8a7 100644 --- a/Rdmp.Core/DataLoad/Engine/Pipeline/Components/Anonymisation/ANOTransformer.cs +++ b/Rdmp.Core/DataLoad/Engine/Pipeline/Components/Anonymisation/ANOTransformer.cs @@ -111,7 +111,7 @@ private static DataTable ColumnToDataTable(DataColumn column, bool discardNulls) if (discardNulls && (o == null || o == DBNull.Value)) continue; - table.Rows.Add(new[] { r[column.ColumnName] }); + table.Rows.Add(r[column.ColumnName]); } table.EndLoadData(); @@ -154,14 +154,10 @@ private DataTable GetSubstitutionsForANOEquivalents(DataTable table, bool previe } } - var substituteForANOIdentifiersProc = SubstitutionStoredProcedure; - - using var cmdSubstituteIdentifiers = new SqlCommand(substituteForANOIdentifiersProc, con) - { - CommandType = CommandType.StoredProcedure, - CommandTimeout = 500, - Transaction = transaction - }; + using var cmdSubstituteIdentifiers = new SqlCommand(SubstitutionStoredProcedure, con); + cmdSubstituteIdentifiers.CommandType = CommandType.StoredProcedure; + cmdSubstituteIdentifiers.CommandTimeout = 500; + cmdSubstituteIdentifiers.Transaction = transaction; cmdSubstituteIdentifiers.Parameters.Add("@batch", SqlDbType.Structured); cmdSubstituteIdentifiers.Parameters.Add("@tableName", SqlDbType.VarChar, 500); diff --git a/Rdmp.Core/DataLoad/Engine/Pipeline/Components/Anonymisation/IdentifierDumper.cs b/Rdmp.Core/DataLoad/Engine/Pipeline/Components/Anonymisation/IdentifierDumper.cs index 900051f7bd..70985a28fd 100644 --- a/Rdmp.Core/DataLoad/Engine/Pipeline/Components/Anonymisation/IdentifierDumper.cs +++ b/Rdmp.Core/DataLoad/Engine/Pipeline/Components/Anonymisation/IdentifierDumper.cs @@ -159,13 +159,13 @@ private void MergeStagingWithLive(string[] pks) mergeSql += $"{GetRuntimeName()} AS dest {Environment.NewLine}"; mergeSql += $"USING {GetStagingRuntimeName()} AS source {Environment.NewLine}"; mergeSql += $"ON ({Environment.NewLine}"; - mergeSql = pks.Aggregate(mergeSql, (s, n) => $"{s} source.[{n}]=dest.[{n}] AND") - .TrimEnd(new[] { 'A', 'N', 'D', ' ' }) + Environment.NewLine; + mergeSql = pks.Aggregate(mergeSql, static (s, n) => $"{s} source.[{n}]=dest.[{n}] AND") + .TrimEnd('A', 'N', 'D', ' ') + Environment.NewLine; mergeSql += $") WHEN NOT MATCHED BY TARGET THEN INSERT ({Environment.NewLine}"; - mergeSql = allColumns.Aggregate(mergeSql, (s, n) => $"{s}[{n}],").TrimEnd(new[] { ',', ' ' }) + + mergeSql = allColumns.Aggregate(mergeSql, static (s, n) => $"{s}[{n}],").TrimEnd(',', ' ') + Environment.NewLine; mergeSql += $") VALUES ({Environment.NewLine}"; - mergeSql = allColumns.Aggregate(mergeSql, (s, n) => $"{s} source.[{n}],").TrimEnd(new[] { ',', ' ' }) + + mergeSql = allColumns.Aggregate(mergeSql, static (s, n) => $"{s} source.[{n}],").TrimEnd(',', ' ') + Environment.NewLine; mergeSql += $");{Environment.NewLine}"; @@ -182,17 +182,17 @@ private void MergeStagingWithLive(string[] pks) updateSql += $"ON ( {Environment.NewLine}"; updateSql += $"/*Primary Keys JOIN*/{Environment.NewLine}"; updateSql = pks.Aggregate(updateSql, (s, n) => $"{s} stag.[{n}]=prod.[{n}] AND") - .TrimEnd(new[] { 'A', 'N', 'D', ' ' }) + Environment.NewLine; + .TrimEnd('A', 'N', 'D', ' ') + Environment.NewLine; updateSql += $") WHERE{Environment.NewLine}"; updateSql += $"/*Primary Keys not null*/{Environment.NewLine}"; updateSql = pks.Aggregate(updateSql, (s, n) => $"{s} stag.[{n}] IS NOT NULL AND") - .TrimEnd(new[] { 'A', 'N', 'D', ' ' }) + Environment.NewLine; + .TrimEnd('A', 'N', 'D', ' ') + Environment.NewLine; updateSql += $"AND EXISTS (SELECT {Environment.NewLine}"; updateSql += $"/*All columns in stag*/{Environment.NewLine}"; - updateSql = allColumns.Aggregate(updateSql, (s, n) => $"{s} stag.[{n}],").TrimEnd(new[] { ',', ' ' }) + + updateSql = allColumns.Aggregate(updateSql, (s, n) => $"{s} stag.[{n}],").TrimEnd(',', ' ') + Environment.NewLine; updateSql += $"EXCEPT SELECT{Environment.NewLine}"; - updateSql = allColumns.Aggregate(updateSql, (s, n) => $"{s} prod.[{n}],").TrimEnd(new[] { ',', ' ' }) + + updateSql = allColumns.Aggregate(updateSql, (s, n) => $"{s} prod.[{n}],").TrimEnd(',', ' ') + Environment.NewLine; updateSql += $")){Environment.NewLine}"; @@ -205,7 +205,7 @@ private void MergeStagingWithLive(string[] pks) updateSql += $"INNER JOIN ToUpdate ON {Environment.NewLine}"; updateSql += $"({Environment.NewLine}"; updateSql = pks.Aggregate(updateSql, (s, n) => $"{s} prod.[{n}]=ToUpdate.[{n}] AND") - .TrimEnd(new[] { 'A', 'N', 'D', ' ' }) + Environment.NewLine; + .TrimEnd('A', 'N', 'D', ' ') + Environment.NewLine; updateSql += $"){Environment.NewLine}"; using (var updateCommand = _dumpDatabase.Server.GetCommand(updateSql, con)) @@ -373,7 +373,7 @@ public void CreateIdentifierDumpTable(ColumnInfo[] primaryKeyColumnInfos) var runtimeName = columnInfo.GetRuntimeName(LoadStage.AdjustRaw); var dataType = columnInfo.GetRuntimeDataType(LoadStage.AdjustRaw); - pks.Rows.Add(new object[] { runtimeName, dataType }); + pks.Rows.Add(runtimeName, dataType); } var dumpColumns = new DataTable(); @@ -390,7 +390,7 @@ public void CreateIdentifierDumpTable(ColumnInfo[] primaryKeyColumnInfos) throw new Exception( $"{discardedColumn.GetType().Name} called {discardedColumn.RuntimeColumnName} does not have an assigned type"); - dumpColumns.Rows.Add(new object[] { discardedColumn.RuntimeColumnName, discardedColumn.SqlDataType }); + dumpColumns.Rows.Add(discardedColumn.RuntimeColumnName, discardedColumn.SqlDataType); } diff --git a/Rdmp.Core/DataLoad/Engine/Pipeline/Destinations/DataTableUploadDestination.cs b/Rdmp.Core/DataLoad/Engine/Pipeline/Destinations/DataTableUploadDestination.cs index 913650fee7..cb3d9601af 100644 --- a/Rdmp.Core/DataLoad/Engine/Pipeline/Destinations/DataTableUploadDestination.cs +++ b/Rdmp.Core/DataLoad/Engine/Pipeline/Destinations/DataTableUploadDestination.cs @@ -114,9 +114,9 @@ public CultureInfo Culture public List ExplicitTypes { get; set; } private bool _firstTime = true; - private HashSet _primaryKey = new(StringComparer.CurrentCultureIgnoreCase); + private readonly HashSet _primaryKey = new(StringComparer.CurrentCultureIgnoreCase); private DiscoveredTable _discoveredTable; - private readonly string _extractionTimeStamp = "extraction_timestamp"; + private const string ExtractionTimeStamp = "extraction_timestamp"; private readonly IExternalCohortTable _externalCohortTable; @@ -156,19 +156,19 @@ private string GetPKValue(DataColumn pkColumn, DataRow row) if (pkName == releaseIdentifierField) { //going to have to look up the previous relaseID to match - DiscoveredTable cohortTable = _externalCohortTable.DiscoverCohortTable(); + var cohortTable = _externalCohortTable.DiscoverCohortTable(); using var lookupDT = cohortTable.GetDataTable(); var releaseIdIndex = lookupDT.Columns.IndexOf(releaseIdentifierField); var privateIdIndex = lookupDT.Columns.IndexOf(privateIdentifierField); - var foundRow = lookupDT.Rows.Cast().Where(r => r.ItemArray[releaseIdIndex].ToString() == value.ToString()).LastOrDefault(); + var foundRow = lookupDT.Rows.Cast().LastOrDefault(r => r.ItemArray[releaseIdIndex].ToString() == value.ToString()); if (foundRow is not null) { var originalValue = foundRow.ItemArray[privateIdIndex]; - var existingIDsforReleaseID = lookupDT.Rows.Cast().Where(r => r.ItemArray[privateIdIndex].ToString() == originalValue.ToString()).Select(s => s.ItemArray[releaseIdIndex].ToString()); - if (existingIDsforReleaseID.Count() > 0) + var existingIDsforReleaseID = lookupDT.Rows.Cast().Where(r => r.ItemArray[privateIdIndex].ToString() == originalValue.ToString()).Select(s => s.ItemArray[releaseIdIndex].ToString()).ToList(); + if (existingIDsforReleaseID.Count != 0) { //we don't know what the current release ID is ( there may be ones from multiple cohorts) - var ids = existingIDsforReleaseID.Select(id => $"'{id}'"); + var ids = existingIDsforReleaseID.Select(static id => $"'{id}'"); return $"{pkName} in ({string.Join(',', ids)})"; } } @@ -279,9 +279,9 @@ public DataTable ProcessPipelineData(DataTable toProcess, IDataLoadEventListener _firstTime = false; } - if (IncludeTimeStamp && _discoveredTable.DiscoverColumns().All(c => c.GetRuntimeName() != _extractionTimeStamp)) + if (IncludeTimeStamp && _discoveredTable.DiscoverColumns().All(c => c.GetRuntimeName() != ExtractionTimeStamp)) { - _discoveredTable.AddColumn(_extractionTimeStamp, new DatabaseTypeRequest(typeof(DateTime)), true, 30000); + _discoveredTable.AddColumn(ExtractionTimeStamp, new DatabaseTypeRequest(typeof(DateTime)), true, 30000); } if (IndexTables) @@ -489,10 +489,10 @@ private void ClearPrimaryKeyFromDataTableAndExplicitWriteTypes(DataTable toProce private void AddTimeStampToExtractionData(DataTable toProcess) { var timeStamp = DateTime.Now; - toProcess.Columns.Add(_extractionTimeStamp); + toProcess.Columns.Add(ExtractionTimeStamp); foreach (DataRow row in toProcess.Rows) { - row[_extractionTimeStamp] = timeStamp; + row[ExtractionTimeStamp] = timeStamp; } } @@ -536,7 +536,7 @@ private void ResizeColumnsIfRequired(DataTable toProcess, IDataLoadEventListener //see if any have changed foreach (DataColumn column in toProcess.Columns) { - if (column.ColumnName == _extractionTimeStamp && IncludeTimeStamp) + if (column.ColumnName == ExtractionTimeStamp && IncludeTimeStamp) { continue; //skip internally generated columns } diff --git a/Rdmp.Core/DataLoad/Modules/Attachers/FlatFileAttacher.cs b/Rdmp.Core/DataLoad/Modules/Attachers/FlatFileAttacher.cs index 2a5c841905..8623d9574c 100644 --- a/Rdmp.Core/DataLoad/Modules/Attachers/FlatFileAttacher.cs +++ b/Rdmp.Core/DataLoad/Modules/Attachers/FlatFileAttacher.cs @@ -142,8 +142,8 @@ private void LoadFile(DiscoveredTable tableToLoad, FileInfo fileToLoad, Discover con.Open(); //now we will read data out of the file in batches - var batchNumber = 1; - var maxBatchSize = 10000; + const int batchNumber = 1; + const int maxBatchSize = 10000; var recordsCreatedSoFar = 0; try diff --git a/Rdmp.Core/DataLoad/Modules/DataFlowOperations/Aliases/AliasHandler.cs b/Rdmp.Core/DataLoad/Modules/DataFlowOperations/Aliases/AliasHandler.cs index 280f4585e0..5fd3220413 100644 --- a/Rdmp.Core/DataLoad/Modules/DataFlowOperations/Aliases/AliasHandler.cs +++ b/Rdmp.Core/DataLoad/Modules/DataFlowOperations/Aliases/AliasHandler.cs @@ -122,7 +122,7 @@ public void Abort(IDataLoadEventListener listener) public void Check(ICheckNotifier notifier) { - var timeout = 5; + const int timeout = 5; try { var result = GenerateAliasTable(timeout); @@ -130,7 +130,7 @@ public void Check(ICheckNotifier notifier) } catch (Exception e) { - var isTimeout = e.Message.ToLower().Contains("timeout"); + var isTimeout = e?.Message.Contains("timeout", StringComparison.OrdinalIgnoreCase) == true; notifier.OnCheckPerformed(new CheckEventArgs($"Failed to generate alias table after {timeout}s", isTimeout ? CheckResult.Warning : CheckResult.Fail, e)); } diff --git a/Rdmp.Core/DataLoad/Modules/Mutilators/Dilution/Operations/IPluginDilutionOperation.cs b/Rdmp.Core/DataLoad/Modules/Mutilators/Dilution/Operations/IPluginDilutionOperation.cs index 19658a8b44..c53bdbdf29 100644 --- a/Rdmp.Core/DataLoad/Modules/Mutilators/Dilution/Operations/IPluginDilutionOperation.cs +++ b/Rdmp.Core/DataLoad/Modules/Mutilators/Dilution/Operations/IPluginDilutionOperation.cs @@ -11,6 +11,4 @@ namespace Rdmp.Core.DataLoad.Modules.Mutilators.Dilution.Operations; /// /// MEF discoverable version of IDilutionOperation /// -public interface IPluginDilutionOperation : IDilutionOperation -{ -} \ No newline at end of file +public interface IPluginDilutionOperation : IDilutionOperation; \ No newline at end of file diff --git a/Rdmp.Core/DataLoad/Modules/Mutilators/RegexRedactionMutilator.cs b/Rdmp.Core/DataLoad/Modules/Mutilators/RegexRedactionMutilator.cs index 525c101060..8770321577 100644 --- a/Rdmp.Core/DataLoad/Modules/Mutilators/RegexRedactionMutilator.cs +++ b/Rdmp.Core/DataLoad/Modules/Mutilators/RegexRedactionMutilator.cs @@ -36,7 +36,9 @@ public class RegexRedactionMutilator : MatchingTablesMutilatorWithDataLoadJob private DiscoveredColumn[] _discoveredPKColumns; - public RegexRedactionMutilator() : base([LoadStage.AdjustRaw, LoadStage.AdjustStaging]) { } + public RegexRedactionMutilator() : base(LoadStage.AdjustRaw, LoadStage.AdjustStaging) + { + } private bool ColumnMatches(DiscoveredColumn column) { @@ -136,15 +138,15 @@ protected override void MutilateTable(IDataLoadJob job, ITableInfo tableInfo, Di pksToSave.Rows[i]["ID"] = i + 1; } - job.OnNotify(this, new NotifyEventArgs(ProgressEventType.Information, $"Creating Temporary tables")); + job.OnNotify(this, new NotifyEventArgs(ProgressEventType.Information, "Creating Temporary tables")); var t1 = table.Database.CreateTable(nameof(RegexRedactionHelper.Constants.pksToSave_Temp), pksToSave); var t2 = table.Database.CreateTable(nameof(RegexRedactionHelper.Constants.redactionsToSaveTable_Temp), redactionsToSaveTable); - job.OnNotify(this, new NotifyEventArgs(ProgressEventType.Information, $"Saving Redactions")); + job.OnNotify(this, new NotifyEventArgs(ProgressEventType.Information, "Saving Redactions")); var server = relatedCatalogues.First().GetDistinctLiveDatabaseServer(DataAccessContext.InternalDataProcessing, false); RegexRedactionHelper.SaveRedactions(job.RepositoryLocator.CatalogueRepository, t1, t2, server, Timeout * 1000); t1.Drop(); t2.Drop(); - job.OnNotify(this, new NotifyEventArgs(ProgressEventType.Information, $"Performing join update")); + job.OnNotify(this, new NotifyEventArgs(ProgressEventType.Information, "Performing join update")); RegexRedactionHelper.DoJoinUpdate(columnInfo, table, table.Database.Server, redactionUpates, _discoveredPKColumns, Timeout * 1000); job.OnNotify(this, new NotifyEventArgs(ProgressEventType.Information, $"Regex Redactions tool found {dt.Rows.Count} redactions.")); } diff --git a/Rdmp.Core/DataLoad/Triggers/Implementations/MicrosoftSQLTriggerImplementer.cs b/Rdmp.Core/DataLoad/Triggers/Implementations/MicrosoftSQLTriggerImplementer.cs index a789af1331..4695c12f23 100644 --- a/Rdmp.Core/DataLoad/Triggers/Implementations/MicrosoftSQLTriggerImplementer.cs +++ b/Rdmp.Core/DataLoad/Triggers/Implementations/MicrosoftSQLTriggerImplementer.cs @@ -244,7 +244,7 @@ private void CreateViewOldVersionsTableValuedFunction(string sqlUsedToCreateArch columnsInArchive = sqlUsedToCreateArchiveTableSQL[startExtractingColumnsAt..]; //trim off excess crud at the end - columnsInArchive = columnsInArchive.Trim(new[] { ')', '\r', '\n' }); + columnsInArchive = columnsInArchive.Trim(')', '\r', '\n'); var sqlToRun = string.Format("CREATE FUNCTION [" + _schema + "].[{0}_Legacy]", QuerySyntaxHelper.MakeHeaderNameSensible(_table.GetRuntimeName())); diff --git a/Rdmp.Core/DataLoad/Triggers/Implementations/TriggerImplementer.cs b/Rdmp.Core/DataLoad/Triggers/Implementations/TriggerImplementer.cs index 9a7852b6a5..256f6e27b0 100644 --- a/Rdmp.Core/DataLoad/Triggers/Implementations/TriggerImplementer.cs +++ b/Rdmp.Core/DataLoad/Triggers/Implementations/TriggerImplementer.cs @@ -21,7 +21,7 @@ namespace Rdmp.Core.DataLoad.Triggers.Implementations; /// Trigger implementer for that creates archive triggers on tables. This is a prerequisite for the RDMP DLE and ensures that /// when updates in a load replace live records the old state is persisted. /// -public abstract class TriggerImplementer : ITriggerImplementer +public abstract partial class TriggerImplementer : ITriggerImplementer { protected readonly bool _createDataLoadRunIdAlso; @@ -144,10 +144,8 @@ private string WorkOutArchiveTableCreationSQL() createTableSQL = createTableSQL.Replace(toReplaceTableName, $"CREATE TABLE {_archiveTable.GetFullyQualifiedName()}"); - var toRemoveIdentities = "IDENTITY\\(\\d+,\\d+\\)"; - //drop identity bit - createTableSQL = Regex.Replace(createTableSQL, toRemoveIdentities, ""); + createTableSQL = RemoveIdentities().Replace(createTableSQL, ""); return createTableSQL; } @@ -206,7 +204,11 @@ private static bool AreCompatibleDatatypes(DiscoveredDataType mainDataType, Disc if (t1.Equals(t2, StringComparison.CurrentCultureIgnoreCase)) return true; - return t1.ToLower().Contains("identity") && - t1.ToLower().Replace("identity", "").Trim().Equals(t2.ToLower().Trim()); + return t1.Contains("identity", StringComparison.OrdinalIgnoreCase) && + t1.Replace("identity", "", StringComparison.OrdinalIgnoreCase).Trim() + .Equals(t2.Trim(), StringComparison.OrdinalIgnoreCase); } + + [GeneratedRegex(@"IDENTITY\(\d+,\d+\)")] + private static partial Regex RemoveIdentities(); } \ No newline at end of file diff --git a/Rdmp.Core/DataQualityEngine/Data/ColumnState.cs b/Rdmp.Core/DataQualityEngine/Data/ColumnState.cs index c3b7003975..d022de9297 100644 --- a/Rdmp.Core/DataQualityEngine/Data/ColumnState.cs +++ b/Rdmp.Core/DataQualityEngine/Data/ColumnState.cs @@ -136,7 +136,7 @@ public void Commit(Evaluation evaluation, string pivotCategory, DbConnection con throw new NotSupportedException("ColumnState was already committed"); var sql = - $"INSERT INTO ColumnState(TargetProperty,DataLoadRunID,Evaluation_ID,CountCorrect,CountDBNull,ItemValidatorXML,CountMissing,CountWrong,CountInvalidatesRow,PivotCategory)VALUES({"@TargetProperty"},{DataLoadRunID},{evaluation.ID},{CountCorrect},{CountDBNull},@ItemValidatorXML,{CountMissing},{CountWrong},{CountInvalidatesRow},@PivotCategory)"; + $"INSERT INTO ColumnState(TargetProperty,DataLoadRunID,Evaluation_ID,CountCorrect,CountDBNull,ItemValidatorXML,CountMissing,CountWrong,CountInvalidatesRow,PivotCategory)VALUES(@TargetProperty,{DataLoadRunID},{evaluation.ID},{CountCorrect},{CountDBNull},@ItemValidatorXML,{CountMissing},{CountWrong},{CountInvalidatesRow},@PivotCategory)"; using (var cmd = DatabaseCommandHelper.GetCommand(sql, con, transaction)) { diff --git a/Rdmp.Core/DataQualityEngine/Data/Evaluation.cs b/Rdmp.Core/DataQualityEngine/Data/Evaluation.cs index 8953ec5cfe..ba030de8bf 100644 --- a/Rdmp.Core/DataQualityEngine/Data/Evaluation.cs +++ b/Rdmp.Core/DataQualityEngine/Data/Evaluation.cs @@ -178,9 +178,9 @@ private void LoadRowAndColumnStates() //get all the column level data - using var cmdGetColumnStates = DatabaseCommandHelper.GetCommand( - $"select * from ColumnState WHERE ColumnState.Evaluation_ID = {ID}", - con.Connection, con.Transaction); + using (var cmdGetColumnStates = DatabaseCommandHelper.GetCommand( + $"select * from ColumnState WHERE ColumnState.Evaluation_ID = {ID}", + con.Connection, con.Transaction)) { using var r2 = cmdGetColumnStates.ExecuteReader(); var colStates = new List(); diff --git a/Rdmp.Core/Logging/DataLoadInfo.cs b/Rdmp.Core/Logging/DataLoadInfo.cs index f3bcce9b67..6aa16dd8b8 100644 --- a/Rdmp.Core/Logging/DataLoadInfo.cs +++ b/Rdmp.Core/Logging/DataLoadInfo.cs @@ -36,7 +36,7 @@ public sealed class DataLoadInfo : IDataLoadInfo public DiscoveredServer DatabaseSettings { get; } - private readonly object _oLock = new(); + private readonly Lock _oLock = new(); private Thread _logThread = null; private BlockingCollection _logQueue = null; private readonly object _logWaiter = new(); diff --git a/Rdmp.Core/MapsDirectlyToDatabaseTable/Attributes/AdjustableLocationAttribute.cs b/Rdmp.Core/MapsDirectlyToDatabaseTable/Attributes/AdjustableLocationAttribute.cs index 02da7b5700..d6720a0037 100644 --- a/Rdmp.Core/MapsDirectlyToDatabaseTable/Attributes/AdjustableLocationAttribute.cs +++ b/Rdmp.Core/MapsDirectlyToDatabaseTable/Attributes/AdjustableLocationAttribute.cs @@ -12,6 +12,4 @@ namespace Rdmp.Core.MapsDirectlyToDatabaseTable.Attributes; /// Used to indicate when a string or Uri property is 'find and replaceable' through the FindAndReplaceUI /// [AttributeUsage(AttributeTargets.Property)] -public class AdjustableLocationAttribute : Attribute -{ -} \ No newline at end of file +public sealed class AdjustableLocationAttribute : Attribute; \ No newline at end of file diff --git a/Rdmp.Core/MapsDirectlyToDatabaseTable/Attributes/RelationshipAttribute.cs b/Rdmp.Core/MapsDirectlyToDatabaseTable/Attributes/RelationshipAttribute.cs index a20b4423cc..23629d5b9d 100644 --- a/Rdmp.Core/MapsDirectlyToDatabaseTable/Attributes/RelationshipAttribute.cs +++ b/Rdmp.Core/MapsDirectlyToDatabaseTable/Attributes/RelationshipAttribute.cs @@ -49,7 +49,7 @@ public RelationshipAttribute(Type cref, RelationshipType type, [CallerMemberName #region Equality Members - protected bool Equals(RelationshipAttribute other) => base.Equals(other) && Equals(Cref, other.Cref) && + protected bool Equals(RelationshipAttribute other) => base.Equals(other) && Cref == other.Cref && string.Equals(PropertyName, other.PropertyName); public override bool Equals(object obj) diff --git a/Rdmp.Core/MapsDirectlyToDatabaseTable/Attributes/UniqueAttribute.cs b/Rdmp.Core/MapsDirectlyToDatabaseTable/Attributes/UniqueAttribute.cs index dcd179d68d..4c33442b26 100644 --- a/Rdmp.Core/MapsDirectlyToDatabaseTable/Attributes/UniqueAttribute.cs +++ b/Rdmp.Core/MapsDirectlyToDatabaseTable/Attributes/UniqueAttribute.cs @@ -14,6 +14,4 @@ namespace Rdmp.Core.MapsDirectlyToDatabaseTable.Attributes; /// on the database level. /// [AttributeUsage(AttributeTargets.Property)] -public class UniqueAttribute : Attribute -{ -} \ No newline at end of file +public class UniqueAttribute : Attribute; \ No newline at end of file diff --git a/Rdmp.Core/MapsDirectlyToDatabaseTable/NewObjectPool.cs b/Rdmp.Core/MapsDirectlyToDatabaseTable/NewObjectPool.cs index 361faae487..4dde085dac 100644 --- a/Rdmp.Core/MapsDirectlyToDatabaseTable/NewObjectPool.cs +++ b/Rdmp.Core/MapsDirectlyToDatabaseTable/NewObjectPool.cs @@ -7,19 +7,20 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Threading; namespace Rdmp.Core.MapsDirectlyToDatabaseTable; public static class NewObjectPool { - private static Scope CurrentScope; - private static object currentScopeLock = new(); + private static Scope _currentScope; + private static readonly Lock currentScopeLock = new(); public static void Add(IMapsDirectlyToDatabaseTable toCreate) { lock (currentScopeLock) { - CurrentScope?.Objects.Add(toCreate); + _currentScope?.Objects.Add(toCreate); } } @@ -37,7 +38,7 @@ public static IMapsDirectlyToDatabaseTable Latest(IEnumerable Objects { get; set; } = new(); diff --git a/Rdmp.Core/MapsDirectlyToDatabaseTable/NoMappingToDatabase.cs b/Rdmp.Core/MapsDirectlyToDatabaseTable/NoMappingToDatabase.cs index d18531f977..0c1c8980c5 100644 --- a/Rdmp.Core/MapsDirectlyToDatabaseTable/NoMappingToDatabase.cs +++ b/Rdmp.Core/MapsDirectlyToDatabaseTable/NoMappingToDatabase.cs @@ -12,6 +12,4 @@ namespace Rdmp.Core.MapsDirectlyToDatabaseTable; /// Used to indicate when a property does not map to an underlying data table /// [AttributeUsage(AttributeTargets.Property)] -public sealed class NoMappingToDatabase : Attribute -{ -} \ No newline at end of file +public sealed class NoMappingToDatabase : Attribute; \ No newline at end of file diff --git a/Rdmp.Core/MapsDirectlyToDatabaseTable/TableRepository.cs b/Rdmp.Core/MapsDirectlyToDatabaseTable/TableRepository.cs index 2cca917114..51602c0ac6 100644 --- a/Rdmp.Core/MapsDirectlyToDatabaseTable/TableRepository.cs +++ b/Rdmp.Core/MapsDirectlyToDatabaseTable/TableRepository.cs @@ -23,7 +23,6 @@ using Rdmp.Core.MapsDirectlyToDatabaseTable.Versioning; using Rdmp.Core.ReusableLibraryCode; using Rdmp.Core.ReusableLibraryCode.DataAccess; -using static Terminal.Gui.MainLoop; namespace Rdmp.Core.MapsDirectlyToDatabaseTable; @@ -36,8 +35,8 @@ public abstract class TableRepository : ITableRepository protected DbConnectionStringBuilder _connectionStringBuilder; public IObscureDependencyFinder ObscureDependencyFinder { get; set; } - private static object _oLockUpdateCommands = new(); - private UpdateCommandStore _updateCommandStore = new(); + private static readonly Lock OLockUpdateCommands = new(); + private readonly UpdateCommandStore _updateCommandStore = new(); public bool SupportsCommits => true; //'accessors' @@ -77,7 +76,7 @@ public void DeleteFromDatabase(IMapsDirectlyToDatabaseTable oTableWrapperObject) _logger.Debug( $"Deleted,{oTableWrapperObject.GetType().Name},{oTableWrapperObject.ID},{oTableWrapperObject}"); - lock (_oLockUpdateCommands) + lock (OLockUpdateCommands) { //if the repository has obscure dependencies ObscureDependencyFinder @@ -131,7 +130,7 @@ public void SaveToDatabase(IMapsDirectlyToDatabaseTable oTableWrapperObject) _logger.Debug( $"Save,{oTableWrapperObject.GetType().Name},{oTableWrapperObject.ID},{c.Property},{c.DatabaseValue},{c.LocalValue}"); - lock (_oLockUpdateCommands) + lock (OLockUpdateCommands) { using var managedConnection = GetConnection(); var cmd = GetUpdateCommandFromStore(oTableWrapperObject.GetType(), managedConnection); @@ -667,9 +666,9 @@ public void InsertAndHydrate(T toCreate, Dictionary construct Inserting?.Invoke(this, new IMapsDirectlyToDatabaseTableEventArgs(toCreate)); } - private object ongoingConnectionsLock = new(); - private readonly Dictionary ongoingConnections = new(); - private readonly Dictionary ongoingTransactions = new(); + private readonly Lock _ongoingConnectionsLock = new(); + private readonly Dictionary _ongoingConnections = new(); + private readonly Dictionary _ongoingTransactions = new(); public IManagedConnection GetConnection() @@ -695,7 +694,7 @@ public IManagedConnection GetConnection() ongoingConnection = DiscoveredServer.GetManagedConnection(ongoingTransaction); //record as the active connection on this thread - ongoingConnections[Thread.CurrentThread] = ongoingConnection; + _ongoingConnections[Thread.CurrentThread] = ongoingConnection; return ongoingConnection; } @@ -703,15 +702,15 @@ public IManagedConnection GetConnection() private void GetOngoingActivitiesFromThreadsDictionary(out IManagedConnection ongoingConnection, out IManagedTransaction ongoingTransaction) { - lock (ongoingConnectionsLock) + lock (_ongoingConnectionsLock) { //see if Thread dictionary has it - if (!ongoingConnections.TryGetValue(Thread.CurrentThread, out ongoingConnection)) - ongoingConnections.Add(Thread.CurrentThread, null); + if (!_ongoingConnections.TryGetValue(Thread.CurrentThread, out ongoingConnection)) + _ongoingConnections.Add(Thread.CurrentThread, null); //see if Thread dictionary has it - if (!ongoingTransactions.TryGetValue(Thread.CurrentThread, out ongoingTransaction)) - ongoingTransactions.Add(Thread.CurrentThread, null); + if (!_ongoingTransactions.TryGetValue(Thread.CurrentThread, out ongoingTransaction)) + _ongoingTransactions.Add(Thread.CurrentThread, null); } } @@ -725,9 +724,9 @@ public IManagedConnection BeginNewTransactedConnection() var toReturn = DiscoveredServer.BeginNewTransactedConnection(); ongoingTransaction = toReturn.ManagedTransaction; - ongoingTransactions[Thread.CurrentThread] = ongoingTransaction; + _ongoingTransactions[Thread.CurrentThread] = ongoingTransaction; - ongoingConnections[Thread.CurrentThread] = toReturn; + _ongoingConnections[Thread.CurrentThread] = toReturn; if (DiscoveredServer.DatabaseType == DatabaseType.MicrosoftSQLServer) { using var cmd = toReturn.Connection.CreateCommand(); @@ -756,14 +755,14 @@ public void EndTransactedConnection(bool commit) else ongoingTransaction.AbandonAndCloseConnection(); - ongoingConnections[Thread.CurrentThread] = null; - ongoingTransactions[Thread.CurrentThread] = null; + _ongoingConnections[Thread.CurrentThread] = null; + _ongoingTransactions[Thread.CurrentThread] = null; } public void ClearUpdateCommandCache() { - lock (_oLockUpdateCommands) + lock (OLockUpdateCommands) { _updateCommandStore.Clear(); } @@ -773,8 +772,8 @@ public void ClearUpdateCommandCache() public DateTime? ObjectToNullableDateTime(object o) => o == null || o == DBNull.Value ? null : (DateTime)o; - private Dictionary _knownSupportedTypes = new(); - private object oLockKnownTypes = new(); + private readonly Dictionary _knownSupportedTypes = new(); + private readonly Lock _oLockKnownTypes = new(); public bool SupportsObjectType(Type type) { @@ -782,7 +781,7 @@ public bool SupportsObjectType(Type type) throw new NotSupportedException( "This method can only be passed Types derived from IMapsDirectlyToDatabaseTable"); - lock (oLockKnownTypes) + lock (_oLockKnownTypes) { if (!_knownSupportedTypes.ContainsKey(type)) _knownSupportedTypes.Add(type, DiscoveredServer.GetCurrentDatabase().ExpectTable(type.Name).Exists()); diff --git a/Rdmp.Core/Providers/CatalogueChildProvider.cs b/Rdmp.Core/Providers/CatalogueChildProvider.cs index 16ae2f55ee..0479472bea 100644 --- a/Rdmp.Core/Providers/CatalogueChildProvider.cs +++ b/Rdmp.Core/Providers/CatalogueChildProvider.cs @@ -53,1916 +53,1916 @@ namespace Rdmp.Core.Providers; /// public class CatalogueChildProvider : ICoreChildProvider { - //Load System - public LoadMetadata[] AllLoadMetadatas { get; set; } + //Load System + public LoadMetadata[] AllLoadMetadatas { get; set; } - private LoadMetadataCatalogueLinkage[] AllLoadMetadataLinkage { get; set; } - public ProcessTask[] AllProcessTasks { get; set; } - public ProcessTaskArgument[] AllProcessTasksArguments { get; set; } + private LoadMetadataCatalogueLinkage[] AllLoadMetadataLinkage { get; set; } + public ProcessTask[] AllProcessTasks { get; set; } + public ProcessTaskArgument[] AllProcessTasksArguments { get; set; } - public LoadProgress[] AllLoadProgresses { get; set; } - public CacheProgress[] AllCacheProgresses { get; set; } - public PermissionWindow[] AllPermissionWindows { get; set; } + public LoadProgress[] AllLoadProgresses { get; set; } + public CacheProgress[] AllCacheProgresses { get; set; } + public PermissionWindow[] AllPermissionWindows { get; set; } - //Catalogue side of things - public Catalogue[] AllCatalogues { get; set; } - public Curation.Data.Dataset[] AllDatasets { get; set; } - public Dictionary AllCataloguesDictionary { get; private set; } + //Catalogue side of things + public Catalogue[] AllCatalogues { get; set; } + public Curation.Data.Dataset[] AllDatasets { get; set; } + public Dictionary AllCataloguesDictionary { get; private set; } - public SupportingDocument[] AllSupportingDocuments { get; set; } - public SupportingSQLTable[] AllSupportingSQL { get; set; } + public SupportingDocument[] AllSupportingDocuments { get; set; } + public SupportingSQLTable[] AllSupportingSQL { get; set; } - //tells you the immediate children of a given node. Do not add to this directly instead add using AddToDictionaries unless you want the Key to be an 'on the sly' no known descendency child - private ConcurrentDictionary> _childDictionary = new(); + //tells you the immediate children of a given node. Do not add to this directly instead add using AddToDictionaries unless you want the Key to be an 'on the sly' no known descendency child + private ConcurrentDictionary> _childDictionary = new(); - //This is the reverse of _childDictionary in some ways. _childDictionary tells you the immediate children while - //this tells you for a given child object what the navigation tree down to get to it is e.g. ascendancy[child] would return [root,grandParent,parent] - private ConcurrentDictionary _descendancyDictionary = new(); + //This is the reverse of _childDictionary in some ways. _childDictionary tells you the immediate children while + //this tells you for a given child object what the navigation tree down to get to it is e.g. ascendancy[child] would return [root,grandParent,parent] + private ConcurrentDictionary _descendancyDictionary = new(); - public IEnumerable AllCatalogueItems => AllCatalogueItemsDictionary.Values; + public IEnumerable AllCatalogueItems => AllCatalogueItemsDictionary.Values; - private Dictionary> _catalogueToCatalogueItems; - public Dictionary AllCatalogueItemsDictionary { get; private set; } + private Dictionary> _catalogueToCatalogueItems; + public Dictionary AllCatalogueItemsDictionary { get; private set; } - private Dictionary _allColumnInfos; + private Dictionary _allColumnInfos; - public AggregateConfiguration[] AllAggregateConfigurations { get; private set; } - public AggregateDimension[] AllAggregateDimensions { get; private set; } + public AggregateConfiguration[] AllAggregateConfigurations { get; private set; } + public AggregateDimension[] AllAggregateDimensions { get; private set; } - public AggregateContinuousDateAxis[] AllAggregateContinuousDateAxis { get; private set; } + public AggregateContinuousDateAxis[] AllAggregateContinuousDateAxis { get; private set; } - public AllRDMPRemotesNode AllRDMPRemotesNode { get; private set; } - public RemoteRDMP[] AllRemoteRDMPs { get; set; } + public AllRDMPRemotesNode AllRDMPRemotesNode { get; private set; } + public RemoteRDMP[] AllRemoteRDMPs { get; set; } - public AllDashboardsNode AllDashboardsNode { get; set; } - public DashboardLayout[] AllDashboards { get; set; } + public AllDashboardsNode AllDashboardsNode { get; set; } + public DashboardLayout[] AllDashboards { get; set; } - public AllObjectSharingNode AllObjectSharingNode { get; private set; } - public ObjectImport[] AllImports { get; set; } - public ObjectExport[] AllExports { get; set; } + public AllObjectSharingNode AllObjectSharingNode { get; private set; } + public ObjectImport[] AllImports { get; set; } + public ObjectExport[] AllExports { get; set; } - public AllStandardRegexesNode AllStandardRegexesNode { get; private set; } - public AllPipelinesNode AllPipelinesNode { get; private set; } - public OtherPipelinesNode OtherPipelinesNode { get; private set; } - public Pipeline[] AllPipelines { get; set; } - public PipelineComponent[] AllPipelineComponents { get; set; } + public AllStandardRegexesNode AllStandardRegexesNode { get; private set; } + public AllPipelinesNode AllPipelinesNode { get; private set; } + public OtherPipelinesNode OtherPipelinesNode { get; private set; } + public Pipeline[] AllPipelines { get; set; } + public PipelineComponent[] AllPipelineComponents { get; set; } - public PipelineComponentArgument[] AllPipelineComponentsArguments { get; set; } + public PipelineComponentArgument[] AllPipelineComponentsArguments { get; set; } - public StandardRegex[] AllStandardRegexes { get; set; } + public StandardRegex[] AllStandardRegexes { get; set; } - //TableInfo side of things - public AllANOTablesNode AllANOTablesNode { get; private set; } - public ANOTable[] AllANOTables { get; set; } + //TableInfo side of things + public AllANOTablesNode AllANOTablesNode { get; private set; } + public ANOTable[] AllANOTables { get; set; } - public ExternalDatabaseServer[] AllExternalServers { get; private set; } - public TableInfoServerNode[] AllServers { get; private set; } - public TableInfo[] AllTableInfos { get; private set; } + public ExternalDatabaseServer[] AllExternalServers { get; private set; } + public TableInfoServerNode[] AllServers { get; private set; } + public TableInfo[] AllTableInfos { get; private set; } - public AllDataAccessCredentialsNode AllDataAccessCredentialsNode { get; set; } + public AllDataAccessCredentialsNode AllDataAccessCredentialsNode { get; set; } - public AllExternalServersNode AllExternalServersNode { get; private set; } - public AllServersNode AllServersNode { get; private set; } + public AllExternalServersNode AllExternalServersNode { get; private set; } + public AllServersNode AllServersNode { get; private set; } - public DataAccessCredentials[] AllDataAccessCredentials { get; set; } - public Dictionary> AllDataAccessCredentialUsages { get; set; } + public DataAccessCredentials[] AllDataAccessCredentials { get; set; } + public Dictionary> AllDataAccessCredentialUsages { get; set; } - public Dictionary> TableInfosToColumnInfos { get; private set; } - public ColumnInfo[] AllColumnInfos { get; private set; } - public PreLoadDiscardedColumn[] AllPreLoadDiscardedColumns { get; private set; } + public Dictionary> TableInfosToColumnInfos { get; private set; } + public ColumnInfo[] AllColumnInfos { get; private set; } + public PreLoadDiscardedColumn[] AllPreLoadDiscardedColumns { get; private set; } - public Lookup[] AllLookups { get; set; } + public Lookup[] AllLookups { get; set; } - public JoinInfo[] AllJoinInfos { get; set; } + public JoinInfo[] AllJoinInfos { get; set; } - public AnyTableSqlParameter[] AllAnyTableParameters; + public AnyTableSqlParameter[] AllAnyTableParameters; - //Filter / extraction side of things - public IEnumerable AllExtractionInformations => AllExtractionInformationsDictionary.Values; + //Filter / extraction side of things + public IEnumerable AllExtractionInformations => AllExtractionInformationsDictionary.Values; - public AllPermissionWindowsNode AllPermissionWindowsNode { get; set; } - public FolderNode LoadMetadataRootFolder { get; set; } + public AllPermissionWindowsNode AllPermissionWindowsNode { get; set; } + public FolderNode LoadMetadataRootFolder { get; set; } - public FolderNode DatasetRootFolder { get; set; } - public FolderNode CohortIdentificationConfigurationRootFolder { get; set; } - public FolderNode CohortIdentificationConfigurationRootFolderWithoutVersionedConfigurations { get; set; } + public FolderNode DatasetRootFolder { get; set; } + public FolderNode CohortIdentificationConfigurationRootFolder { get; set; } + public FolderNode CohortIdentificationConfigurationRootFolderWithoutVersionedConfigurations { get; set; } - public AllConnectionStringKeywordsNode AllConnectionStringKeywordsNode { get; set; } - public ConnectionStringKeyword[] AllConnectionStringKeywords { get; set; } + public AllConnectionStringKeywordsNode AllConnectionStringKeywordsNode { get; set; } + public ConnectionStringKeyword[] AllConnectionStringKeywords { get; set; } - public Dictionary AllExtractionInformationsDictionary { get; private set; } - protected Dictionary _extractionInformationsByCatalogueItem; + public Dictionary AllExtractionInformationsDictionary { get; private set; } + protected Dictionary _extractionInformationsByCatalogueItem; - private IFilterManager _aggregateFilterManager; + private IFilterManager _aggregateFilterManager; - //Filters for Aggregates (includes filter containers (AND/OR) - public Dictionary AllAggregateContainersDictionary { get; private set; } - public AggregateFilterContainer[] AllAggregateContainers => AllAggregateContainersDictionary.Values.ToArray(); + //Filters for Aggregates (includes filter containers (AND/OR) + public Dictionary AllAggregateContainersDictionary { get; private set; } + public AggregateFilterContainer[] AllAggregateContainers => AllAggregateContainersDictionary.Values.ToArray(); - public AggregateFilter[] AllAggregateFilters { get; private set; } - public AggregateFilterParameter[] AllAggregateFilterParameters { get; private set; } + public AggregateFilter[] AllAggregateFilters { get; private set; } + public AggregateFilterParameter[] AllAggregateFilterParameters { get; private set; } - //Catalogue master filters (does not include any support for filter containers (AND/OR) - private ExtractionFilter[] AllCatalogueFilters; - public ExtractionFilterParameter[] AllCatalogueParameters; - public ExtractionFilterParameterSet[] AllCatalogueValueSets; - public ExtractionFilterParameterSetValue[] AllCatalogueValueSetValues; + //Catalogue master filters (does not include any support for filter containers (AND/OR) + private ExtractionFilter[] AllCatalogueFilters; + public ExtractionFilterParameter[] AllCatalogueParameters; + public ExtractionFilterParameterSet[] AllCatalogueValueSets; + public ExtractionFilterParameterSetValue[] AllCatalogueValueSetValues; - private ICohortContainerManager _cohortContainerManager; + private ICohortContainerManager _cohortContainerManager; - public CohortIdentificationConfiguration[] AllCohortIdentificationConfigurations { get; private set; } - public CohortAggregateContainer[] AllCohortAggregateContainers { get; set; } - public JoinableCohortAggregateConfiguration[] AllJoinables { get; set; } - public JoinableCohortAggregateConfigurationUse[] AllJoinUses { get; set; } + public CohortIdentificationConfiguration[] AllCohortIdentificationConfigurations { get; private set; } + public CohortAggregateContainer[] AllCohortAggregateContainers { get; set; } + public JoinableCohortAggregateConfiguration[] AllJoinables { get; set; } + public JoinableCohortAggregateConfigurationUse[] AllJoinUses { get; set; } - /// - /// Collection of all objects for which there are masqueraders - /// - public ConcurrentDictionary> AllMasqueraders { get; private set; } + /// + /// Collection of all objects for which there are masqueraders + /// + public ConcurrentDictionary> AllMasqueraders { get; private set; } - private IChildProvider[] _pluginChildProviders; - private readonly ICatalogueRepository _catalogueRepository; - private readonly ICheckNotifier _errorsCheckNotifier; - private readonly List _blockedPlugins = new(); + private IChildProvider[] _pluginChildProviders; + private readonly ICatalogueRepository _catalogueRepository; + private readonly ICheckNotifier _errorsCheckNotifier; + private readonly List _blockedPlugins = new(); - public AllGovernanceNode AllGovernanceNode { get; private set; } - public GovernancePeriod[] AllGovernancePeriods { get; private set; } - public GovernanceDocument[] AllGovernanceDocuments { get; private set; } - public Dictionary> GovernanceCoverage { get; private set; } + public AllGovernanceNode AllGovernanceNode { get; private set; } + public GovernancePeriod[] AllGovernancePeriods { get; private set; } + public GovernanceDocument[] AllGovernanceDocuments { get; private set; } + public Dictionary> GovernanceCoverage { get; private set; } - private CommentStore _commentStore; + private CommentStore _commentStore; - public JoinableCohortAggregateConfigurationUse[] AllJoinableCohortAggregateConfigurationUse { get; private set; } - public AllPluginsNode AllPluginsNode { get; private set; } - public HashSet PipelineUseCases { get; set; } = new(); + public JoinableCohortAggregateConfigurationUse[] AllJoinableCohortAggregateConfigurationUse { get; private set; } + public AllPluginsNode AllPluginsNode { get; private set; } + public HashSet PipelineUseCases { get; set; } = new(); - /// - /// Lock for changes to Child provider - /// - protected object WriteLock = new(); + /// + /// Lock for changes to Child provider + /// + protected object WriteLock = new(); - public AllOrphanAggregateConfigurationsNode OrphanAggregateConfigurationsNode { get; set; } = new(); - public AllTemplateAggregateConfigurationsNode TemplateAggregateConfigurationsNode { get; set; } = new(); - public FolderNode CatalogueRootFolder { get; private set; } + public AllOrphanAggregateConfigurationsNode OrphanAggregateConfigurationsNode { get; set; } = new(); + public AllTemplateAggregateConfigurationsNode TemplateAggregateConfigurationsNode { get; set; } = new(); + public FolderNode CatalogueRootFolder { get; private set; } - public AllDatasetsNode AllDatasetsNode { get; set; } + public AllDatasetsNode AllDatasetsNode { get; set; } - public RegexRedactionConfiguration[] AllRegexRedactionConfigurations { get; set; } - public AllRegexRedactionConfigurationsNode AllRegexRedactionConfigurationsNode { get; set; } + public RegexRedactionConfiguration[] AllRegexRedactionConfigurations { get; set; } + public AllRegexRedactionConfigurationsNode AllRegexRedactionConfigurationsNode { get; set; } - public HashSet OrphanAggregateConfigurations; - public AggregateConfiguration[] TemplateAggregateConfigurations; + public HashSet OrphanAggregateConfigurations; + public AggregateConfiguration[] TemplateAggregateConfigurations; - protected Stopwatch ProgressStopwatch = Stopwatch.StartNew(); - private int _progress; + protected Stopwatch ProgressStopwatch = Stopwatch.StartNew(); + private int _progress; - /// - /// - /// - /// - /// - /// Where to report errors building the hierarchy e.g. when crash. Set to null for - /// Previous child provider state if you know it otherwise null - public CatalogueChildProvider(ICatalogueRepository repository, IChildProvider[] pluginChildProviders, - ICheckNotifier errorsCheckNotifier, CatalogueChildProvider previousStateIfKnown) - { - _commentStore = repository.CommentStore; - _catalogueRepository = repository; - _catalogueRepository?.EncryptionManager?.ClearAllInjections(); + /// + /// + /// + /// + /// + /// Where to report errors building the hierarchy e.g. when crash. Set to null for + /// Previous child provider state if you know it otherwise null + public CatalogueChildProvider(ICatalogueRepository repository, IChildProvider[] pluginChildProviders, + ICheckNotifier errorsCheckNotifier, CatalogueChildProvider previousStateIfKnown) + { + _commentStore = repository.CommentStore; + _catalogueRepository = repository; + _catalogueRepository?.EncryptionManager?.ClearAllInjections(); - _errorsCheckNotifier = errorsCheckNotifier ?? IgnoreAllErrorsCheckNotifier.Instance; + _errorsCheckNotifier = errorsCheckNotifier ?? IgnoreAllErrorsCheckNotifier.Instance; - if (UserSettings.DebugPerformance) - _errorsCheckNotifier.OnCheckPerformed(new CheckEventArgs( - $"Refresh generated by:{Environment.NewLine}{Environment.StackTrace}", CheckResult.Success)); + if (UserSettings.DebugPerformance) + _errorsCheckNotifier.OnCheckPerformed(new CheckEventArgs( + $"Refresh generated by:{Environment.NewLine}{Environment.StackTrace}", CheckResult.Success)); - // all the objects which are - AllMasqueraders = new ConcurrentDictionary>(); + // all the objects which are + AllMasqueraders = new ConcurrentDictionary>(); - _pluginChildProviders = pluginChildProviders ?? Array.Empty(); + _pluginChildProviders = pluginChildProviders ?? Array.Empty(); - ReportProgress("Before object fetches"); + ReportProgress("Before object fetches"); - AllAnyTableParameters = GetAllObjects(repository); + AllAnyTableParameters = GetAllObjects(repository); - AllANOTables = GetAllObjects(repository); - AllANOTablesNode = new AllANOTablesNode(); - AddChildren(AllANOTablesNode); + AllANOTables = GetAllObjects(repository); + AllANOTablesNode = new AllANOTablesNode(); + AddChildren(AllANOTablesNode); - AllCatalogues = GetAllObjects(repository); - AllCataloguesDictionary = AllCatalogues.ToDictionaryEx(i => i.ID, o => o); + AllCatalogues = GetAllObjects(repository); + AllCataloguesDictionary = AllCatalogues.ToDictionaryEx(i => i.ID, o => o); - AllDatasets = GetAllObjects(repository); + AllDatasets = GetAllObjects(repository); - AllLoadMetadatas = GetAllObjects(repository); - AllLoadMetadataLinkage = GetAllObjects(repository); - AllProcessTasks = GetAllObjects(repository); - AllProcessTasksArguments = GetAllObjects(repository); - AllLoadProgresses = GetAllObjects(repository); - AllCacheProgresses = GetAllObjects(repository); + AllLoadMetadatas = GetAllObjects(repository); + AllLoadMetadataLinkage = GetAllObjects(repository); + AllProcessTasks = GetAllObjects(repository); + AllProcessTasksArguments = GetAllObjects(repository); + AllLoadProgresses = GetAllObjects(repository); + AllCacheProgresses = GetAllObjects(repository); - AllPermissionWindows = GetAllObjects(repository); - AllPermissionWindowsNode = new AllPermissionWindowsNode(); - AddChildren(AllPermissionWindowsNode); + AllPermissionWindows = GetAllObjects(repository); + AllPermissionWindowsNode = new AllPermissionWindowsNode(); + AddChildren(AllPermissionWindowsNode); - AllRemoteRDMPs = GetAllObjects(repository); + AllRemoteRDMPs = GetAllObjects(repository); - AllExternalServers = GetAllObjects(repository); + AllExternalServers = GetAllObjects(repository); - AllTableInfos = GetAllObjects(repository); - AllDataAccessCredentials = GetAllObjects(repository); - AllDataAccessCredentialsNode = new AllDataAccessCredentialsNode(); - AddChildren(AllDataAccessCredentialsNode); + AllTableInfos = GetAllObjects(repository); + AllDataAccessCredentials = GetAllObjects(repository); + AllDataAccessCredentialsNode = new AllDataAccessCredentialsNode(); + AddChildren(AllDataAccessCredentialsNode); - AllConnectionStringKeywordsNode = new AllConnectionStringKeywordsNode(); - AllConnectionStringKeywords = GetAllObjects(repository).ToArray(); - AddToDictionaries(new HashSet(AllConnectionStringKeywords), - new DescendancyList(AllConnectionStringKeywordsNode)); + AllConnectionStringKeywordsNode = new AllConnectionStringKeywordsNode(); + AllConnectionStringKeywords = GetAllObjects(repository).ToArray(); + AddToDictionaries(new HashSet(AllConnectionStringKeywords), + new DescendancyList(AllConnectionStringKeywordsNode)); - ReportProgress("after basic object fetches"); + ReportProgress("after basic object fetches"); - Task.WaitAll( - //which TableInfos use which Credentials under which DataAccessContexts - Task.Factory.StartNew(() => - { - AllDataAccessCredentialUsages = - repository.TableInfoCredentialsManager.GetAllCredentialUsagesBy(AllDataAccessCredentials, - AllTableInfos); - }), - Task.Factory.StartNew(() => { AllColumnInfos = GetAllObjects(repository); }) - ); + Task.WaitAll( + //which TableInfos use which Credentials under which DataAccessContexts + Task.Factory.StartNew(() => + { + AllDataAccessCredentialUsages = + repository.TableInfoCredentialsManager.GetAllCredentialUsagesBy(AllDataAccessCredentials, + AllTableInfos); + }), + Task.Factory.StartNew(() => { AllColumnInfos = GetAllObjects(repository); }) + ); - ReportProgress("After credentials"); + ReportProgress("After credentials"); - TableInfosToColumnInfos = AllColumnInfos.GroupBy(c => c.TableInfo_ID) - .ToDictionaryEx(gdc => gdc.Key, gdc => gdc.ToList()); + TableInfosToColumnInfos = AllColumnInfos.GroupBy(c => c.TableInfo_ID) + .ToDictionaryEx(gdc => gdc.Key, gdc => gdc.ToList()); - ReportProgress("After TableInfo to ColumnInfo mapping"); + ReportProgress("After TableInfo to ColumnInfo mapping"); - AllPreLoadDiscardedColumns = GetAllObjects(repository); + AllPreLoadDiscardedColumns = GetAllObjects(repository); - AllSupportingDocuments = GetAllObjects(repository); - AllSupportingSQL = GetAllObjects(repository); + AllSupportingDocuments = GetAllObjects(repository); + AllSupportingSQL = GetAllObjects(repository); - AllCohortIdentificationConfigurations = GetAllObjects(repository); + AllCohortIdentificationConfigurations = GetAllObjects(repository); - FetchCatalogueItems(); + FetchCatalogueItems(); - ReportProgress("After CatalogueItem injection"); + ReportProgress("After CatalogueItem injection"); - FetchExtractionInformations(); + FetchExtractionInformations(); - ReportProgress("After ExtractionInformation injection"); + ReportProgress("After ExtractionInformation injection"); - BuildAggregateConfigurations(); + BuildAggregateConfigurations(); - BuildCohortCohortAggregateContainers(); + BuildCohortCohortAggregateContainers(); - AllJoinables = GetAllObjects(repository); - AllJoinUses = GetAllObjects(repository); + AllJoinables = GetAllObjects(repository); + AllJoinUses = GetAllObjects(repository); - AllCatalogueFilters = GetAllObjects(repository); - AllCatalogueParameters = GetAllObjects(repository); - AllCatalogueValueSets = GetAllObjects(repository); - AllCatalogueValueSetValues = GetAllObjects(repository); + AllCatalogueFilters = GetAllObjects(repository); + AllCatalogueParameters = GetAllObjects(repository); + AllCatalogueValueSets = GetAllObjects(repository); + AllCatalogueValueSetValues = GetAllObjects(repository); - ReportProgress("After Filter and Joinable fetching"); + ReportProgress("After Filter and Joinable fetching"); - AllLookups = GetAllObjects(repository); + AllLookups = GetAllObjects(repository); - foreach (var l in AllLookups) - l.SetKnownColumns(_allColumnInfos[l.PrimaryKey_ID], _allColumnInfos[l.ForeignKey_ID], - _allColumnInfos[l.Description_ID]); + foreach (var l in AllLookups) + l.SetKnownColumns(_allColumnInfos[l.PrimaryKey_ID], _allColumnInfos[l.ForeignKey_ID], + _allColumnInfos[l.Description_ID]); - AllJoinInfos = repository.GetAllObjects(); + AllJoinInfos = repository.GetAllObjects(); - foreach (var j in AllJoinInfos) - j.SetKnownColumns(_allColumnInfos[j.PrimaryKey_ID], _allColumnInfos[j.ForeignKey_ID]); + foreach (var j in AllJoinInfos) + j.SetKnownColumns(_allColumnInfos[j.PrimaryKey_ID], _allColumnInfos[j.ForeignKey_ID]); - ReportProgress("After SetKnownColumns"); + ReportProgress("After SetKnownColumns"); - AllExternalServersNode = new AllExternalServersNode(); - AddChildren(AllExternalServersNode); + AllExternalServersNode = new AllExternalServersNode(); + AddChildren(AllExternalServersNode); - AllRDMPRemotesNode = new AllRDMPRemotesNode(); - AddChildren(AllRDMPRemotesNode); + AllRDMPRemotesNode = new AllRDMPRemotesNode(); + AddChildren(AllRDMPRemotesNode); - AllDashboardsNode = new AllDashboardsNode(); - AllDashboards = GetAllObjects(repository); - AddChildren(AllDashboardsNode); + AllDashboardsNode = new AllDashboardsNode(); + AllDashboards = GetAllObjects(repository); + AddChildren(AllDashboardsNode); - AllObjectSharingNode = new AllObjectSharingNode(); - AllExports = GetAllObjects(repository); - AllImports = GetAllObjects(repository); + AllObjectSharingNode = new AllObjectSharingNode(); + AllExports = GetAllObjects(repository); + AllImports = GetAllObjects(repository); - AddChildren(AllObjectSharingNode); + AddChildren(AllObjectSharingNode); - ReportProgress("After Object Sharing discovery"); + ReportProgress("After Object Sharing discovery"); - //Pipelines setup (see also DataExportChildProvider for calls to AddPipelineUseCases) - //Root node for all pipelines - AllPipelinesNode = new AllPipelinesNode(); + //Pipelines setup (see also DataExportChildProvider for calls to AddPipelineUseCases) + //Root node for all pipelines + AllPipelinesNode = new AllPipelinesNode(); - //Pipelines not found to be part of any use case after AddPipelineUseCases - OtherPipelinesNode = new OtherPipelinesNode(); - AllPipelines = GetAllObjects(repository); - AllPipelineComponents = GetAllObjects(repository); - AllPipelineComponentsArguments = GetAllObjects(repository); + //Pipelines not found to be part of any use case after AddPipelineUseCases + OtherPipelinesNode = new OtherPipelinesNode(); + AllPipelines = GetAllObjects(repository); + AllPipelineComponents = GetAllObjects(repository); + AllPipelineComponentsArguments = GetAllObjects(repository); - foreach (var p in AllPipelines) - p.InjectKnown(AllPipelineComponents.Where(pc => pc.Pipeline_ID == p.ID).ToArray()); + foreach (var p in AllPipelines) + p.InjectKnown(AllPipelineComponents.Where(pc => pc.Pipeline_ID == p.ID).ToArray()); - AllStandardRegexesNode = new AllStandardRegexesNode(); - AllStandardRegexes = GetAllObjects(repository); - AddToDictionaries(new HashSet(AllStandardRegexes), new DescendancyList(AllStandardRegexesNode)); + AllStandardRegexesNode = new AllStandardRegexesNode(); + AllStandardRegexes = GetAllObjects(repository); + AddToDictionaries(new HashSet(AllStandardRegexes), new DescendancyList(AllStandardRegexesNode)); - ReportProgress("After Pipelines setup"); + ReportProgress("After Pipelines setup"); - //All the things for TableInfoCollectionUI - BuildServerNodes(); + //All the things for TableInfoCollectionUI + BuildServerNodes(); - ReportProgress("BuildServerNodes"); + ReportProgress("BuildServerNodes"); - //add a new CatalogueItemNodes - InjectCatalogueItems(); + //add a new CatalogueItemNodes + InjectCatalogueItems(); - CatalogueRootFolder = FolderHelper.BuildFolderTree(AllCatalogues); - AddChildren(CatalogueRootFolder, new DescendancyList(CatalogueRootFolder)); + CatalogueRootFolder = FolderHelper.BuildFolderTree(AllCatalogues); + AddChildren(CatalogueRootFolder, new DescendancyList(CatalogueRootFolder)); - DatasetRootFolder = FolderHelper.BuildFolderTree(AllDatasets); - AddChildren(DatasetRootFolder, new DescendancyList(DatasetRootFolder)); + DatasetRootFolder = FolderHelper.BuildFolderTree(AllDatasets); + AddChildren(DatasetRootFolder, new DescendancyList(DatasetRootFolder)); - ReportProgress("Build Catalogue Folder Root"); + ReportProgress("Build Catalogue Folder Root"); - LoadMetadataRootFolder = FolderHelper.BuildFolderTree(AllLoadMetadatas.Where(lmd => lmd.RootLoadMetadata_ID is null).ToArray()); - AddChildren(LoadMetadataRootFolder, new DescendancyList(LoadMetadataRootFolder)); + LoadMetadataRootFolder = FolderHelper.BuildFolderTree(AllLoadMetadatas.Where(lmd => lmd.RootLoadMetadata_ID is null).ToArray()); + AddChildren(LoadMetadataRootFolder, new DescendancyList(LoadMetadataRootFolder)); - CohortIdentificationConfigurationRootFolder = - FolderHelper.BuildFolderTree(AllCohortIdentificationConfigurations); - AddChildren(CohortIdentificationConfigurationRootFolder, - new DescendancyList(CohortIdentificationConfigurationRootFolder)); + CohortIdentificationConfigurationRootFolder = + FolderHelper.BuildFolderTree(AllCohortIdentificationConfigurations); + AddChildren(CohortIdentificationConfigurationRootFolder, + new DescendancyList(CohortIdentificationConfigurationRootFolder)); - CohortIdentificationConfigurationRootFolderWithoutVersionedConfigurations = FolderHelper.BuildFolderTree(AllCohortIdentificationConfigurations.Where(cic => cic.Version is null).ToArray()); - AddChildren(CohortIdentificationConfigurationRootFolderWithoutVersionedConfigurations, - new DescendancyList(CohortIdentificationConfigurationRootFolderWithoutVersionedConfigurations)); - var templateAggregateConfigurationIds = - new HashSet( - repository.GetExtendedProperties(ExtendedProperty.IsTemplate) - .Where(p => p.ReferencedObjectType.Equals(nameof(AggregateConfiguration))) - .Select(r => r.ReferencedObjectID)); + CohortIdentificationConfigurationRootFolderWithoutVersionedConfigurations = FolderHelper.BuildFolderTree(AllCohortIdentificationConfigurations.Where(cic => cic.Version is null).ToArray()); + AddChildren(CohortIdentificationConfigurationRootFolderWithoutVersionedConfigurations, + new DescendancyList(CohortIdentificationConfigurationRootFolderWithoutVersionedConfigurations)); + var templateAggregateConfigurationIds = + new HashSet( + repository.GetExtendedProperties(ExtendedProperty.IsTemplate) + .Where(p => p.ReferencedObjectType.Equals(nameof(AggregateConfiguration))) + .Select(r => r.ReferencedObjectID)); - TemplateAggregateConfigurations = AllAggregateConfigurations - .Where(ac => templateAggregateConfigurationIds.Contains(ac.ID)).ToArray(); + TemplateAggregateConfigurations = AllAggregateConfigurations + .Where(ac => templateAggregateConfigurationIds.Contains(ac.ID)).ToArray(); - //add the orphans under the orphan folder - AddToDictionaries(new HashSet(OrphanAggregateConfigurations), - new DescendancyList(OrphanAggregateConfigurationsNode)); + //add the orphans under the orphan folder + AddToDictionaries(new HashSet(OrphanAggregateConfigurations), + new DescendancyList(OrphanAggregateConfigurationsNode)); - var dec = new DescendancyList(TemplateAggregateConfigurationsNode); - dec.SetBetterRouteExists(); - AddToDictionaries(new HashSet(TemplateAggregateConfigurations), dec); + var dec = new DescendancyList(TemplateAggregateConfigurationsNode); + dec.SetBetterRouteExists(); + AddToDictionaries(new HashSet(TemplateAggregateConfigurations), dec); - //Some AggregateConfigurations are 'Patient Index Tables', this happens when there is an existing JoinableCohortAggregateConfiguration declared where - //the AggregateConfiguration_ID is the AggregateConfiguration.ID. We can inject this knowledge now so to avoid database lookups later (e.g. at icon provision time) - var joinableDictionaryByAggregateConfigurationId = - AllJoinables.ToDictionaryEx(j => j.AggregateConfiguration_ID, v => v); + //Some AggregateConfigurations are 'Patient Index Tables', this happens when there is an existing JoinableCohortAggregateConfiguration declared where + //the AggregateConfiguration_ID is the AggregateConfiguration.ID. We can inject this knowledge now so to avoid database lookups later (e.g. at icon provision time) + var joinableDictionaryByAggregateConfigurationId = + AllJoinables.ToDictionaryEx(j => j.AggregateConfiguration_ID, v => v); - foreach (var ac in AllAggregateConfigurations) //if there's a joinable - ac.InjectKnown( //inject that we know the joinable (and what it is) - joinableDictionaryByAggregateConfigurationId.GetValueOrDefault(ac.ID)); //otherwise inject that it is not a joinable (suppresses database checking later) + foreach (var ac in AllAggregateConfigurations) //if there's a joinable + ac.InjectKnown( //inject that we know the joinable (and what it is) + joinableDictionaryByAggregateConfigurationId.GetValueOrDefault(ac.ID)); //otherwise inject that it is not a joinable (suppresses database checking later) - ReportProgress("After AggregateConfiguration injection"); + ReportProgress("After AggregateConfiguration injection"); - AllGovernanceNode = new AllGovernanceNode(); - AllGovernancePeriods = GetAllObjects(repository); - AllGovernanceDocuments = GetAllObjects(repository); - GovernanceCoverage = repository.GovernanceManager.GetAllGovernedCataloguesForAllGovernancePeriods(); + AllGovernanceNode = new AllGovernanceNode(); + AllGovernancePeriods = GetAllObjects(repository); + AllGovernanceDocuments = GetAllObjects(repository); + GovernanceCoverage = repository.GovernanceManager.GetAllGovernedCataloguesForAllGovernancePeriods(); - AddChildren(AllGovernanceNode); + AddChildren(AllGovernanceNode); - ReportProgress("After Governance"); + ReportProgress("After Governance"); - AllPluginsNode = new AllPluginsNode(); - AddChildren(AllPluginsNode); + AllPluginsNode = new AllPluginsNode(); + AddChildren(AllPluginsNode); - ReportProgress("After Plugins"); + ReportProgress("After Plugins"); - AllRegexRedactionConfigurations = GetAllObjects(repository); - AllRegexRedactionConfigurationsNode = new AllRegexRedactionConfigurationsNode(); - AddChildren(AllRegexRedactionConfigurationsNode); + AllRegexRedactionConfigurations = GetAllObjects(repository); + AllRegexRedactionConfigurationsNode = new AllRegexRedactionConfigurationsNode(); + AddChildren(AllRegexRedactionConfigurationsNode); - AllDatasets = GetAllObjects(repository); - AllDatasetsNode = new AllDatasetsNode(); - AddChildren(AllDatasetsNode); + AllDatasets = GetAllObjects(repository); + AllDatasetsNode = new AllDatasetsNode(); + AddChildren(AllDatasetsNode); - ReportProgress("After Configurations"); + ReportProgress("After Configurations"); - var searchables = new Dictionary>(); + var searchables = new Dictionary>(); - foreach (var o in _descendancyDictionary.Keys.OfType()) - { - if (!searchables.ContainsKey(o.ID)) - searchables.Add(o.ID, new HashSet()); + foreach (var o in _descendancyDictionary.Keys.OfType()) + { + if (!searchables.ContainsKey(o.ID)) + searchables.Add(o.ID, new HashSet()); - searchables[o.ID].Add(o); - } + searchables[o.ID].Add(o); + } - ReportProgress("After building Searchables"); + ReportProgress("After building Searchables"); - foreach (var e in AllExports) - { - if (!searchables.TryGetValue(e.ReferencedObjectID, out var searchable)) - continue; + foreach (var e in AllExports) + { + if (!searchables.TryGetValue(e.ReferencedObjectID, out var searchable)) + continue; - var known = searchable - .FirstOrDefault(s => e.ReferencedObjectType == s.GetType().FullName); + var known = searchable + .FirstOrDefault(s => e.ReferencedObjectType == s.GetType().FullName); - if (known != null) - e.InjectKnown(known); - } + if (known != null) + e.InjectKnown(known); + } - ReportProgress("After building exports"); - } + ReportProgress("After building exports"); + } - private void FetchCatalogueItems() - { - AllCatalogueItemsDictionary = - GetAllObjects(_catalogueRepository).ToDictionaryEx(i => i.ID, o => o); + private void FetchCatalogueItems() + { + AllCatalogueItemsDictionary = + GetAllObjects(_catalogueRepository).ToDictionaryEx(i => i.ID, o => o); - ReportProgress("After CatalogueItem getting"); + ReportProgress("After CatalogueItem getting"); - _catalogueToCatalogueItems = AllCatalogueItems.GroupBy(c => c.Catalogue_ID) - .ToDictionaryEx(gdc => gdc.Key, gdc => gdc.ToList()); - _allColumnInfos = AllColumnInfos.ToDictionaryEx(i => i.ID, o => o); + _catalogueToCatalogueItems = AllCatalogueItems.GroupBy(c => c.Catalogue_ID) + .ToDictionaryEx(gdc => gdc.Key, gdc => gdc.ToList()); + _allColumnInfos = AllColumnInfos.ToDictionaryEx(i => i.ID, o => o); - ReportProgress("After CatalogueItem Dictionary building"); - - //Inject known ColumnInfos into CatalogueItems - Parallel.ForEach(AllCatalogueItems, ci => - { - if (ci.ColumnInfo_ID != null && _allColumnInfos.TryGetValue(ci.ColumnInfo_ID.Value, out var col)) - ci.InjectKnown(col); - else - ci.InjectKnown((ColumnInfo)null); - }); - } - - private void FetchExtractionInformations() - { - AllExtractionInformationsDictionary = GetAllObjects(_catalogueRepository) - .ToDictionaryEx(i => i.ID, o => o); - _extractionInformationsByCatalogueItem = - AllExtractionInformationsDictionary.Values.ToDictionaryEx(k => k.CatalogueItem_ID, v => v); - - //Inject known CatalogueItems into ExtractionInformations - foreach (var ei in AllExtractionInformationsDictionary.Values) - if (AllCatalogueItemsDictionary.TryGetValue(ei.CatalogueItem_ID, out var ci)) - { - ei.InjectKnown(ci.ColumnInfo); - ei.InjectKnown(ci); - } - } - - private void BuildCohortCohortAggregateContainers() - { - AllCohortAggregateContainers = GetAllObjects(_catalogueRepository); - - - //if we have a database repository then we should get answers from the caching version CohortContainerManagerFromChildProvider otherwise - //just use the one that is configured on the repository. - - _cohortContainerManager = _catalogueRepository is CatalogueRepository cataRepo - ? new CohortContainerManagerFromChildProvider(cataRepo, this) - : _catalogueRepository.CohortContainerManager; - } - - private void BuildAggregateConfigurations() - { - AllJoinableCohortAggregateConfigurationUse = - GetAllObjects(_catalogueRepository); - AllAggregateConfigurations = GetAllObjects(_catalogueRepository); - - BuildAggregateDimensions(); - - //to start with all aggregates are orphans (we prune this as we determine descendency in AddChildren methods - OrphanAggregateConfigurations = - new HashSet( - AllAggregateConfigurations.Where(ac => ac.IsCohortIdentificationAggregate)); - - foreach (var configuration in AllAggregateConfigurations) - { - configuration.InjectKnown(AllCataloguesDictionary[configuration.Catalogue_ID]); - configuration.InjectKnown(AllAggregateDimensions.Where(d => d.AggregateConfiguration_ID == configuration.ID) - .ToArray()); - } - - foreach (var d in AllAggregateDimensions) - d.InjectKnown(AllExtractionInformationsDictionary[d.ExtractionInformation_ID]); - - ReportProgress("AggregateDimension injections"); - - BuildAggregateFilterContainers(); - } - - private void BuildAggregateDimensions() - { - AllAggregateDimensions = GetAllObjects(_catalogueRepository); - AllAggregateContinuousDateAxis = GetAllObjects(_catalogueRepository); - } - - private void BuildAggregateFilterContainers() - { - AllAggregateContainersDictionary = GetAllObjects(_catalogueRepository) - .ToDictionaryEx(o => o.ID, o2 => o2); - AllAggregateFilters = GetAllObjects(_catalogueRepository); - AllAggregateFilterParameters = GetAllObjects(_catalogueRepository); - - _aggregateFilterManager = _catalogueRepository is CatalogueRepository cataRepo - ? new FilterManagerFromChildProvider(cataRepo, this) - : _catalogueRepository.FilterManager; - } - - - protected void ReportProgress(string desc) - { - if (UserSettings.DebugPerformance) - { - _errorsCheckNotifier.OnCheckPerformed(new CheckEventArgs( - $"ChildProvider Stage {_progress++} ({desc}):{ProgressStopwatch.ElapsedMilliseconds}ms", - CheckResult.Success)); - ProgressStopwatch.Restart(); - } - } - - private void AddChildren(AllPluginsNode allPluginsNode) - { - var children = new HashSet(LoadModuleAssembly.Assemblies); - var descendancy = new DescendancyList(allPluginsNode); - AddToDictionaries(children, descendancy); - } - - private void AddChildren(AllRegexRedactionConfigurationsNode allRegexRedactionConfigurationsNode) - { - var children = new HashSet(AllRegexRedactionConfigurations); - var descendancy = new DescendancyList(allRegexRedactionConfigurationsNode); - AddToDictionaries(children, descendancy); - } - - private void AddChildren(AllDatasetsNode allDatasetsNode) - { - var children = new HashSet(AllDatasets); - var descendancy = new DescendancyList(allDatasetsNode); - AddToDictionaries(children, descendancy); - } - - private void AddChildren(AllGovernanceNode allGovernanceNode) - { - var children = new HashSet(); - var descendancy = new DescendancyList(allGovernanceNode); - - foreach (var gp in AllGovernancePeriods) - { - children.Add(gp); - AddChildren(gp, descendancy.Add(gp)); - } - - AddToDictionaries(children, descendancy); - } - - private void AddChildren(GovernancePeriod governancePeriod, DescendancyList descendancy) - { - var children = new HashSet(); - - foreach (var doc in AllGovernanceDocuments.Where(d => d.GovernancePeriod_ID == governancePeriod.ID)) - children.Add(doc); - - AddToDictionaries(children, descendancy); - } - - private void AddChildren(AllPermissionWindowsNode allPermissionWindowsNode) - { - var descendancy = new DescendancyList(allPermissionWindowsNode); - - foreach (var permissionWindow in AllPermissionWindows) - AddChildren(permissionWindow, descendancy.Add(permissionWindow)); - - - AddToDictionaries(new HashSet(AllPermissionWindows), descendancy); - } - - private void AddChildren(PermissionWindow permissionWindow, DescendancyList descendancy) - { - var children = new HashSet(); - - foreach (var cacheProgress in AllCacheProgresses) - if (cacheProgress.PermissionWindow_ID == permissionWindow.ID) - children.Add(new PermissionWindowUsedByCacheProgressNode(cacheProgress, permissionWindow, false)); + ReportProgress("After CatalogueItem Dictionary building"); + + //Inject known ColumnInfos into CatalogueItems + Parallel.ForEach(AllCatalogueItems, ci => + { + if (ci.ColumnInfo_ID != null && _allColumnInfos.TryGetValue(ci.ColumnInfo_ID.Value, out var col)) + ci.InjectKnown(col); + else + ci.InjectKnown((ColumnInfo)null); + }); + } + + private void FetchExtractionInformations() + { + AllExtractionInformationsDictionary = GetAllObjects(_catalogueRepository) + .ToDictionaryEx(i => i.ID, o => o); + _extractionInformationsByCatalogueItem = + AllExtractionInformationsDictionary.Values.ToDictionaryEx(k => k.CatalogueItem_ID, v => v); + + //Inject known CatalogueItems into ExtractionInformations + foreach (var ei in AllExtractionInformationsDictionary.Values) + if (AllCatalogueItemsDictionary.TryGetValue(ei.CatalogueItem_ID, out var ci)) + { + ei.InjectKnown(ci.ColumnInfo); + ei.InjectKnown(ci); + } + } + + private void BuildCohortCohortAggregateContainers() + { + AllCohortAggregateContainers = GetAllObjects(_catalogueRepository); + + + //if we have a database repository then we should get answers from the caching version CohortContainerManagerFromChildProvider otherwise + //just use the one that is configured on the repository. + + _cohortContainerManager = _catalogueRepository is CatalogueRepository cataRepo + ? new CohortContainerManagerFromChildProvider(cataRepo, this) + : _catalogueRepository.CohortContainerManager; + } + + private void BuildAggregateConfigurations() + { + AllJoinableCohortAggregateConfigurationUse = + GetAllObjects(_catalogueRepository); + AllAggregateConfigurations = GetAllObjects(_catalogueRepository); + + BuildAggregateDimensions(); + + //to start with all aggregates are orphans (we prune this as we determine descendency in AddChildren methods + OrphanAggregateConfigurations = + new HashSet( + AllAggregateConfigurations.Where(ac => ac.IsCohortIdentificationAggregate)); + + foreach (var configuration in AllAggregateConfigurations) + { + configuration.InjectKnown(AllCataloguesDictionary[configuration.Catalogue_ID]); + configuration.InjectKnown(AllAggregateDimensions.Where(d => d.AggregateConfiguration_ID == configuration.ID) + .ToArray()); + } + + foreach (var d in AllAggregateDimensions) + d.InjectKnown(AllExtractionInformationsDictionary[d.ExtractionInformation_ID]); + + ReportProgress("AggregateDimension injections"); + + BuildAggregateFilterContainers(); + } + + private void BuildAggregateDimensions() + { + AllAggregateDimensions = GetAllObjects(_catalogueRepository); + AllAggregateContinuousDateAxis = GetAllObjects(_catalogueRepository); + } + + private void BuildAggregateFilterContainers() + { + AllAggregateContainersDictionary = GetAllObjects(_catalogueRepository) + .ToDictionaryEx(o => o.ID, o2 => o2); + AllAggregateFilters = GetAllObjects(_catalogueRepository); + AllAggregateFilterParameters = GetAllObjects(_catalogueRepository); + + _aggregateFilterManager = _catalogueRepository is CatalogueRepository cataRepo + ? new FilterManagerFromChildProvider(cataRepo, this) + : _catalogueRepository.FilterManager; + } + + + protected void ReportProgress(string desc) + { + if (UserSettings.DebugPerformance) + { + _errorsCheckNotifier.OnCheckPerformed(new CheckEventArgs( + $"ChildProvider Stage {_progress++} ({desc}):{ProgressStopwatch.ElapsedMilliseconds}ms", + CheckResult.Success)); + ProgressStopwatch.Restart(); + } + } + + private void AddChildren(AllPluginsNode allPluginsNode) + { + var children = new HashSet(LoadModuleAssembly.Assemblies); + var descendancy = new DescendancyList(allPluginsNode); + AddToDictionaries(children, descendancy); + } + + private void AddChildren(AllRegexRedactionConfigurationsNode allRegexRedactionConfigurationsNode) + { + var children = new HashSet(AllRegexRedactionConfigurations); + var descendancy = new DescendancyList(allRegexRedactionConfigurationsNode); + AddToDictionaries(children, descendancy); + } + + private void AddChildren(AllDatasetsNode allDatasetsNode) + { + var children = new HashSet(AllDatasets); + var descendancy = new DescendancyList(allDatasetsNode); + AddToDictionaries(children, descendancy); + } + + private void AddChildren(AllGovernanceNode allGovernanceNode) + { + var children = new HashSet(); + var descendancy = new DescendancyList(allGovernanceNode); + + foreach (var gp in AllGovernancePeriods) + { + children.Add(gp); + AddChildren(gp, descendancy.Add(gp)); + } + + AddToDictionaries(children, descendancy); + } + + private void AddChildren(GovernancePeriod governancePeriod, DescendancyList descendancy) + { + var children = new HashSet(); + + foreach (var doc in AllGovernanceDocuments.Where(d => d.GovernancePeriod_ID == governancePeriod.ID)) + children.Add(doc); + + AddToDictionaries(children, descendancy); + } + + private void AddChildren(AllPermissionWindowsNode allPermissionWindowsNode) + { + var descendancy = new DescendancyList(allPermissionWindowsNode); + + foreach (var permissionWindow in AllPermissionWindows) + AddChildren(permissionWindow, descendancy.Add(permissionWindow)); + + + AddToDictionaries(new HashSet(AllPermissionWindows), descendancy); + } + + private void AddChildren(PermissionWindow permissionWindow, DescendancyList descendancy) + { + var children = new HashSet(); + + foreach (var cacheProgress in AllCacheProgresses) + if (cacheProgress.PermissionWindow_ID == permissionWindow.ID) + children.Add(new PermissionWindowUsedByCacheProgressNode(cacheProgress, permissionWindow, false)); - AddToDictionaries(children, descendancy); - } + AddToDictionaries(children, descendancy); + } - private void AddChildren(AllExternalServersNode allExternalServersNode) - { - AddToDictionaries(new HashSet(AllExternalServers), new DescendancyList(allExternalServersNode)); - } - - private void AddChildren(AllRDMPRemotesNode allRDMPRemotesNode) - { - AddToDictionaries(new HashSet(AllRemoteRDMPs), new DescendancyList(allRDMPRemotesNode)); - } + private void AddChildren(AllExternalServersNode allExternalServersNode) + { + AddToDictionaries(new HashSet(AllExternalServers), new DescendancyList(allExternalServersNode)); + } + + private void AddChildren(AllRDMPRemotesNode allRDMPRemotesNode) + { + AddToDictionaries(new HashSet(AllRemoteRDMPs), new DescendancyList(allRDMPRemotesNode)); + } - private void AddChildren(AllDashboardsNode allDashboardsNode) - { - AddToDictionaries(new HashSet(AllDashboards), new DescendancyList(allDashboardsNode)); - } + private void AddChildren(AllDashboardsNode allDashboardsNode) + { + AddToDictionaries(new HashSet(AllDashboards), new DescendancyList(allDashboardsNode)); + } - private void AddChildren(AllObjectSharingNode allObjectSharingNode) - { - var descendancy = new DescendancyList(allObjectSharingNode); + private void AddChildren(AllObjectSharingNode allObjectSharingNode) + { + var descendancy = new DescendancyList(allObjectSharingNode); - var allExportsNode = new AllObjectExportsNode(); - var allImportsNode = new AllObjectImportsNode(); + var allExportsNode = new AllObjectExportsNode(); + var allImportsNode = new AllObjectImportsNode(); - AddToDictionaries(new HashSet(AllExports), descendancy.Add(allExportsNode)); - AddToDictionaries(new HashSet(AllImports), descendancy.Add(allImportsNode)); + AddToDictionaries(new HashSet(AllExports), descendancy.Add(allExportsNode)); + AddToDictionaries(new HashSet(AllImports), descendancy.Add(allImportsNode)); - AddToDictionaries(new HashSet(new object[] { allExportsNode, allImportsNode }), descendancy); - } + AddToDictionaries(new HashSet(new object[] { allExportsNode, allImportsNode }), descendancy); + } - /// - /// Creates new s and fills it with all compatible Pipelines - do not call this method more than once - /// - protected void AddPipelineUseCases(Dictionary useCases) - { - var descendancy = new DescendancyList(AllPipelinesNode); - var children = new HashSet(); + /// + /// Creates new s and fills it with all compatible Pipelines - do not call this method more than once + /// + protected void AddPipelineUseCases(Dictionary useCases) + { + var descendancy = new DescendancyList(AllPipelinesNode); + var children = new HashSet(); - //pipelines not found to be part of any StandardPipelineUseCase - var unknownPipelines = new HashSet(AllPipelines); + //pipelines not found to be part of any StandardPipelineUseCase + var unknownPipelines = new HashSet(AllPipelines); - foreach (var useCase in useCases) - { - var node = new StandardPipelineUseCaseNode(useCase.Key, useCase.Value, _commentStore); + foreach (var useCase in useCases) + { + var node = new StandardPipelineUseCaseNode(useCase.Key, useCase.Value, _commentStore); - //keep track of all the use cases - PipelineUseCases.Add(node); + //keep track of all the use cases + PipelineUseCases.Add(node); - foreach (var pipeline in AddChildren(node, descendancy.Add(node))) - unknownPipelines.Remove(pipeline); + foreach (var pipeline in AddChildren(node, descendancy.Add(node))) + unknownPipelines.Remove(pipeline); - children.Add(node); - } + children.Add(node); + } - children.Add(OtherPipelinesNode); - OtherPipelinesNode.Pipelines.AddRange(unknownPipelines.Cast()); - AddToDictionaries(unknownPipelines, descendancy.Add(OtherPipelinesNode)); + children.Add(OtherPipelinesNode); + OtherPipelinesNode.Pipelines.AddRange(unknownPipelines.Cast()); + AddToDictionaries(unknownPipelines, descendancy.Add(OtherPipelinesNode)); - //it is the first standard use case - AddToDictionaries(children, descendancy); - } + //it is the first standard use case + AddToDictionaries(children, descendancy); + } - private IEnumerable AddChildren(StandardPipelineUseCaseNode node, DescendancyList descendancy) - { - var children = new HashSet(); + private IEnumerable AddChildren(StandardPipelineUseCaseNode node, DescendancyList descendancy) + { + var children = new HashSet(); - var repo = new MemoryRepository(); + var repo = new MemoryRepository(); - //Could be an issue here if a pipeline becomes compatible with multiple use cases. - //Should be impossible currently but one day it could be an issue especially if we were to - //support plugin use cases in this hierarchy + //Could be an issue here if a pipeline becomes compatible with multiple use cases. + //Should be impossible currently but one day it could be an issue especially if we were to + //support plugin use cases in this hierarchy - //find compatible pipelines useCase.Value - foreach (var compatiblePipeline in AllPipelines.Where(node.UseCase.GetContext().IsAllowable)) - { - var useCaseNode = new PipelineCompatibleWithUseCaseNode(repo, compatiblePipeline, node.UseCase); + //find compatible pipelines useCase.Value + foreach (var compatiblePipeline in AllPipelines.Where(node.UseCase.GetContext().IsAllowable)) + { + var useCaseNode = new PipelineCompatibleWithUseCaseNode(repo, compatiblePipeline, node.UseCase); - AddChildren(useCaseNode, descendancy.Add(useCaseNode)); + AddChildren(useCaseNode, descendancy.Add(useCaseNode)); - node.Pipelines.Add(compatiblePipeline); - children.Add(useCaseNode); - } + node.Pipelines.Add(compatiblePipeline); + children.Add(useCaseNode); + } - //it is the first standard use case - AddToDictionaries(children, descendancy); + //it is the first standard use case + AddToDictionaries(children, descendancy); - return children.Cast().Select(u => u.Pipeline); - } + return children.Cast().Select(u => u.Pipeline); + } - private void AddChildren(PipelineCompatibleWithUseCaseNode pipelineNode, DescendancyList descendancy) - { - var components = AllPipelineComponents.Where(c => c.Pipeline_ID == pipelineNode.Pipeline.ID) - .OrderBy(o => o.Order) - .ToArray(); + private void AddChildren(PipelineCompatibleWithUseCaseNode pipelineNode, DescendancyList descendancy) + { + var components = AllPipelineComponents.Where(c => c.Pipeline_ID == pipelineNode.Pipeline.ID) + .OrderBy(o => o.Order) + .ToArray(); - foreach (var component in components) - AddChildren(component, descendancy.Add(component)); + foreach (var component in components) + AddChildren(component, descendancy.Add(component)); - var children = new HashSet(components); + var children = new HashSet(components); - AddToDictionaries(children, descendancy); - } + AddToDictionaries(children, descendancy); + } - private void AddChildren(PipelineComponent pipelineComponent, DescendancyList descendancy) - { - var components = AllPipelineComponentsArguments.Where(c => c.PipelineComponent_ID == pipelineComponent.ID) - .ToArray(); + private void AddChildren(PipelineComponent pipelineComponent, DescendancyList descendancy) + { + var components = AllPipelineComponentsArguments.Where(c => c.PipelineComponent_ID == pipelineComponent.ID) + .ToArray(); - var children = new HashSet(components); + var children = new HashSet(components); - AddToDictionaries(children, descendancy); - } + AddToDictionaries(children, descendancy); + } - private void BuildServerNodes() - { - //add a root node for all the servers to be children of - AllServersNode = new AllServersNode(); + private void BuildServerNodes() + { + //add a root node for all the servers to be children of + AllServersNode = new AllServersNode(); - var descendancy = new DescendancyList(AllServersNode); - var allServers = new List(); + var descendancy = new DescendancyList(AllServersNode); + var allServers = new List(); - foreach (var typeGroup in AllTableInfos.GroupBy(t => t.DatabaseType)) - { - var dbType = typeGroup.Key; - IEnumerable tables = typeGroup; + foreach (var typeGroup in AllTableInfos.GroupBy(t => t.DatabaseType)) + { + var dbType = typeGroup.Key; + IEnumerable tables = typeGroup; - var serversByName = tables - .GroupBy(c => c.Server ?? TableInfoServerNode.NullServerNode, StringComparer.CurrentCultureIgnoreCase) - .Select(s => new TableInfoServerNode(s.Key, dbType, s)); + var serversByName = tables + .GroupBy(c => c.Server ?? TableInfoServerNode.NullServerNode, StringComparer.CurrentCultureIgnoreCase) + .Select(s => new TableInfoServerNode(s.Key, dbType, s)); - foreach (var server in serversByName) - { - allServers.Add(server); - AddChildren(server, descendancy.Add(server)); - } - } + foreach (var server in serversByName) + { + allServers.Add(server); + AddChildren(server, descendancy.Add(server)); + } + } - //create the server nodes - AllServers = allServers.ToArray(); + //create the server nodes + AllServers = allServers.ToArray(); - //record the fact that all the servers are children of the all servers node - AddToDictionaries(new HashSet(AllServers), descendancy); - } + //record the fact that all the servers are children of the all servers node + AddToDictionaries(new HashSet(AllServers), descendancy); + } - private void AddChildren(AllDataAccessCredentialsNode allDataAccessCredentialsNode) - { - var children = new HashSet(); + private void AddChildren(AllDataAccessCredentialsNode allDataAccessCredentialsNode) + { + var children = new HashSet(); - var isKeyMissing = false; - if (_catalogueRepository.EncryptionManager is PasswordEncryptionKeyLocation keyLocation) - isKeyMissing = string.IsNullOrWhiteSpace(keyLocation.GetKeyFileLocation()); + var isKeyMissing = false; + if (_catalogueRepository.EncryptionManager is PasswordEncryptionKeyLocation keyLocation) + isKeyMissing = string.IsNullOrWhiteSpace(keyLocation.GetKeyFileLocation()); - children.Add(new DecryptionPrivateKeyNode(isKeyMissing)); - - foreach (var creds in AllDataAccessCredentials) - children.Add(creds); - - - AddToDictionaries(children, new DescendancyList(allDataAccessCredentialsNode)); - } - - private void AddChildren(AllANOTablesNode anoTablesNode) - { - AddToDictionaries(new HashSet(AllANOTables), new DescendancyList(anoTablesNode)); - } - - private void AddChildren(FolderNode folder, DescendancyList descendancy) - { - foreach (var child in folder.ChildFolders) - //add subfolder children - AddChildren(child, descendancy.Add(child)); - - //add catalogues in folder - foreach (var c in folder.ChildObjects) AddChildren(c, descendancy.Add(c)); - - // Children are the folders + objects - AddToDictionaries(new HashSet( - folder.ChildFolders.Cast() - .Union(folder.ChildObjects)), descendancy - ); - } - - private void AddChildren(FolderNode folder, DescendancyList descendancy) - { - foreach (var child in folder.ChildFolders) - //add subfolder children - AddChildren(child, descendancy.Add(child)); - - //add loads in folder - foreach (var lmd in folder.ChildObjects.Where(lmd => lmd.RootLoadMetadata_ID == null).ToArray()) AddChildren(lmd, descendancy.Add(lmd)); - // Children are the folders + objects - AddToDictionaries(new HashSet( - folder.ChildFolders.Cast() - .Union(folder.ChildObjects)), descendancy - ); - } - - private void AddChildren(FolderNode folder, DescendancyList descendancy) - { - foreach (var child in folder.ChildFolders) - //add subfolder children - AddChildren(child, descendancy.Add(child)); - - //add loads in folder - foreach (var ds in folder.ChildObjects) AddChildren(ds, descendancy.Add(ds)); - - // Children are the folders + objects - AddToDictionaries(new HashSet( - folder.ChildFolders.Cast() - .Union(folder.ChildObjects)), descendancy - ); - } - - private void AddChildren(FolderNode folder, DescendancyList descendancy) - { - foreach (var child in folder.ChildFolders) - //add subfolder children - AddChildren(child, descendancy.Add(child)); - - - //add cics in folder - foreach (var cic in folder.ChildObjects) AddChildren(cic, descendancy.Add(cic)); - - // Children are the folders + objects - AddToDictionaries(new HashSet( - folder.ChildFolders.Cast() - .Union(folder.ChildObjects)), descendancy - ); - } - - private void AddChildren(Curation.Data.Dataset lmd, DescendancyList descendancy) - { - var childObjects = new List(); - AddToDictionaries(new HashSet(childObjects), descendancy); - } - - - #region Load Metadata - - private void AddChildren(LoadMetadata lmd, DescendancyList descendancy, bool includeSchedule = true, bool includeCatalogues = true, bool includeVersions = true) - { - var childObjects = new List(); - - if (lmd.OverrideRAWServer_ID.HasValue) - { - var server = AllExternalServers.Single(s => s.ID == lmd.OverrideRAWServer_ID.Value); - var usage = new OverrideRawServerNode(lmd, server); - childObjects.Add(usage); - } - if (includeSchedule) - { - var allSchedulesNode = new LoadMetadataScheduleNode(lmd); - AddChildren(allSchedulesNode, descendancy.Add(allSchedulesNode)); - childObjects.Add(allSchedulesNode); - } - - if (includeCatalogues) - { - var allCataloguesNode = new AllCataloguesUsedByLoadMetadataNode(lmd); - AddChildren(allCataloguesNode, descendancy.Add(allCataloguesNode)); - childObjects.Add(allCataloguesNode); - } - - var processTasksNode = new AllProcessTasksUsedByLoadMetadataNode(lmd); - AddChildren(processTasksNode, descendancy.Add(processTasksNode)); - childObjects.Add(processTasksNode); - - if (includeVersions) - { - var versionsNode = new LoadMetadataVersionNode(lmd); - AddChildren(versionsNode, descendancy.Add(versionsNode)); - childObjects.Add(versionsNode); - } - - childObjects.Add(new LoadDirectoryNode(lmd)); - - AddToDictionaries(new HashSet(childObjects), descendancy); - } - - private void AddChildren(LoadMetadataScheduleNode allSchedulesNode, DescendancyList descendancy) - { - var childObjects = new HashSet(); - - var lmd = allSchedulesNode.LoadMetadata; - - foreach (var lp in AllLoadProgresses.Where(p => p.LoadMetadata_ID == lmd.ID)) - { - AddChildren(lp, descendancy.Add(lp)); - childObjects.Add(lp); - } - - if (childObjects.Any()) - AddToDictionaries(childObjects, descendancy); - } - - private void AddChildren(LoadProgress loadProgress, DescendancyList descendancy) - { - var cacheProgresses = AllCacheProgresses.Where(cp => cp.LoadProgress_ID == loadProgress.ID).ToArray(); - - foreach (var cacheProgress in cacheProgresses) - AddChildren(cacheProgress, descendancy.Add(cacheProgress)); - - if (cacheProgresses.Any()) - AddToDictionaries(new HashSet(cacheProgresses), descendancy); - } - - private void AddChildren(CacheProgress cacheProgress, DescendancyList descendancy) - { - var children = new HashSet(); - - if (cacheProgress.PermissionWindow_ID != null) - { - var window = AllPermissionWindows.Single(w => w.ID == cacheProgress.PermissionWindow_ID); - var windowNode = new PermissionWindowUsedByCacheProgressNode(cacheProgress, window, true); - - children.Add(windowNode); - } - - if (children.Any()) - AddToDictionaries(children, descendancy); - } - - private void AddChildren(AllProcessTasksUsedByLoadMetadataNode allProcessTasksUsedByLoadMetadataNode, - DescendancyList descendancy) - { - var childObjects = new HashSet(); - - var lmd = allProcessTasksUsedByLoadMetadataNode.LoadMetadata; - childObjects.Add(new LoadStageNode(lmd, LoadStage.GetFiles)); - childObjects.Add(new LoadStageNode(lmd, LoadStage.Mounting)); - childObjects.Add(new LoadStageNode(lmd, LoadStage.AdjustRaw)); - childObjects.Add(new LoadStageNode(lmd, LoadStage.AdjustStaging)); - childObjects.Add(new LoadStageNode(lmd, LoadStage.PostLoad)); - - foreach (LoadStageNode node in childObjects) - AddChildren(node, descendancy.Add(node)); - - AddToDictionaries(childObjects, descendancy); - } - - private void AddChildren(LoadStageNode loadStageNode, DescendancyList descendancy) - { - var tasks = AllProcessTasks.Where( - p => p.LoadMetadata_ID == loadStageNode.LoadMetadata.ID && p.LoadStage == loadStageNode.LoadStage) - .OrderBy(o => o.Order).ToArray(); - - foreach (var processTask in tasks) - AddChildren(processTask, descendancy.Add(processTask)); - - if (tasks.Any()) - AddToDictionaries(new HashSet(tasks), descendancy); - } - - private void AddChildren(ProcessTask procesTask, DescendancyList descendancy) - { - var args = AllProcessTasksArguments.Where( - a => a.ProcessTask_ID == procesTask.ID).ToArray(); - - if (args.Any()) - AddToDictionaries(new HashSet(args), descendancy); - } - - private void AddChildren(LoadMetadataVersionNode LoadMetadataVersionNode, DescendancyList descendancy) - { - LoadMetadataVersionNode.LoadMetadataVersions = AllLoadMetadatas.Where(lmd => lmd.RootLoadMetadata_ID == LoadMetadataVersionNode.LoadMetadata.ID).ToList(); - var childObjects = new List(); - - foreach (var lmd in LoadMetadataVersionNode.LoadMetadataVersions) - { - AddChildren(lmd, descendancy.Add(lmd), false, false, false); - childObjects.Add(lmd); - } - AddToDictionaries(new HashSet(childObjects), descendancy); - - } - - private void AddChildren(AllCataloguesUsedByLoadMetadataNode allCataloguesUsedByLoadMetadataNode, - DescendancyList descendancy) - { - var loadMetadataId = allCataloguesUsedByLoadMetadataNode.LoadMetadata.ID; - var linkedCatalogueIDs = AllLoadMetadataLinkage.Where(link => link.LoadMetadataID == loadMetadataId).Select(static link => link.CatalogueID); - var usedCatalogues = linkedCatalogueIDs.Select(catalogueId => AllCatalogues.FirstOrDefault(c => c.ID == catalogueId)).Where(static foundCatalogue => foundCatalogue is not null).ToList(); - allCataloguesUsedByLoadMetadataNode.UsedCatalogues = usedCatalogues; - var childObjects = usedCatalogues.Select(foundCatalogue => new CatalogueUsedByLoadMetadataNode(allCataloguesUsedByLoadMetadataNode.LoadMetadata, foundCatalogue)).Cast().ToHashSet(); - - AddToDictionaries(childObjects, descendancy); - } - - #endregion - - protected void AddChildren(Catalogue c, DescendancyList descendancy) - { - var childObjects = new List(); - - var catalogueAggregates = AllAggregateConfigurations.Where(a => a.Catalogue_ID == c.ID).ToArray(); - var cohortAggregates = catalogueAggregates.Where(a => a.IsCohortIdentificationAggregate).ToArray(); - var regularAggregates = catalogueAggregates.Except(cohortAggregates).ToArray(); - - //get all the CatalogueItems for this Catalogue (TryGet because Catalogue may not have any items - var cis = _catalogueToCatalogueItems.TryGetValue(c.ID, out var result) - ? result.ToArray() - : Array.Empty(); - - //tell the CatalogueItems that we are are their parent - foreach (var ci in cis) - ci.InjectKnown(c); - - // core includes project specific which basically means the same thing - var core = new CatalogueItemsNode(c, - cis.Where(ci => ci.ExtractionInformation?.ExtractionCategory == ExtractionCategory.Core || - ci.ExtractionInformation?.ExtractionCategory == ExtractionCategory.ProjectSpecific) - , ExtractionCategory.Core); - - c.InjectKnown(cis); - - var deprecated = new CatalogueItemsNode(c, - cis.Where(ci => ci.ExtractionInformation?.ExtractionCategory == ExtractionCategory.Deprecated), - ExtractionCategory.Deprecated); - var special = new CatalogueItemsNode(c, - cis.Where(ci => ci.ExtractionInformation?.ExtractionCategory == ExtractionCategory.SpecialApprovalRequired), - ExtractionCategory.SpecialApprovalRequired); - var intern = new CatalogueItemsNode(c, - cis.Where(ci => ci.ExtractionInformation?.ExtractionCategory == ExtractionCategory.Internal), - ExtractionCategory.Internal); - var supplemental = new CatalogueItemsNode(c, - cis.Where(ci => ci.ExtractionInformation?.ExtractionCategory == ExtractionCategory.Supplemental), - ExtractionCategory.Supplemental); - var notExtractable = new CatalogueItemsNode(c, cis.Where(ci => ci.ExtractionInformation == null), null); - - AddChildren(core, descendancy.Add(core)); - childObjects.Add(core); - - foreach (var optional in new[] { deprecated, special, intern, supplemental, notExtractable }) - if (optional.CatalogueItems.Any()) - { - AddChildren(optional, descendancy.Add(optional)); - childObjects.Add(optional); - } - - //do we have any foreign key fields into this lookup table - var lookups = AllLookups.Where(l => c.CatalogueItems.Any(ci => ci.ColumnInfo_ID == l.ForeignKey_ID)).ToArray(); - - var docs = AllSupportingDocuments.Where(d => d.Catalogue_ID == c.ID).ToArray(); - var sql = AllSupportingSQL.Where(d => d.Catalogue_ID == c.ID).ToArray(); - - //if there are supporting documents or supporting sql files then add documentation node - if (docs.Any() || sql.Any()) - { - var documentationNode = new DocumentationNode(c, docs, sql); - - //add the documentations node - childObjects.Add(documentationNode); - - //record the children - AddToDictionaries(new HashSet(docs.Cast().Union(sql)), descendancy.Add(documentationNode)); - } - - if (lookups.Any()) - { - var lookupsNode = new CatalogueLookupsNode(c, lookups); - //add the documentations node - childObjects.Add(lookupsNode); - - - //record the children - AddToDictionaries(new HashSet(lookups.Select(l => new CatalogueLookupUsageNode(c, l))), - descendancy.Add(lookupsNode)); - } - - if (regularAggregates.Any()) - { - var aggregatesNode = new AggregatesNode(c, regularAggregates); - childObjects.Add(aggregatesNode); - - var nodeDescendancy = descendancy.Add(aggregatesNode); - AddToDictionaries(new HashSet(regularAggregates), nodeDescendancy); - - foreach (var regularAggregate in regularAggregates) - AddChildren(regularAggregate, nodeDescendancy.Add(regularAggregate)); - } - - //finalise - AddToDictionaries(new HashSet(childObjects), descendancy); - } - - private void InjectCatalogueItems() - { - foreach (var ci in AllCatalogueItems) - if (_extractionInformationsByCatalogueItem.TryGetValue(ci.ID, out var ei)) - ci.InjectKnown(ei); - else - ci.InjectKnown((ExtractionInformation)null); - } - - private void AddChildren(CatalogueItemsNode node, DescendancyList descendancyList) - { - AddToDictionaries(new HashSet(node.CatalogueItems), descendancyList); - - foreach (var ci in node.CatalogueItems) - AddChildren(ci, descendancyList.Add(ci)); - } - - private void AddChildren(AggregateConfiguration aggregateConfiguration, DescendancyList descendancy) - { - var childrenObjects = new HashSet(); - - var parameters = AllAnyTableParameters.Where(p => p.IsReferenceTo(aggregateConfiguration)).Cast() - .ToArray(); - - foreach (var p in parameters) - childrenObjects.Add(p); - - // show the dimensions in the tree - foreach (var dim in aggregateConfiguration.AggregateDimensions) childrenObjects.Add(dim); - - // show the axis (if any) in the tree. If there are multiple axis in this tree then that is bad but maybe the user can delete one of them to fix the situation - foreach (var axis in AllAggregateContinuousDateAxis.Where(a => - aggregateConfiguration.AggregateDimensions.Any(d => d.ID == a.AggregateDimension_ID))) - childrenObjects.Add(axis); - - //we can step into this twice, once via Catalogue children and once via CohortIdentificationConfiguration children - //if we get in via Catalogue children then descendancy will be Ignore=true we don't end up emphasising into CatalogueCollectionUI when - //really user wants to see it in CohortIdentificationCollectionUI - if (aggregateConfiguration.RootFilterContainer_ID != null) - { - var container = AllAggregateContainersDictionary[(int)aggregateConfiguration.RootFilterContainer_ID]; - - AddChildren(container, descendancy.Add(container)); - childrenObjects.Add(container); - } - - AddToDictionaries(childrenObjects, descendancy); - } - - private void AddChildren(AggregateFilterContainer container, DescendancyList descendancy) - { - var childrenObjects = new List(); - - var subcontainers = _aggregateFilterManager.GetSubContainers(container); - var filters = _aggregateFilterManager.GetFilters(container); - - foreach (AggregateFilterContainer subcontainer in subcontainers) - { - //one of our children is this subcontainer - childrenObjects.Add(subcontainer); - - //but also document its children - AddChildren(subcontainer, descendancy.Add(subcontainer)); - } - - //also add the filters for the container - foreach (var f in filters) - { - // for filters add the parameters under them - AddChildren((AggregateFilter)f, descendancy.Add(f)); - childrenObjects.Add(f); - } - - //add our children to the dictionary - AddToDictionaries(new HashSet(childrenObjects), descendancy); - } - - private void AddChildren(AggregateFilter f, DescendancyList descendancy) - { - AddToDictionaries(new HashSet(AllAggregateFilterParameters.Where(p => p.AggregateFilter_ID == f.ID)), - descendancy); - } - - private void AddChildren(CatalogueItem ci, DescendancyList descendancy) - { - var childObjects = new List(); - - var ei = ci.ExtractionInformation; - if (ei != null) - { - childObjects.Add(ei); - AddChildren(ei, descendancy.Add(ei)); - } - else - { - ci.InjectKnown( - (ExtractionInformation)null); // we know the CatalogueItem has no ExtractionInformation child because it's not in the dictionary - } - - if (ci.ColumnInfo_ID.HasValue && _allColumnInfos.TryGetValue(ci.ColumnInfo_ID.Value, out var col)) - childObjects.Add(new LinkedColumnInfoNode(ci, col)); - - AddToDictionaries(new HashSet(childObjects), descendancy); - } - - private void AddChildren(ExtractionInformation extractionInformation, DescendancyList descendancy) - { - var children = new HashSet(); - - foreach (var filter in AllCatalogueFilters.Where(f => f.ExtractionInformation_ID == extractionInformation.ID)) - { - //add the filter as a child of the - children.Add(filter); - AddChildren(filter, descendancy.Add(filter)); - } - - AddToDictionaries(children, descendancy); - } - - private void AddChildren(ExtractionFilter filter, DescendancyList descendancy) - { - var children = new HashSet(); - var parameters = AllCatalogueParameters.Where(p => p.ExtractionFilter_ID == filter.ID).ToArray(); - var parameterSets = AllCatalogueValueSets.Where(vs => vs.ExtractionFilter_ID == filter.ID).ToArray(); - - filter.InjectKnown(parameterSets); - - foreach (var p in parameters) - children.Add(p); - - foreach (var set in parameterSets) - { - children.Add(set); - AddChildren(set, descendancy.Add(set), parameters); - } - - if (children.Any()) - AddToDictionaries(children, descendancy); - } - - private void AddChildren(ExtractionFilterParameterSet set, DescendancyList descendancy, - ExtractionFilterParameter[] filterParameters) - { - var children = new HashSet(); - - foreach (var setValue in AllCatalogueValueSetValues.Where(v => v.ExtractionFilterParameterSet_ID == set.ID)) - { - setValue.InjectKnown(filterParameters.SingleOrDefault(p => p.ID == setValue.ExtractionFilterParameter_ID)); - children.Add(setValue); - } - - AddToDictionaries(children, descendancy); - } - - private void AddChildren(CohortIdentificationConfiguration cic, DescendancyList descendancy) - { - var children = new HashSet(); - - //it has an associated query cache - if (cic.QueryCachingServer_ID != null) - children.Add(new QueryCacheUsedByCohortIdentificationNode(cic, - AllExternalServers.Single(s => s.ID == cic.QueryCachingServer_ID))); - - var parameters = AllAnyTableParameters.Where(p => p.IsReferenceTo(cic)).Cast().ToArray(); - foreach (var p in parameters) children.Add(p); - - //if it has a root container - if (cic.RootCohortAggregateContainer_ID != null) - { - var container = AllCohortAggregateContainers.Single(c => c.ID == cic.RootCohortAggregateContainer_ID); - AddChildren(container, descendancy.Add(container).SetBetterRouteExists()); - children.Add(container); - } - - //get the patient index tables - var joinableNode = new JoinableCollectionNode(cic, - AllJoinables.Where(j => j.CohortIdentificationConfiguration_ID == cic.ID).ToArray()); - AddChildren(joinableNode, descendancy.Add(joinableNode).SetBetterRouteExists()); - children.Add(joinableNode); - - AddToDictionaries(children, descendancy.SetBetterRouteExists()); - } - - private void AddChildren(JoinableCollectionNode joinablesNode, DescendancyList descendancy) - { - var children = new HashSet(); - - foreach (var joinable in joinablesNode.Joinables) - try - { - var agg = AllAggregateConfigurations.Single(ac => ac.ID == joinable.AggregateConfiguration_ID); - ForceAggregateNaming(agg, descendancy); - children.Add(agg); - - //it's no longer an orphan because it's in a known cic (as a patient index table) - OrphanAggregateConfigurations.Remove(agg); - - AddChildren(agg, descendancy.Add(agg)); - } - catch (Exception e) - { - throw new Exception( - $"JoinableCohortAggregateConfiguration (patient index table) object (ID={joinable.ID}) references AggregateConfiguration_ID {joinable.AggregateConfiguration_ID} but that AggregateConfiguration was not found", - e); - } - - AddToDictionaries(children, descendancy); - } - - private void AddChildren(CohortAggregateContainer container, DescendancyList descendancy) - { - //get subcontainers - var subcontainers = _cohortContainerManager.GetChildren(container).OfType().ToList(); - - //if there are subcontainers - foreach (var subcontainer in subcontainers) - AddChildren(subcontainer, descendancy.Add(subcontainer)); - - //get our configurations - var configurations = _cohortContainerManager.GetChildren(container).OfType().ToList(); - - //record the configurations children including full descendancy - foreach (var configuration in configurations) - { - ForceAggregateNaming(configuration, descendancy); - AddChildren(configuration, descendancy.Add(configuration)); - - //it's no longer an orphan because it's in a known cic - OrphanAggregateConfigurations.Remove(configuration); - } - - //all our children (containers and aggregates) - //children are all aggregates and containers at the current hierarchy level in order - var children = subcontainers.Union(configurations.Cast()).OrderBy(o => o.Order).ToList(); - - AddToDictionaries(new HashSet(children), descendancy); - } - - private void ForceAggregateNaming(AggregateConfiguration configuration, DescendancyList descendancy) - { - //configuration has the wrong name - if (!configuration.IsCohortIdentificationAggregate) - { - _errorsCheckNotifier.OnCheckPerformed(new CheckEventArgs( - $"Had to fix naming of configuration '{configuration}' because it didn't start with correct cic prefix", - CheckResult.Warning)); - descendancy.Parents.OfType().Single() - .EnsureNamingConvention(configuration); - configuration.SaveToDatabase(); - } - } - - private void AddChildren(TableInfoServerNode serverNode, DescendancyList descendancy) - { - //add empty hashset - var children = new HashSet(); - - var databases = - serverNode.Tables.GroupBy( - k => k.Database ?? TableInfoDatabaseNode.NullDatabaseNode, StringComparer.CurrentCultureIgnoreCase) - .Select(g => new TableInfoDatabaseNode(g.Key, serverNode, g)); - - foreach (var db in databases) - { - children.Add(db); - AddChildren(db, descendancy.Add(db)); - } - - //now we have recorded all the children add them with descendancy - AddToDictionaries(children, descendancy); - } - - private void AddChildren(TableInfoDatabaseNode dbNode, DescendancyList descendancy) - { - //add empty hashset - var children = new HashSet(); - - foreach (var t in dbNode.Tables) - { - //record the children of the table infos (mostly column infos) - children.Add(t); - - //the all servers node=>the TableInfoServerNode => the t - AddChildren(t, descendancy.Add(t)); - } - - //now we have recorded all the children add them with descendancy - AddToDictionaries(children, descendancy); - } - - private void AddChildren(TableInfo tableInfo, DescendancyList descendancy) - { - //add empty hashset - var children = new HashSet(); - - //if the table has an identifier dump listed - if (tableInfo.IdentifierDumpServer_ID != null) - { - //if there is a dump (e.g. for dilution and dumping - not appearing in the live table) - var server = AllExternalServers.Single(s => s.ID == tableInfo.IdentifierDumpServer_ID.Value); - - children.Add(new IdentifierDumpServerUsageNode(tableInfo, server)); - } - - //get the discarded columns in this table - var discardedCols = new HashSet(AllPreLoadDiscardedColumns.Where(c => c.TableInfo_ID == tableInfo.ID)); - - //tell the column who their parent is so they don't need to look up the database - foreach (PreLoadDiscardedColumn discardedCol in discardedCols) - discardedCol.InjectKnown(tableInfo); - - //if there are discarded columns - if (discardedCols.Any()) - { - var identifierDumpNode = new PreLoadDiscardedColumnsNode(tableInfo); - - //record that the usage is a child of TableInfo - children.Add(identifierDumpNode); - - //record that the discarded columns are children of identifier dump usage node - AddToDictionaries(discardedCols, descendancy.Add(identifierDumpNode)); - } - - //if it is a table valued function - if (tableInfo.IsTableValuedFunction) - { - //that has parameters - var parameters = tableInfo.GetAllParameters(); - - foreach (var p in parameters) children.Add(p); - } - - //next add the column infos - if (TableInfosToColumnInfos.TryGetValue(tableInfo.ID, out var result)) - foreach (var c in result) - { - children.Add(c); - c.InjectKnown(tableInfo); - AddChildren(c, descendancy.Add(c).SetBetterRouteExists()); - } - - //finally add any credentials objects - if (AllDataAccessCredentialUsages.TryGetValue(tableInfo, out var nodes)) - foreach (var node in nodes) - children.Add(node); - - //now we have recorded all the children add them with descendancy via the TableInfo descendancy - AddToDictionaries(children, descendancy); - } - - private void AddChildren(ColumnInfo columnInfo, DescendancyList descendancy) - { - var lookups = AllLookups.Where(l => l.Description_ID == columnInfo.ID).ToArray(); - var joinInfos = AllJoinInfos.Where(j => j.PrimaryKey_ID == columnInfo.ID); - - var children = new HashSet(); - - foreach (var l in lookups) - children.Add(l); - - foreach (var j in joinInfos) - children.Add(j); - - if (children.Any()) - AddToDictionaries(children, descendancy); - } - - protected void AddToDictionaries(HashSet children, DescendancyList list) - { - if (list.IsEmpty) - throw new ArgumentException("DescendancyList cannot be empty", nameof(list)); - - //document that the last parent has these as children - var parent = list.Last(); - - _childDictionary.AddOrUpdate(parent, - children, (p, s) => children); - - //now document the entire parent order to reach each child object i.e. 'Root=>Grandparent=>Parent' is how you get to 'Child' - foreach (var o in children) - _descendancyDictionary.AddOrUpdate(o, list, (k, v) => HandleDescendancyCollision(k, v, list)); - - - foreach (var masquerader in children.OfType()) - { - var key = masquerader.MasqueradingAs(); - - if (!AllMasqueraders.ContainsKey(key)) - AllMasqueraders.AddOrUpdate(key, new HashSet(), (o, set) => set); - - lock (AllMasqueraders) - { - AllMasqueraders[key].Add(masquerader); - } - } - } - - private static DescendancyList HandleDescendancyCollision(object key, DescendancyList oldRoute, - DescendancyList newRoute) - { - //if the new route is the best best - if (newRoute.NewBestRoute && !oldRoute.NewBestRoute) - return newRoute; - - // If the new one is marked BetterRouteExists just throw away the new one - return newRoute.BetterRouteExists ? oldRoute : newRoute; - // If in doubt use the newest one - } - - private HashSet GetAllObjects() - { - //anything which has children or is a child of someone else (distinct because HashSet) - return new HashSet(_childDictionary.SelectMany(kvp => kvp.Value).Union(_childDictionary.Keys)); - } - - public virtual object[] GetChildren(object model) - { - lock (WriteLock) - { - //if we have a record of any children in the child dictionary for the parent model object - if (_childDictionary.TryGetValue(model, out var cached)) - return cached.OrderBy(static o => o.ToString()).ToArray(); - - return model switch - { - //if they want the children of a Pipeline (which we don't track) just serve the components - Pipeline p => p.PipelineComponents.ToArray(), - //if they want the children of a PipelineComponent (which we don't track) just serve the arguments - PipelineComponent pc => pc.PipelineComponentArguments.ToArray(), - _ => Array.Empty() - }; - } - } - - public IEnumerable GetAllObjects(Type type, bool unwrapMasqueraders) - { - lock (WriteLock) - { - //things that are a match on Type but not IMasqueradeAs - var exactMatches = GetAllSearchables().Keys.Where(t => t is not IMasqueradeAs).Where(type.IsInstanceOfType); - - //Union the unwrapped masqueraders - return unwrapMasqueraders - ? exactMatches.Union( - AllMasqueraders - .Select(kvp => kvp.Key) - .OfType() - .Where(type.IsInstanceOfType)) - .Distinct() - : exactMatches; - } - } - - public DescendancyList GetDescendancyListIfAnyFor(object model) - { - lock (WriteLock) - { - return _descendancyDictionary.GetValueOrDefault(model); - } - } - - - public object GetRootObjectOrSelf(object objectToEmphasise) - { - lock (WriteLock) - { - var descendancy = GetDescendancyListIfAnyFor(objectToEmphasise); - - return descendancy != null && descendancy.Parents.Any() ? descendancy.Parents[0] : objectToEmphasise; - } - } - - - public virtual Dictionary GetAllSearchables() - { - lock (WriteLock) - { - var toReturn = new Dictionary(); - - foreach (var kvp in _descendancyDictionary.Where(kvp => kvp.Key is IMapsDirectlyToDatabaseTable)) - toReturn.Add((IMapsDirectlyToDatabaseTable)kvp.Key, kvp.Value); - - return toReturn; - } - } - - public IEnumerable GetAllChildrenRecursively(object o) - { - lock (WriteLock) - { - var toReturn = new List(); - - foreach (var child in GetChildren(o)) - { - toReturn.Add(child); - toReturn.AddRange(GetAllChildrenRecursively(child)); - } - - return toReturn; - } - } - - /// - /// Asks all plugins to provide the child objects for every object we have found so far. This method is recursive, call it with null the first time to use all objects. It will then - /// call itself with all the new objects that were sent back by the plugin (so that new objects found can still have children). - /// - /// - protected void GetPluginChildren(HashSet objectsToAskAbout = null) - { - lock (WriteLock) - { - var newObjectsFound = new HashSet(); - - var sw = new Stopwatch(); - - var providers = _pluginChildProviders.Except(_blockedPlugins).ToArray(); - - //for every object found so far - if (providers.Any()) - foreach (var o in objectsToAskAbout ?? GetAllObjects()) - //for every plugin loaded (that is not forbidlisted) - foreach (var plugin in providers) - //ask about the children - try - { - sw.Restart(); - //otherwise ask plugin what its children are - var pluginChildren = plugin.GetChildren(o); - - //if the plugin takes too long to respond we need to stop - if (sw.ElapsedMilliseconds > 1000) - { - _blockedPlugins.Add(plugin); - throw new Exception( - $"Plugin '{plugin}' was forbidlisted for taking too long to respond to GetChildren(o) where o was a '{o.GetType().Name}' ('{o}')"); - } - - //it has children - if (pluginChildren != null && pluginChildren.Any()) - { - //get the descendancy of the parent - var parentDescendancy = GetDescendancyListIfAnyFor(o); - var newDescendancy = parentDescendancy == null - ? new DescendancyList(new[] { o }) - : //if the parent is a root level object start a new descendancy list from it - parentDescendancy - .Add(o); //otherwise keep going down, returns a new DescendancyList so doesn't corrupt the dictionary one - newDescendancy = - parentDescendancy - .Add(o); //otherwise keep going down, returns a new DescendancyList so doesn't corrupt the dictionary one - - //record that - foreach (var pluginChild in pluginChildren) - { - //if the parent didn't have any children before - if (!_childDictionary.ContainsKey(o)) - _childDictionary.AddOrUpdate(o, new HashSet(), - (o1, set) => set); //it does now - - - //add us to the parent objects child collection - _childDictionary[o].Add(pluginChild); - - //add to the child collection of the parent object kvp.Key - _descendancyDictionary.AddOrUpdate(pluginChild, newDescendancy, - (s, e) => newDescendancy); - - //we have found a new object so we must ask other plugins about it (chances are a plugin will have a whole tree of sub objects) - newObjectsFound.Add(pluginChild); - } - } - } - catch (Exception e) - { - _errorsCheckNotifier.OnCheckPerformed(new CheckEventArgs(e.Message, CheckResult.Fail, e)); - } - - if (newObjectsFound.Any()) - GetPluginChildren(newObjectsFound); - } - } - - public IEnumerable GetMasqueradersOf(object o) - { - lock (WriteLock) - { - return AllMasqueraders.TryGetValue(o, out var result) ? result : Array.Empty(); - } - } - - protected T[] GetAllObjects(IRepository repository) where T : IMapsDirectlyToDatabaseTable - { - lock (WriteLock) - { - return repository.GetAllObjects(); - } - } - - - protected void AddToReturnSearchablesWithNoDecendancy( - Dictionary toReturn, - IEnumerable toAdd) - { - lock (WriteLock) - { - foreach (var m in toAdd) - toReturn.Add(m, null); - } - } - - public virtual void UpdateTo(ICoreChildProvider other) - { - ArgumentNullException.ThrowIfNull(other); - - if (other is not CatalogueChildProvider otherCat) - throw new NotSupportedException( - $"Did not know how to UpdateTo ICoreChildProvider of type {other.GetType().Name}"); - - AllLoadMetadatas = otherCat.AllLoadMetadatas; - AllProcessTasks = otherCat.AllProcessTasks; - AllProcessTasksArguments = otherCat.AllProcessTasksArguments; - AllLoadProgresses = otherCat.AllLoadProgresses; - AllCacheProgresses = otherCat.AllCacheProgresses; - AllPermissionWindows = otherCat.AllPermissionWindows; - AllCatalogues = otherCat.AllCatalogues; - AllCataloguesDictionary = otherCat.AllCataloguesDictionary; - AllSupportingDocuments = otherCat.AllSupportingDocuments; - AllSupportingSQL = otherCat.AllSupportingSQL; - _childDictionary = otherCat._childDictionary; - _descendancyDictionary = otherCat._descendancyDictionary; - _catalogueToCatalogueItems = otherCat._catalogueToCatalogueItems; - AllCatalogueItemsDictionary = otherCat.AllCatalogueItemsDictionary; - _allColumnInfos = otherCat._allColumnInfos; - AllAggregateConfigurations = otherCat.AllAggregateConfigurations; - AllAggregateDimensions = otherCat.AllAggregateDimensions; - AllAggregateContinuousDateAxis = otherCat.AllAggregateContinuousDateAxis; - AllRDMPRemotesNode = otherCat.AllRDMPRemotesNode; - AllRemoteRDMPs = otherCat.AllRemoteRDMPs; - AllDashboardsNode = otherCat.AllDashboardsNode; - AllDashboards = otherCat.AllDashboards; - AllObjectSharingNode = otherCat.AllObjectSharingNode; - AllImports = otherCat.AllImports; - AllExports = otherCat.AllExports; - AllStandardRegexesNode = otherCat.AllStandardRegexesNode; - AllPipelinesNode = otherCat.AllPipelinesNode; - OtherPipelinesNode = otherCat.OtherPipelinesNode; - AllPipelines = otherCat.AllPipelines; - AllPipelineComponents = otherCat.AllPipelineComponents; - AllPipelineComponentsArguments = otherCat.AllPipelineComponentsArguments; - AllStandardRegexes = otherCat.AllStandardRegexes; - AllANOTablesNode = otherCat.AllANOTablesNode; - AllANOTables = otherCat.AllANOTables; - AllExternalServers = otherCat.AllExternalServers; - AllServers = otherCat.AllServers; - AllTableInfos = otherCat.AllTableInfos; - AllDataAccessCredentialsNode = otherCat.AllDataAccessCredentialsNode; - AllExternalServersNode = otherCat.AllExternalServersNode; - AllServersNode = otherCat.AllServersNode; - AllDataAccessCredentials = otherCat.AllDataAccessCredentials; - AllDataAccessCredentialUsages = otherCat.AllDataAccessCredentialUsages; - TableInfosToColumnInfos = otherCat.TableInfosToColumnInfos; - AllColumnInfos = otherCat.AllColumnInfos; - AllPreLoadDiscardedColumns = otherCat.AllPreLoadDiscardedColumns; - AllLookups = otherCat.AllLookups; - AllJoinInfos = otherCat.AllJoinInfos; - AllAnyTableParameters = otherCat.AllAnyTableParameters; - AllMasqueraders = otherCat.AllMasqueraders; - AllExtractionInformationsDictionary = otherCat.AllExtractionInformationsDictionary; - _pluginChildProviders = otherCat._pluginChildProviders; - AllPermissionWindowsNode = otherCat.AllPermissionWindowsNode; - LoadMetadataRootFolder = otherCat.LoadMetadataRootFolder; - CatalogueRootFolder = otherCat.CatalogueRootFolder; - CohortIdentificationConfigurationRootFolder = otherCat.CohortIdentificationConfigurationRootFolder; - AllConnectionStringKeywordsNode = otherCat.AllConnectionStringKeywordsNode; - AllConnectionStringKeywords = otherCat.AllConnectionStringKeywords; - AllAggregateContainersDictionary = otherCat.AllAggregateContainersDictionary; - AllAggregateFilters = otherCat.AllAggregateFilters; - AllAggregateFilterParameters = otherCat.AllAggregateFilterParameters; - AllCohortIdentificationConfigurations = otherCat.AllCohortIdentificationConfigurations; - AllCohortAggregateContainers = otherCat.AllCohortAggregateContainers; - AllJoinables = otherCat.AllJoinables; - AllJoinUses = otherCat.AllJoinUses; - AllGovernanceNode = otherCat.AllGovernanceNode; - AllGovernancePeriods = otherCat.AllGovernancePeriods; - AllGovernanceDocuments = otherCat.AllGovernanceDocuments; - GovernanceCoverage = otherCat.GovernanceCoverage; - AllJoinableCohortAggregateConfigurationUse = otherCat.AllJoinableCohortAggregateConfigurationUse; - AllPluginsNode = otherCat.AllPluginsNode; - PipelineUseCases = otherCat.PipelineUseCases; - OrphanAggregateConfigurationsNode = otherCat.OrphanAggregateConfigurationsNode; - TemplateAggregateConfigurationsNode = otherCat.TemplateAggregateConfigurationsNode; - AllCatalogueParameters = otherCat.AllCatalogueParameters; - AllCatalogueValueSets = otherCat.AllCatalogueValueSets; - AllCatalogueValueSetValues = otherCat.AllCatalogueValueSetValues; - OrphanAggregateConfigurations = otherCat.OrphanAggregateConfigurations; - } - - public virtual bool SelectiveRefresh(IMapsDirectlyToDatabaseTable databaseEntity) - { - ProgressStopwatch.Restart(); - - return databaseEntity switch - { - AggregateFilterParameter afp => SelectiveRefresh(afp.AggregateFilter), - AggregateFilter af => SelectiveRefresh(af), - AggregateFilterContainer afc => SelectiveRefresh(afc), - CohortAggregateContainer cac => SelectiveRefresh(cac), - ExtractionInformation ei => SelectiveRefresh(ei), - CatalogueItem ci => SelectiveRefresh(ci), - _ => false - }; - } - - - public bool SelectiveRefresh(CatalogueItem ci) - { - var descendancy = GetDescendancyListIfAnyFor(ci.Catalogue); - if (descendancy == null) return false; - - FetchCatalogueItems(); - FetchExtractionInformations(); - AddChildren(ci.Catalogue, descendancy.Add(ci.Catalogue)); - return true; - } - - public bool SelectiveRefresh(ExtractionInformation ei) - { - var descendancy = GetDescendancyListIfAnyFor(ei); - var cata = descendancy?.Parents.OfType().LastOrDefault() ?? ei.CatalogueItem.Catalogue; - - if (cata == null) - return false; - - var cataDescendancy = GetDescendancyListIfAnyFor(cata); - - if (cataDescendancy == null) - return false; - - FetchCatalogueItems(); - - foreach (var ci in AllCatalogueItems.Where(ci => ci.ID == ei.CatalogueItem_ID)) ci.ClearAllInjections(); - - // property changes or deleting the ExtractionInformation - FetchExtractionInformations(); - - // refresh the Catalogue - AddChildren(cata, cataDescendancy.Add(cata)); - return true; - } - - public bool SelectiveRefresh(CohortAggregateContainer container) - { - var parentContainer = container.GetParentContainerIfAny(); - if (parentContainer != null) - { - var descendancy = GetDescendancyListIfAnyFor(parentContainer); - - if (descendancy != null) - { - BuildAggregateConfigurations(); - - BuildCohortCohortAggregateContainers(); - AddChildren(parentContainer, descendancy.Add(parentContainer)); - return true; - } - } - - var cic = container.GetCohortIdentificationConfiguration(); - - if (cic != null) - { - var descendancy = GetDescendancyListIfAnyFor(cic); - - if (descendancy != null) - { - BuildAggregateConfigurations(); - BuildCohortCohortAggregateContainers(); - AddChildren(cic, descendancy.Add(cic)); - return true; - } - } - - return false; - } - - public bool SelectiveRefresh(AggregateFilter f) - { - var knownContainer = GetDescendancyListIfAnyFor(f.FilterContainer); - if (knownContainer == null) return false; - - BuildAggregateFilterContainers(); - AddChildren((AggregateFilterContainer)f.FilterContainer, knownContainer.Add(f.FilterContainer)); - return true; - } + children.Add(new DecryptionPrivateKeyNode(isKeyMissing)); + + foreach (var creds in AllDataAccessCredentials) + children.Add(creds); + + + AddToDictionaries(children, new DescendancyList(allDataAccessCredentialsNode)); + } + + private void AddChildren(AllANOTablesNode anoTablesNode) + { + AddToDictionaries(new HashSet(AllANOTables), new DescendancyList(anoTablesNode)); + } + + private void AddChildren(FolderNode folder, DescendancyList descendancy) + { + foreach (var child in folder.ChildFolders) + //add subfolder children + AddChildren(child, descendancy.Add(child)); + + //add catalogues in folder + foreach (var c in folder.ChildObjects) AddChildren(c, descendancy.Add(c)); + + // Children are the folders + objects + AddToDictionaries(new HashSet( + folder.ChildFolders.Cast() + .Union(folder.ChildObjects)), descendancy + ); + } + + private void AddChildren(FolderNode folder, DescendancyList descendancy) + { + foreach (var child in folder.ChildFolders) + //add subfolder children + AddChildren(child, descendancy.Add(child)); + + //add loads in folder + foreach (var lmd in folder.ChildObjects.Where(lmd => lmd.RootLoadMetadata_ID == null).ToArray()) AddChildren(lmd, descendancy.Add(lmd)); + // Children are the folders + objects + AddToDictionaries(new HashSet( + folder.ChildFolders.Cast() + .Union(folder.ChildObjects)), descendancy + ); + } + + private void AddChildren(FolderNode folder, DescendancyList descendancy) + { + foreach (var child in folder.ChildFolders) + //add subfolder children + AddChildren(child, descendancy.Add(child)); + + //add loads in folder + foreach (var ds in folder.ChildObjects) AddChildren(ds, descendancy.Add(ds)); + + // Children are the folders + objects + AddToDictionaries(new HashSet( + folder.ChildFolders.Cast() + .Union(folder.ChildObjects)), descendancy + ); + } + + private void AddChildren(FolderNode folder, DescendancyList descendancy) + { + foreach (var child in folder.ChildFolders) + //add subfolder children + AddChildren(child, descendancy.Add(child)); + + + //add cics in folder + foreach (var cic in folder.ChildObjects) AddChildren(cic, descendancy.Add(cic)); + + // Children are the folders + objects + AddToDictionaries(new HashSet( + folder.ChildFolders.Cast() + .Union(folder.ChildObjects)), descendancy + ); + } + + private void AddChildren(Curation.Data.Dataset lmd, DescendancyList descendancy) + { + var childObjects = new List(); + AddToDictionaries(new HashSet(childObjects), descendancy); + } + + + #region Load Metadata + + private void AddChildren(LoadMetadata lmd, DescendancyList descendancy, bool includeSchedule = true, bool includeCatalogues = true, bool includeVersions = true) + { + var childObjects = new List(); + + if (lmd.OverrideRAWServer_ID.HasValue) + { + var server = AllExternalServers.Single(s => s.ID == lmd.OverrideRAWServer_ID.Value); + var usage = new OverrideRawServerNode(lmd, server); + childObjects.Add(usage); + } + if (includeSchedule) + { + var allSchedulesNode = new LoadMetadataScheduleNode(lmd); + AddChildren(allSchedulesNode, descendancy.Add(allSchedulesNode)); + childObjects.Add(allSchedulesNode); + } + + if (includeCatalogues) + { + var allCataloguesNode = new AllCataloguesUsedByLoadMetadataNode(lmd); + AddChildren(allCataloguesNode, descendancy.Add(allCataloguesNode)); + childObjects.Add(allCataloguesNode); + } + + var processTasksNode = new AllProcessTasksUsedByLoadMetadataNode(lmd); + AddChildren(processTasksNode, descendancy.Add(processTasksNode)); + childObjects.Add(processTasksNode); + + if (includeVersions) + { + var versionsNode = new LoadMetadataVersionNode(lmd); + AddChildren(versionsNode, descendancy.Add(versionsNode)); + childObjects.Add(versionsNode); + } + + childObjects.Add(new LoadDirectoryNode(lmd)); + + AddToDictionaries(new HashSet(childObjects), descendancy); + } + + private void AddChildren(LoadMetadataScheduleNode allSchedulesNode, DescendancyList descendancy) + { + var childObjects = new HashSet(); + + var lmd = allSchedulesNode.LoadMetadata; + + foreach (var lp in AllLoadProgresses.Where(p => p.LoadMetadata_ID == lmd.ID)) + { + AddChildren(lp, descendancy.Add(lp)); + childObjects.Add(lp); + } + + if (childObjects.Any()) + AddToDictionaries(childObjects, descendancy); + } + + private void AddChildren(LoadProgress loadProgress, DescendancyList descendancy) + { + var cacheProgresses = AllCacheProgresses.Where(cp => cp.LoadProgress_ID == loadProgress.ID).ToArray(); + + foreach (var cacheProgress in cacheProgresses) + AddChildren(cacheProgress, descendancy.Add(cacheProgress)); + + if (cacheProgresses.Any()) + AddToDictionaries(new HashSet(cacheProgresses), descendancy); + } + + private void AddChildren(CacheProgress cacheProgress, DescendancyList descendancy) + { + var children = new HashSet(); + + if (cacheProgress.PermissionWindow_ID != null) + { + var window = AllPermissionWindows.Single(w => w.ID == cacheProgress.PermissionWindow_ID); + var windowNode = new PermissionWindowUsedByCacheProgressNode(cacheProgress, window, true); + + children.Add(windowNode); + } + + if (children.Any()) + AddToDictionaries(children, descendancy); + } + + private void AddChildren(AllProcessTasksUsedByLoadMetadataNode allProcessTasksUsedByLoadMetadataNode, + DescendancyList descendancy) + { + var childObjects = new HashSet(); + + var lmd = allProcessTasksUsedByLoadMetadataNode.LoadMetadata; + childObjects.Add(new LoadStageNode(lmd, LoadStage.GetFiles)); + childObjects.Add(new LoadStageNode(lmd, LoadStage.Mounting)); + childObjects.Add(new LoadStageNode(lmd, LoadStage.AdjustRaw)); + childObjects.Add(new LoadStageNode(lmd, LoadStage.AdjustStaging)); + childObjects.Add(new LoadStageNode(lmd, LoadStage.PostLoad)); + + foreach (LoadStageNode node in childObjects) + AddChildren(node, descendancy.Add(node)); + + AddToDictionaries(childObjects, descendancy); + } + + private void AddChildren(LoadStageNode loadStageNode, DescendancyList descendancy) + { + var tasks = AllProcessTasks.Where( + p => p.LoadMetadata_ID == loadStageNode.LoadMetadata.ID && p.LoadStage == loadStageNode.LoadStage) + .OrderBy(o => o.Order).ToArray(); + + foreach (var processTask in tasks) + AddChildren(processTask, descendancy.Add(processTask)); + + if (tasks.Any()) + AddToDictionaries(new HashSet(tasks), descendancy); + } + + private void AddChildren(ProcessTask procesTask, DescendancyList descendancy) + { + var args = AllProcessTasksArguments.Where( + a => a.ProcessTask_ID == procesTask.ID).ToArray(); + + if (args.Any()) + AddToDictionaries(new HashSet(args), descendancy); + } + + private void AddChildren(LoadMetadataVersionNode LoadMetadataVersionNode, DescendancyList descendancy) + { + LoadMetadataVersionNode.LoadMetadataVersions = AllLoadMetadatas.Where(lmd => lmd.RootLoadMetadata_ID == LoadMetadataVersionNode.LoadMetadata.ID).ToList(); + var childObjects = new List(); + + foreach (var lmd in LoadMetadataVersionNode.LoadMetadataVersions) + { + AddChildren(lmd, descendancy.Add(lmd), false, false, false); + childObjects.Add(lmd); + } + AddToDictionaries(new HashSet(childObjects), descendancy); + + } + + private void AddChildren(AllCataloguesUsedByLoadMetadataNode allCataloguesUsedByLoadMetadataNode, + DescendancyList descendancy) + { + var loadMetadataId = allCataloguesUsedByLoadMetadataNode.LoadMetadata.ID; + var linkedCatalogueIDs = AllLoadMetadataLinkage.Where(link => link.LoadMetadataID == loadMetadataId).Select(static link => link.CatalogueID); + var usedCatalogues = linkedCatalogueIDs.Select(catalogueId => AllCatalogues.FirstOrDefault(c => c.ID == catalogueId)).Where(static foundCatalogue => foundCatalogue is not null).ToList(); + allCataloguesUsedByLoadMetadataNode.UsedCatalogues = usedCatalogues; + var childObjects = usedCatalogues.Select(foundCatalogue => new CatalogueUsedByLoadMetadataNode(allCataloguesUsedByLoadMetadataNode.LoadMetadata, foundCatalogue)).Cast().ToHashSet(); + + AddToDictionaries(childObjects, descendancy); + } + + #endregion + + protected void AddChildren(Catalogue c, DescendancyList descendancy) + { + var childObjects = new List(); + + var catalogueAggregates = AllAggregateConfigurations.Where(a => a.Catalogue_ID == c.ID).ToArray(); + var cohortAggregates = catalogueAggregates.Where(a => a.IsCohortIdentificationAggregate).ToArray(); + var regularAggregates = catalogueAggregates.Except(cohortAggregates).ToArray(); + + //get all the CatalogueItems for this Catalogue (TryGet because Catalogue may not have any items + var cis = _catalogueToCatalogueItems.TryGetValue(c.ID, out var result) + ? result.ToArray() + : Array.Empty(); + + //tell the CatalogueItems that we are are their parent + foreach (var ci in cis) + ci.InjectKnown(c); + + // core includes project specific which basically means the same thing + var core = new CatalogueItemsNode(c, + cis.Where(ci => ci.ExtractionInformation?.ExtractionCategory == ExtractionCategory.Core || + ci.ExtractionInformation?.ExtractionCategory == ExtractionCategory.ProjectSpecific) + , ExtractionCategory.Core); + + c.InjectKnown(cis); + + var deprecated = new CatalogueItemsNode(c, + cis.Where(ci => ci.ExtractionInformation?.ExtractionCategory == ExtractionCategory.Deprecated), + ExtractionCategory.Deprecated); + var special = new CatalogueItemsNode(c, + cis.Where(ci => ci.ExtractionInformation?.ExtractionCategory == ExtractionCategory.SpecialApprovalRequired), + ExtractionCategory.SpecialApprovalRequired); + var intern = new CatalogueItemsNode(c, + cis.Where(ci => ci.ExtractionInformation?.ExtractionCategory == ExtractionCategory.Internal), + ExtractionCategory.Internal); + var supplemental = new CatalogueItemsNode(c, + cis.Where(ci => ci.ExtractionInformation?.ExtractionCategory == ExtractionCategory.Supplemental), + ExtractionCategory.Supplemental); + var notExtractable = new CatalogueItemsNode(c, cis.Where(ci => ci.ExtractionInformation == null), null); + + AddChildren(core, descendancy.Add(core)); + childObjects.Add(core); + + foreach (var optional in new[] { deprecated, special, intern, supplemental, notExtractable }) + if (optional.CatalogueItems.Any()) + { + AddChildren(optional, descendancy.Add(optional)); + childObjects.Add(optional); + } + + //do we have any foreign key fields into this lookup table + var lookups = AllLookups.Where(l => c.CatalogueItems.Any(ci => ci.ColumnInfo_ID == l.ForeignKey_ID)).ToArray(); + + var docs = AllSupportingDocuments.Where(d => d.Catalogue_ID == c.ID).ToArray(); + var sql = AllSupportingSQL.Where(d => d.Catalogue_ID == c.ID).ToArray(); + + //if there are supporting documents or supporting sql files then add documentation node + if (docs.Any() || sql.Any()) + { + var documentationNode = new DocumentationNode(c, docs, sql); + + //add the documentations node + childObjects.Add(documentationNode); + + //record the children + AddToDictionaries(new HashSet(docs.Cast().Union(sql)), descendancy.Add(documentationNode)); + } + + if (lookups.Any()) + { + var lookupsNode = new CatalogueLookupsNode(c, lookups); + //add the documentations node + childObjects.Add(lookupsNode); + + + //record the children + AddToDictionaries(new HashSet(lookups.Select(l => new CatalogueLookupUsageNode(c, l))), + descendancy.Add(lookupsNode)); + } + + if (regularAggregates.Any()) + { + var aggregatesNode = new AggregatesNode(c, regularAggregates); + childObjects.Add(aggregatesNode); + + var nodeDescendancy = descendancy.Add(aggregatesNode); + AddToDictionaries(new HashSet(regularAggregates), nodeDescendancy); + + foreach (var regularAggregate in regularAggregates) + AddChildren(regularAggregate, nodeDescendancy.Add(regularAggregate)); + } + + //finalise + AddToDictionaries(new HashSet(childObjects), descendancy); + } + + private void InjectCatalogueItems() + { + foreach (var ci in AllCatalogueItems) + if (_extractionInformationsByCatalogueItem.TryGetValue(ci.ID, out var ei)) + ci.InjectKnown(ei); + else + ci.InjectKnown((ExtractionInformation)null); + } + + private void AddChildren(CatalogueItemsNode node, DescendancyList descendancyList) + { + AddToDictionaries(new HashSet(node.CatalogueItems), descendancyList); + + foreach (var ci in node.CatalogueItems) + AddChildren(ci, descendancyList.Add(ci)); + } + + private void AddChildren(AggregateConfiguration aggregateConfiguration, DescendancyList descendancy) + { + var childrenObjects = new HashSet(); + + var parameters = AllAnyTableParameters.Where(p => p.IsReferenceTo(aggregateConfiguration)).Cast() + .ToArray(); + + foreach (var p in parameters) + childrenObjects.Add(p); + + // show the dimensions in the tree + foreach (var dim in aggregateConfiguration.AggregateDimensions) childrenObjects.Add(dim); + + // show the axis (if any) in the tree. If there are multiple axis in this tree then that is bad but maybe the user can delete one of them to fix the situation + foreach (var axis in AllAggregateContinuousDateAxis.Where(a => + aggregateConfiguration.AggregateDimensions.Any(d => d.ID == a.AggregateDimension_ID))) + childrenObjects.Add(axis); + + //we can step into this twice, once via Catalogue children and once via CohortIdentificationConfiguration children + //if we get in via Catalogue children then descendancy will be Ignore=true we don't end up emphasising into CatalogueCollectionUI when + //really user wants to see it in CohortIdentificationCollectionUI + if (aggregateConfiguration.RootFilterContainer_ID != null) + { + var container = AllAggregateContainersDictionary[(int)aggregateConfiguration.RootFilterContainer_ID]; + + AddChildren(container, descendancy.Add(container)); + childrenObjects.Add(container); + } + + AddToDictionaries(childrenObjects, descendancy); + } + + private void AddChildren(AggregateFilterContainer container, DescendancyList descendancy) + { + var childrenObjects = new List(); + + var subcontainers = _aggregateFilterManager.GetSubContainers(container); + var filters = _aggregateFilterManager.GetFilters(container); + + foreach (AggregateFilterContainer subcontainer in subcontainers) + { + //one of our children is this subcontainer + childrenObjects.Add(subcontainer); + + //but also document its children + AddChildren(subcontainer, descendancy.Add(subcontainer)); + } + + //also add the filters for the container + foreach (var f in filters) + { + // for filters add the parameters under them + AddChildren((AggregateFilter)f, descendancy.Add(f)); + childrenObjects.Add(f); + } + + //add our children to the dictionary + AddToDictionaries(new HashSet(childrenObjects), descendancy); + } + + private void AddChildren(AggregateFilter f, DescendancyList descendancy) + { + AddToDictionaries(new HashSet(AllAggregateFilterParameters.Where(p => p.AggregateFilter_ID == f.ID)), + descendancy); + } + + private void AddChildren(CatalogueItem ci, DescendancyList descendancy) + { + var childObjects = new List(); + + var ei = ci.ExtractionInformation; + if (ei != null) + { + childObjects.Add(ei); + AddChildren(ei, descendancy.Add(ei)); + } + else + { + ci.InjectKnown( + (ExtractionInformation)null); // we know the CatalogueItem has no ExtractionInformation child because it's not in the dictionary + } + + if (ci.ColumnInfo_ID.HasValue && _allColumnInfos.TryGetValue(ci.ColumnInfo_ID.Value, out var col)) + childObjects.Add(new LinkedColumnInfoNode(ci, col)); + + AddToDictionaries(new HashSet(childObjects), descendancy); + } + + private void AddChildren(ExtractionInformation extractionInformation, DescendancyList descendancy) + { + var children = new HashSet(); + + foreach (var filter in AllCatalogueFilters.Where(f => f.ExtractionInformation_ID == extractionInformation.ID)) + { + //add the filter as a child of the + children.Add(filter); + AddChildren(filter, descendancy.Add(filter)); + } + + AddToDictionaries(children, descendancy); + } + + private void AddChildren(ExtractionFilter filter, DescendancyList descendancy) + { + var children = new HashSet(); + var parameters = AllCatalogueParameters.Where(p => p.ExtractionFilter_ID == filter.ID).ToArray(); + var parameterSets = AllCatalogueValueSets.Where(vs => vs.ExtractionFilter_ID == filter.ID).ToArray(); + + filter.InjectKnown(parameterSets); + + foreach (var p in parameters) + children.Add(p); + + foreach (var set in parameterSets) + { + children.Add(set); + AddChildren(set, descendancy.Add(set), parameters); + } + + if (children.Any()) + AddToDictionaries(children, descendancy); + } + + private void AddChildren(ExtractionFilterParameterSet set, DescendancyList descendancy, + ExtractionFilterParameter[] filterParameters) + { + var children = new HashSet(); + + foreach (var setValue in AllCatalogueValueSetValues.Where(v => v.ExtractionFilterParameterSet_ID == set.ID)) + { + setValue.InjectKnown(filterParameters.SingleOrDefault(p => p.ID == setValue.ExtractionFilterParameter_ID)); + children.Add(setValue); + } + + AddToDictionaries(children, descendancy); + } + + private void AddChildren(CohortIdentificationConfiguration cic, DescendancyList descendancy) + { + var children = new HashSet(); + + //it has an associated query cache + if (cic.QueryCachingServer_ID != null) + children.Add(new QueryCacheUsedByCohortIdentificationNode(cic, + AllExternalServers.Single(s => s.ID == cic.QueryCachingServer_ID))); + + var parameters = AllAnyTableParameters.Where(p => p.IsReferenceTo(cic)).Cast().ToArray(); + foreach (var p in parameters) children.Add(p); + + //if it has a root container + if (cic.RootCohortAggregateContainer_ID != null) + { + var container = AllCohortAggregateContainers.Single(c => c.ID == cic.RootCohortAggregateContainer_ID); + AddChildren(container, descendancy.Add(container).SetBetterRouteExists()); + children.Add(container); + } + + //get the patient index tables + var joinableNode = new JoinableCollectionNode(cic, + AllJoinables.Where(j => j.CohortIdentificationConfiguration_ID == cic.ID).ToArray()); + AddChildren(joinableNode, descendancy.Add(joinableNode).SetBetterRouteExists()); + children.Add(joinableNode); + + AddToDictionaries(children, descendancy.SetBetterRouteExists()); + } + + private void AddChildren(JoinableCollectionNode joinablesNode, DescendancyList descendancy) + { + var children = new HashSet(); + + foreach (var joinable in joinablesNode.Joinables) + try + { + var agg = AllAggregateConfigurations.Single(ac => ac.ID == joinable.AggregateConfiguration_ID); + ForceAggregateNaming(agg, descendancy); + children.Add(agg); + + //it's no longer an orphan because it's in a known cic (as a patient index table) + OrphanAggregateConfigurations.Remove(agg); + + AddChildren(agg, descendancy.Add(agg)); + } + catch (Exception e) + { + throw new Exception( + $"JoinableCohortAggregateConfiguration (patient index table) object (ID={joinable.ID}) references AggregateConfiguration_ID {joinable.AggregateConfiguration_ID} but that AggregateConfiguration was not found", + e); + } + + AddToDictionaries(children, descendancy); + } + + private void AddChildren(CohortAggregateContainer container, DescendancyList descendancy) + { + //get subcontainers + var subcontainers = _cohortContainerManager.GetChildren(container).OfType().ToList(); + + //if there are subcontainers + foreach (var subcontainer in subcontainers) + AddChildren(subcontainer, descendancy.Add(subcontainer)); + + //get our configurations + var configurations = _cohortContainerManager.GetChildren(container).OfType().ToList(); + + //record the configurations children including full descendancy + foreach (var configuration in configurations) + { + ForceAggregateNaming(configuration, descendancy); + AddChildren(configuration, descendancy.Add(configuration)); + + //it's no longer an orphan because it's in a known cic + OrphanAggregateConfigurations.Remove(configuration); + } + + //all our children (containers and aggregates) + //children are all aggregates and containers at the current hierarchy level in order + var children = subcontainers.Union(configurations.Cast()).OrderBy(o => o.Order).ToList(); + + AddToDictionaries(new HashSet(children), descendancy); + } + + private void ForceAggregateNaming(AggregateConfiguration configuration, DescendancyList descendancy) + { + //configuration has the wrong name + if (!configuration.IsCohortIdentificationAggregate) + { + _errorsCheckNotifier.OnCheckPerformed(new CheckEventArgs( + $"Had to fix naming of configuration '{configuration}' because it didn't start with correct cic prefix", + CheckResult.Warning)); + descendancy.Parents.OfType().Single() + .EnsureNamingConvention(configuration); + configuration.SaveToDatabase(); + } + } + + private void AddChildren(TableInfoServerNode serverNode, DescendancyList descendancy) + { + //add empty hashset + var children = new HashSet(); + + var databases = + serverNode.Tables.GroupBy( + k => k.Database ?? TableInfoDatabaseNode.NullDatabaseNode, StringComparer.CurrentCultureIgnoreCase) + .Select(g => new TableInfoDatabaseNode(g.Key, serverNode, g)); + + foreach (var db in databases) + { + children.Add(db); + AddChildren(db, descendancy.Add(db)); + } + + //now we have recorded all the children add them with descendancy + AddToDictionaries(children, descendancy); + } + + private void AddChildren(TableInfoDatabaseNode dbNode, DescendancyList descendancy) + { + //add empty hashset + var children = new HashSet(); + + foreach (var t in dbNode.Tables) + { + //record the children of the table infos (mostly column infos) + children.Add(t); + + //the all servers node=>the TableInfoServerNode => the t + AddChildren(t, descendancy.Add(t)); + } + + //now we have recorded all the children add them with descendancy + AddToDictionaries(children, descendancy); + } + + private void AddChildren(TableInfo tableInfo, DescendancyList descendancy) + { + //add empty hashset + var children = new HashSet(); + + //if the table has an identifier dump listed + if (tableInfo.IdentifierDumpServer_ID != null) + { + //if there is a dump (e.g. for dilution and dumping - not appearing in the live table) + var server = AllExternalServers.Single(s => s.ID == tableInfo.IdentifierDumpServer_ID.Value); + + children.Add(new IdentifierDumpServerUsageNode(tableInfo, server)); + } + + //get the discarded columns in this table + var discardedCols = new HashSet(AllPreLoadDiscardedColumns.Where(c => c.TableInfo_ID == tableInfo.ID)); + + //tell the column who their parent is so they don't need to look up the database + foreach (PreLoadDiscardedColumn discardedCol in discardedCols) + discardedCol.InjectKnown(tableInfo); + + //if there are discarded columns + if (discardedCols.Any()) + { + var identifierDumpNode = new PreLoadDiscardedColumnsNode(tableInfo); + + //record that the usage is a child of TableInfo + children.Add(identifierDumpNode); + + //record that the discarded columns are children of identifier dump usage node + AddToDictionaries(discardedCols, descendancy.Add(identifierDumpNode)); + } + + //if it is a table valued function + if (tableInfo.IsTableValuedFunction) + { + //that has parameters + var parameters = tableInfo.GetAllParameters(); + + foreach (var p in parameters) children.Add(p); + } + + //next add the column infos + if (TableInfosToColumnInfos.TryGetValue(tableInfo.ID, out var result)) + foreach (var c in result) + { + children.Add(c); + c.InjectKnown(tableInfo); + AddChildren(c, descendancy.Add(c).SetBetterRouteExists()); + } + + //finally add any credentials objects + if (AllDataAccessCredentialUsages.TryGetValue(tableInfo, out var nodes)) + foreach (var node in nodes) + children.Add(node); + + //now we have recorded all the children add them with descendancy via the TableInfo descendancy + AddToDictionaries(children, descendancy); + } + + private void AddChildren(ColumnInfo columnInfo, DescendancyList descendancy) + { + var lookups = AllLookups.Where(l => l.Description_ID == columnInfo.ID).ToArray(); + var joinInfos = AllJoinInfos.Where(j => j.PrimaryKey_ID == columnInfo.ID); + + var children = new HashSet(); + + foreach (var l in lookups) + children.Add(l); + + foreach (var j in joinInfos) + children.Add(j); + + if (children.Any()) + AddToDictionaries(children, descendancy); + } + + protected void AddToDictionaries(HashSet children, DescendancyList list) + { + if (list.IsEmpty) + throw new ArgumentException("DescendancyList cannot be empty", nameof(list)); + + //document that the last parent has these as children + var parent = list.Last(); + + _childDictionary.AddOrUpdate(parent, + children, (p, s) => children); + + //now document the entire parent order to reach each child object i.e. 'Root=>Grandparent=>Parent' is how you get to 'Child' + foreach (var o in children) + _descendancyDictionary.AddOrUpdate(o, list, (k, v) => HandleDescendancyCollision(k, v, list)); + + + foreach (var masquerader in children.OfType()) + { + var key = masquerader.MasqueradingAs(); + + if (!AllMasqueraders.ContainsKey(key)) + AllMasqueraders.AddOrUpdate(key, new HashSet(), (o, set) => set); + + lock (AllMasqueraders) + { + AllMasqueraders[key].Add(masquerader); + } + } + } + + private static DescendancyList HandleDescendancyCollision(object key, DescendancyList oldRoute, + DescendancyList newRoute) + { + //if the new route is the best best + if (newRoute.NewBestRoute && !oldRoute.NewBestRoute) + return newRoute; + + // If the new one is marked BetterRouteExists just throw away the new one + return newRoute.BetterRouteExists ? oldRoute : newRoute; + // If in doubt use the newest one + } + + private HashSet GetAllObjects() + { + //anything which has children or is a child of someone else (distinct because HashSet) + return new HashSet(_childDictionary.SelectMany(kvp => kvp.Value).Union(_childDictionary.Keys)); + } + + public virtual object[] GetChildren(object model) + { + lock (WriteLock) + { + //if we have a record of any children in the child dictionary for the parent model object + if (_childDictionary.TryGetValue(model, out var cached)) + return cached.OrderBy(static o => o.ToString()).ToArray(); + + return model switch + { + //if they want the children of a Pipeline (which we don't track) just serve the components + Pipeline p => p.PipelineComponents.ToArray(), + //if they want the children of a PipelineComponent (which we don't track) just serve the arguments + PipelineComponent pc => pc.PipelineComponentArguments.ToArray(), + _ => Array.Empty() + }; + } + } + + public IEnumerable GetAllObjects(Type type, bool unwrapMasqueraders) + { + lock (WriteLock) + { + //things that are a match on Type but not IMasqueradeAs + var exactMatches = GetAllSearchables().Keys.Where(t => t is not IMasqueradeAs).Where(type.IsInstanceOfType); + + //Union the unwrapped masqueraders + return unwrapMasqueraders + ? exactMatches.Union( + AllMasqueraders + .Select(kvp => kvp.Key) + .OfType() + .Where(type.IsInstanceOfType)) + .Distinct() + : exactMatches; + } + } + + public DescendancyList GetDescendancyListIfAnyFor(object model) + { + lock (WriteLock) + { + return _descendancyDictionary.GetValueOrDefault(model); + } + } + + + public object GetRootObjectOrSelf(object objectToEmphasise) + { + lock (WriteLock) + { + var descendancy = GetDescendancyListIfAnyFor(objectToEmphasise); + + return descendancy != null && descendancy.Parents.Any() ? descendancy.Parents[0] : objectToEmphasise; + } + } + + + public virtual Dictionary GetAllSearchables() + { + lock (WriteLock) + { + var toReturn = new Dictionary(); + + foreach (var kvp in _descendancyDictionary.Where(kvp => kvp.Key is IMapsDirectlyToDatabaseTable)) + toReturn.Add((IMapsDirectlyToDatabaseTable)kvp.Key, kvp.Value); + + return toReturn; + } + } + + public IEnumerable GetAllChildrenRecursively(object o) + { + lock (WriteLock) + { + var toReturn = new List(); + + foreach (var child in GetChildren(o)) + { + toReturn.Add(child); + toReturn.AddRange(GetAllChildrenRecursively(child)); + } + + return toReturn; + } + } + + /// + /// Asks all plugins to provide the child objects for every object we have found so far. This method is recursive, call it with null the first time to use all objects. It will then + /// call itself with all the new objects that were sent back by the plugin (so that new objects found can still have children). + /// + /// + protected void GetPluginChildren(HashSet objectsToAskAbout = null) + { + lock (WriteLock) + { + var newObjectsFound = new HashSet(); + + var sw = new Stopwatch(); + + var providers = _pluginChildProviders.Except(_blockedPlugins).ToArray(); + + //for every object found so far + if (providers.Any()) + foreach (var o in objectsToAskAbout ?? GetAllObjects()) + //for every plugin loaded (that is not forbidlisted) + foreach (var plugin in providers) + //ask about the children + try + { + sw.Restart(); + //otherwise ask plugin what its children are + var pluginChildren = plugin.GetChildren(o); + + //if the plugin takes too long to respond we need to stop + if (sw.ElapsedMilliseconds > 1000) + { + _blockedPlugins.Add(plugin); + throw new Exception( + $"Plugin '{plugin}' was forbidlisted for taking too long to respond to GetChildren(o) where o was a '{o.GetType().Name}' ('{o}')"); + } + + //it has children + if (pluginChildren != null && pluginChildren.Any()) + { + //get the descendancy of the parent + var parentDescendancy = GetDescendancyListIfAnyFor(o); + var newDescendancy = parentDescendancy == null + ? new DescendancyList(o) + : //if the parent is a root level object start a new descendancy list from it + parentDescendancy + .Add(o); //otherwise keep going down, returns a new DescendancyList so doesn't corrupt the dictionary one + newDescendancy = + parentDescendancy + .Add(o); //otherwise keep going down, returns a new DescendancyList so doesn't corrupt the dictionary one + + //record that + foreach (var pluginChild in pluginChildren) + { + //if the parent didn't have any children before + if (!_childDictionary.ContainsKey(o)) + _childDictionary.AddOrUpdate(o, new HashSet(), + (o1, set) => set); //it does now + + + //add us to the parent objects child collection + _childDictionary[o].Add(pluginChild); + + //add to the child collection of the parent object kvp.Key + _descendancyDictionary.AddOrUpdate(pluginChild, newDescendancy, + (s, e) => newDescendancy); + + //we have found a new object so we must ask other plugins about it (chances are a plugin will have a whole tree of sub objects) + newObjectsFound.Add(pluginChild); + } + } + } + catch (Exception e) + { + _errorsCheckNotifier.OnCheckPerformed(new CheckEventArgs(e.Message, CheckResult.Fail, e)); + } + + if (newObjectsFound.Any()) + GetPluginChildren(newObjectsFound); + } + } + + public IEnumerable GetMasqueradersOf(object o) + { + lock (WriteLock) + { + return AllMasqueraders.TryGetValue(o, out var result) ? result : Array.Empty(); + } + } + + protected T[] GetAllObjects(IRepository repository) where T : IMapsDirectlyToDatabaseTable + { + lock (WriteLock) + { + return repository.GetAllObjects(); + } + } + + + protected void AddToReturnSearchablesWithNoDecendancy( + Dictionary toReturn, + IEnumerable toAdd) + { + lock (WriteLock) + { + foreach (var m in toAdd) + toReturn.Add(m, null); + } + } + + public virtual void UpdateTo(ICoreChildProvider other) + { + ArgumentNullException.ThrowIfNull(other); + + if (other is not CatalogueChildProvider otherCat) + throw new NotSupportedException( + $"Did not know how to UpdateTo ICoreChildProvider of type {other.GetType().Name}"); + + AllLoadMetadatas = otherCat.AllLoadMetadatas; + AllProcessTasks = otherCat.AllProcessTasks; + AllProcessTasksArguments = otherCat.AllProcessTasksArguments; + AllLoadProgresses = otherCat.AllLoadProgresses; + AllCacheProgresses = otherCat.AllCacheProgresses; + AllPermissionWindows = otherCat.AllPermissionWindows; + AllCatalogues = otherCat.AllCatalogues; + AllCataloguesDictionary = otherCat.AllCataloguesDictionary; + AllSupportingDocuments = otherCat.AllSupportingDocuments; + AllSupportingSQL = otherCat.AllSupportingSQL; + _childDictionary = otherCat._childDictionary; + _descendancyDictionary = otherCat._descendancyDictionary; + _catalogueToCatalogueItems = otherCat._catalogueToCatalogueItems; + AllCatalogueItemsDictionary = otherCat.AllCatalogueItemsDictionary; + _allColumnInfos = otherCat._allColumnInfos; + AllAggregateConfigurations = otherCat.AllAggregateConfigurations; + AllAggregateDimensions = otherCat.AllAggregateDimensions; + AllAggregateContinuousDateAxis = otherCat.AllAggregateContinuousDateAxis; + AllRDMPRemotesNode = otherCat.AllRDMPRemotesNode; + AllRemoteRDMPs = otherCat.AllRemoteRDMPs; + AllDashboardsNode = otherCat.AllDashboardsNode; + AllDashboards = otherCat.AllDashboards; + AllObjectSharingNode = otherCat.AllObjectSharingNode; + AllImports = otherCat.AllImports; + AllExports = otherCat.AllExports; + AllStandardRegexesNode = otherCat.AllStandardRegexesNode; + AllPipelinesNode = otherCat.AllPipelinesNode; + OtherPipelinesNode = otherCat.OtherPipelinesNode; + AllPipelines = otherCat.AllPipelines; + AllPipelineComponents = otherCat.AllPipelineComponents; + AllPipelineComponentsArguments = otherCat.AllPipelineComponentsArguments; + AllStandardRegexes = otherCat.AllStandardRegexes; + AllANOTablesNode = otherCat.AllANOTablesNode; + AllANOTables = otherCat.AllANOTables; + AllExternalServers = otherCat.AllExternalServers; + AllServers = otherCat.AllServers; + AllTableInfos = otherCat.AllTableInfos; + AllDataAccessCredentialsNode = otherCat.AllDataAccessCredentialsNode; + AllExternalServersNode = otherCat.AllExternalServersNode; + AllServersNode = otherCat.AllServersNode; + AllDataAccessCredentials = otherCat.AllDataAccessCredentials; + AllDataAccessCredentialUsages = otherCat.AllDataAccessCredentialUsages; + TableInfosToColumnInfos = otherCat.TableInfosToColumnInfos; + AllColumnInfos = otherCat.AllColumnInfos; + AllPreLoadDiscardedColumns = otherCat.AllPreLoadDiscardedColumns; + AllLookups = otherCat.AllLookups; + AllJoinInfos = otherCat.AllJoinInfos; + AllAnyTableParameters = otherCat.AllAnyTableParameters; + AllMasqueraders = otherCat.AllMasqueraders; + AllExtractionInformationsDictionary = otherCat.AllExtractionInformationsDictionary; + _pluginChildProviders = otherCat._pluginChildProviders; + AllPermissionWindowsNode = otherCat.AllPermissionWindowsNode; + LoadMetadataRootFolder = otherCat.LoadMetadataRootFolder; + CatalogueRootFolder = otherCat.CatalogueRootFolder; + CohortIdentificationConfigurationRootFolder = otherCat.CohortIdentificationConfigurationRootFolder; + AllConnectionStringKeywordsNode = otherCat.AllConnectionStringKeywordsNode; + AllConnectionStringKeywords = otherCat.AllConnectionStringKeywords; + AllAggregateContainersDictionary = otherCat.AllAggregateContainersDictionary; + AllAggregateFilters = otherCat.AllAggregateFilters; + AllAggregateFilterParameters = otherCat.AllAggregateFilterParameters; + AllCohortIdentificationConfigurations = otherCat.AllCohortIdentificationConfigurations; + AllCohortAggregateContainers = otherCat.AllCohortAggregateContainers; + AllJoinables = otherCat.AllJoinables; + AllJoinUses = otherCat.AllJoinUses; + AllGovernanceNode = otherCat.AllGovernanceNode; + AllGovernancePeriods = otherCat.AllGovernancePeriods; + AllGovernanceDocuments = otherCat.AllGovernanceDocuments; + GovernanceCoverage = otherCat.GovernanceCoverage; + AllJoinableCohortAggregateConfigurationUse = otherCat.AllJoinableCohortAggregateConfigurationUse; + AllPluginsNode = otherCat.AllPluginsNode; + PipelineUseCases = otherCat.PipelineUseCases; + OrphanAggregateConfigurationsNode = otherCat.OrphanAggregateConfigurationsNode; + TemplateAggregateConfigurationsNode = otherCat.TemplateAggregateConfigurationsNode; + AllCatalogueParameters = otherCat.AllCatalogueParameters; + AllCatalogueValueSets = otherCat.AllCatalogueValueSets; + AllCatalogueValueSetValues = otherCat.AllCatalogueValueSetValues; + OrphanAggregateConfigurations = otherCat.OrphanAggregateConfigurations; + } + + public virtual bool SelectiveRefresh(IMapsDirectlyToDatabaseTable databaseEntity) + { + ProgressStopwatch.Restart(); + + return databaseEntity switch + { + AggregateFilterParameter afp => SelectiveRefresh(afp.AggregateFilter), + AggregateFilter af => SelectiveRefresh(af), + AggregateFilterContainer afc => SelectiveRefresh(afc), + CohortAggregateContainer cac => SelectiveRefresh(cac), + ExtractionInformation ei => SelectiveRefresh(ei), + CatalogueItem ci => SelectiveRefresh(ci), + _ => false + }; + } + + + public bool SelectiveRefresh(CatalogueItem ci) + { + var descendancy = GetDescendancyListIfAnyFor(ci.Catalogue); + if (descendancy == null) return false; + + FetchCatalogueItems(); + FetchExtractionInformations(); + AddChildren(ci.Catalogue, descendancy.Add(ci.Catalogue)); + return true; + } + + public bool SelectiveRefresh(ExtractionInformation ei) + { + var descendancy = GetDescendancyListIfAnyFor(ei); + var cata = descendancy?.Parents.OfType().LastOrDefault() ?? ei.CatalogueItem.Catalogue; + + if (cata == null) + return false; + + var cataDescendancy = GetDescendancyListIfAnyFor(cata); + + if (cataDescendancy == null) + return false; + + FetchCatalogueItems(); + + foreach (var ci in AllCatalogueItems.Where(ci => ci.ID == ei.CatalogueItem_ID)) ci.ClearAllInjections(); + + // property changes or deleting the ExtractionInformation + FetchExtractionInformations(); + + // refresh the Catalogue + AddChildren(cata, cataDescendancy.Add(cata)); + return true; + } + + public bool SelectiveRefresh(CohortAggregateContainer container) + { + var parentContainer = container.GetParentContainerIfAny(); + if (parentContainer != null) + { + var descendancy = GetDescendancyListIfAnyFor(parentContainer); + + if (descendancy != null) + { + BuildAggregateConfigurations(); + + BuildCohortCohortAggregateContainers(); + AddChildren(parentContainer, descendancy.Add(parentContainer)); + return true; + } + } + + var cic = container.GetCohortIdentificationConfiguration(); + + if (cic != null) + { + var descendancy = GetDescendancyListIfAnyFor(cic); + + if (descendancy != null) + { + BuildAggregateConfigurations(); + BuildCohortCohortAggregateContainers(); + AddChildren(cic, descendancy.Add(cic)); + return true; + } + } + + return false; + } + + public bool SelectiveRefresh(AggregateFilter f) + { + var knownContainer = GetDescendancyListIfAnyFor(f.FilterContainer); + if (knownContainer == null) return false; + + BuildAggregateFilterContainers(); + AddChildren((AggregateFilterContainer)f.FilterContainer, knownContainer.Add(f.FilterContainer)); + return true; + } - public bool SelectiveRefresh(AggregateFilterContainer container) - { - var aggregate = container.GetAggregate(); + public bool SelectiveRefresh(AggregateFilterContainer container) + { + var aggregate = container.GetAggregate(); - if (aggregate == null) return false; + if (aggregate == null) return false; - var descendancy = GetDescendancyListIfAnyFor(aggregate); + var descendancy = GetDescendancyListIfAnyFor(aggregate); - if (descendancy == null) return false; + if (descendancy == null) return false; - // update just in case we became a root filter for someone - aggregate.RevertToDatabaseState(); + // update just in case we became a root filter for someone + aggregate.RevertToDatabaseState(); - BuildAggregateFilterContainers(); + BuildAggregateFilterContainers(); - AddChildren(aggregate, descendancy.Add(aggregate)); - return true; - } + AddChildren(aggregate, descendancy.Add(aggregate)); + return true; + } } \ No newline at end of file diff --git a/Rdmp.Core/Providers/CatalogueProblemProvider.cs b/Rdmp.Core/Providers/CatalogueProblemProvider.cs index cf1f01ae2f..3e405e2ac4 100644 --- a/Rdmp.Core/Providers/CatalogueProblemProvider.cs +++ b/Rdmp.Core/Providers/CatalogueProblemProvider.cs @@ -6,7 +6,6 @@ using System; using System.Collections.Generic; -using System.Diagnostics; using System.Globalization; using System.Linq; using Rdmp.Core.CommandExecution.AtomicCommands; diff --git a/Rdmp.Core/Providers/DataExportChildProvider.cs b/Rdmp.Core/Providers/DataExportChildProvider.cs index df0266f273..618eae79eb 100644 --- a/Rdmp.Core/Providers/DataExportChildProvider.cs +++ b/Rdmp.Core/Providers/DataExportChildProvider.cs @@ -7,6 +7,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Threading; using System.Threading.Tasks; using FAnsi.Discovery; using Rdmp.Core.Caching.Pipeline; @@ -72,7 +73,7 @@ public class DataExportChildProvider : CatalogueChildProvider new(); - private readonly object _oProjectNumberToCohortsDictionary = new(); + private readonly Lock _oProjectNumberToCohortsDictionaryLock = new(); public Dictionary> ProjectNumberToCohortsDictionary = new(); public ProjectCohortIdentificationConfigurationAssociation[] AllProjectAssociatedCics; @@ -592,7 +593,7 @@ private void GetCohortAvailability(ExternalCohortTable source) //tell the cohort about the data c.InjectKnown(externalData); - lock (_oProjectNumberToCohortsDictionary) + lock (_oProjectNumberToCohortsDictionaryLock) { //for performance also keep a dictionary of project number => compatible cohorts if (!ProjectNumberToCohortsDictionary.ContainsKey(externalData.ExternalProjectNumber)) diff --git a/Rdmp.Core/Providers/Nodes/Category.cs b/Rdmp.Core/Providers/Nodes/Category.cs deleted file mode 100644 index e776f49a2b..0000000000 --- a/Rdmp.Core/Providers/Nodes/Category.cs +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright (c) The University of Dundee 2018-2019 -// This file is part of the Research Data Management Platform (RDMP). -// 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. -// 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. -// You should have received a copy of the GNU General Public License along with RDMP. If not, see . - -namespace Rdmp.Core.Providers.Nodes; - -public class Category -{ -} \ No newline at end of file diff --git a/Rdmp.Core/Providers/Nodes/Node.cs b/Rdmp.Core/Providers/Nodes/Node.cs index dd60b1d639..d3d4f0f474 100644 --- a/Rdmp.Core/Providers/Nodes/Node.cs +++ b/Rdmp.Core/Providers/Nodes/Node.cs @@ -9,6 +9,4 @@ namespace Rdmp.Core.Providers.Nodes; /// /// Abstract base for all collection and proxy nodes in RDMP tree hierarchies e.g. /// -public abstract class Node -{ -} \ No newline at end of file +public abstract class Node; \ No newline at end of file diff --git a/Rdmp.Core/Providers/Nodes/UsedByNodes/IObjectUsedByOtherObjectNode.cs b/Rdmp.Core/Providers/Nodes/UsedByNodes/IObjectUsedByOtherObjectNode.cs index 3f0b237213..0cc255395e 100644 --- a/Rdmp.Core/Providers/Nodes/UsedByNodes/IObjectUsedByOtherObjectNode.cs +++ b/Rdmp.Core/Providers/Nodes/UsedByNodes/IObjectUsedByOtherObjectNode.cs @@ -8,9 +8,7 @@ namespace Rdmp.Core.Providers.Nodes.UsedByNodes; -public interface IObjectUsedByOtherObjectNode : IMasqueradeAs -{ -} +public interface IObjectUsedByOtherObjectNode : IMasqueradeAs; public interface IObjectUsedByOtherObjectNode : IObjectUsedByOtherObjectNode { diff --git a/Rdmp.Core/QueryBuilding/AggregateBuilder.cs b/Rdmp.Core/QueryBuilding/AggregateBuilder.cs index 969495994a..76ab8cc840 100644 --- a/Rdmp.Core/QueryBuilding/AggregateBuilder.cs +++ b/Rdmp.Core/QueryBuilding/AggregateBuilder.cs @@ -406,9 +406,7 @@ public void RegenerateSQL() if (primary == null) //we don't currently know the primary (i.e. none of the SELECT columns were from primary tables so use this table as primary) primary = t; - else if (primary.ID == t.ID) //we know the primary already but it is the same table so that's fine - continue; - else + else if (primary.ID != t.ID) //we know the primary already: if it is the same table so that's fine //this isn't fine throw new QueryBuildingException( $"You chose to FORCE a join to table {t} which is marked IsPrimaryExtractionTable but you have also selected a column called {primary} which is also an IsPrimaryExtractionTable (cannot have 2 different primary extraction tables)"); diff --git a/Rdmp.Core/QueryBuilding/CohortQueryBuilder.cs b/Rdmp.Core/QueryBuilding/CohortQueryBuilder.cs index a86015b56b..42064964ce 100644 --- a/Rdmp.Core/QueryBuilding/CohortQueryBuilder.cs +++ b/Rdmp.Core/QueryBuilding/CohortQueryBuilder.cs @@ -35,14 +35,14 @@ namespace Rdmp.Core.QueryBuilding; public class CohortQueryBuilder { private ICoreChildProvider _childProvider; - private object oSQLLock = new(); + private readonly Lock _oSQLLock = new(); private string _sql; public string SQL { get { - lock (oSQLLock) + lock (_oSQLLock) { if (SQLOutOfDate) RegenerateSQL(); diff --git a/Rdmp.Core/QueryBuilding/CohortQueryBuilderDependency.cs b/Rdmp.Core/QueryBuilding/CohortQueryBuilderDependency.cs index 72b730950d..fe2eba6b9b 100644 --- a/Rdmp.Core/QueryBuilding/CohortQueryBuilderDependency.cs +++ b/Rdmp.Core/QueryBuilding/CohortQueryBuilderDependency.cs @@ -84,30 +84,28 @@ public CohortQueryBuilderDependency(AggregateConfiguration cohortSet, JoinableCohortAggregateConfigurationUse patientIndexTableIfAny, ICoreChildProvider childProvider, IReadOnlyCollection pluginCohortCompilers) { - var childProvider1 = childProvider; _pluginCohortCompilers = pluginCohortCompilers; CohortSet = cohortSet; PatientIndexTableIfAny = patientIndexTableIfAny; //record the IsExtractionIdentifier column for the log (helps with debugging count issues) - var eis = cohortSet?.AggregateDimensions?.Where(d => d.IsExtractionIdentifier).ToArray(); + var eis = cohortSet?.AggregateDimensions?.Where(static d => d.IsExtractionIdentifier).ToArray(); //Multiple IsExtractionIdentifier columns is a big problem but it's handled elsewhere if (eis is { Length: 1 }) ExtractionIdentifierColumn = eis[0]; - if (PatientIndexTableIfAny != null) - { - var join = childProvider1.AllJoinables.SingleOrDefault(j => - j.ID == PatientIndexTableIfAny.JoinableCohortAggregateConfiguration_ID) ?? - throw new Exception("ICoreChildProvider did not know about the provided patient index table"); - JoinedTo = childProvider1.AllAggregateConfigurations.SingleOrDefault(ac => - ac.ID == join.AggregateConfiguration_ID); + if (PatientIndexTableIfAny == null) return; - if (JoinedTo == null) - throw new Exception( - "ICoreChildProvider did not know about the provided patient index table AggregateConfiguration"); - } + var join = childProvider.AllJoinables.SingleOrDefault(j => + j.ID == PatientIndexTableIfAny.JoinableCohortAggregateConfiguration_ID) ?? + throw new Exception("ICoreChildProvider did not know about the provided patient index table"); + JoinedTo = childProvider.AllAggregateConfigurations.SingleOrDefault(ac => + ac.ID == join.AggregateConfiguration_ID); + + if (JoinedTo == null) + throw new Exception( + "ICoreChildProvider did not know about the provided patient index table AggregateConfiguration"); } public override string ToString() => diff --git a/Rdmp.Core/QueryBuilding/CohortQueryBuilderHelper.cs b/Rdmp.Core/QueryBuilding/CohortQueryBuilderHelper.cs index 8b13b1b07f..73f2c06709 100644 --- a/Rdmp.Core/QueryBuilding/CohortQueryBuilderHelper.cs +++ b/Rdmp.Core/QueryBuilding/CohortQueryBuilderHelper.cs @@ -126,9 +126,8 @@ public static CohortQueryBuilderDependencySql GetSQLForAggregate(AggregateConfig var builderSqlWithoutParameters = builder.SQL; //get the SQL from the builder (for the current configuration) - without parameters - var currentBlock = builderSqlWithoutParameters; - var toReturn = new CohortQueryBuilderDependencySql(currentBlock, builder.ParameterManager); + var toReturn = new CohortQueryBuilderDependencySql(builderSqlWithoutParameters, builder.ParameterManager); if (args.JoinSql != null) toReturn.ParametersUsed.MergeWithoutRename(args.JoinSql.ParametersUsed); diff --git a/Rdmp.Core/QueryBuilding/ConstantParameter.cs b/Rdmp.Core/QueryBuilding/ConstantParameter.cs index e6ca91366f..72c24739aa 100644 --- a/Rdmp.Core/QueryBuilding/ConstantParameter.cs +++ b/Rdmp.Core/QueryBuilding/ConstantParameter.cs @@ -108,7 +108,7 @@ public static ConstantParameter Parse(string sql, IQuerySyntaxHelper syntaxHelpe throw new Exception($"Value line did not start with SET:{sql}"); var valueLineSplit = valueLine.Split(new[] { '=' }); - var value = valueLineSplit[1].TrimEnd(new[] { ';', '\r' }); + var value = valueLineSplit[1].TrimEnd(';', '\r'); return new ConstantParameter(declaration.Trim(), value.Trim(), comment, syntaxHelper); } diff --git a/Rdmp.Core/QueryBuilding/Parameters/ParameterManager.cs b/Rdmp.Core/QueryBuilding/Parameters/ParameterManager.cs index 0cca555f90..21604763c5 100644 --- a/Rdmp.Core/QueryBuilding/Parameters/ParameterManager.cs +++ b/Rdmp.Core/QueryBuilding/Parameters/ParameterManager.cs @@ -159,10 +159,10 @@ public IEnumerable GetFinalResolvedParametersList() throw new QueryBuildingException(exceptionMessage); //problem was from a user one from their Catalogue Database, tell them the ProblemObject as well - throw new QueryBuildingException(exceptionMessage, new[] { asConcreteObject }); + throw new QueryBuildingException(exceptionMessage, asConcreteObject); } - return toReturn.Select(t => t.Parameter); + return toReturn.Select(static t => t.Parameter); } /// @@ -319,8 +319,7 @@ public void ImportAndElevateResolvedParametersFromSubquery(ParameterManager toIm else //there's an override with the same name but different datatypes (that's a problem) throw new QueryBuildingException( - $"Parameter {parameterToImport} has the same name as an existing parameter with a global override but differing declarations (normally we would handle with a rename but we can't because of the overriding global)", - new object[] { existing, parameterToImport, overridingGlobal }); + $"Parameter {parameterToImport} has the same name as an existing parameter with a global override but differing declarations (normally we would handle with a rename but we can't because of the overriding global)", existing, parameterToImport, overridingGlobal); //one already exists so we will have to do a parameter rename @@ -459,8 +458,7 @@ public ISqlParameter GetOverrideIfAnyFor(ISqlParameter existing) public void RemoveParameter(ISqlParameter deletable) { foreach (var parameters in ParametersFoundSoFarInQueryGeneration.Values) - if (parameters.Contains(deletable)) - parameters.Remove(deletable); + parameters.Remove(deletable); } /// diff --git a/Rdmp.Core/QueryBuilding/PrimaryKeyCollisionResolver.cs b/Rdmp.Core/QueryBuilding/PrimaryKeyCollisionResolver.cs index be98e773d1..42b8b3be9b 100644 --- a/Rdmp.Core/QueryBuilding/PrimaryKeyCollisionResolver.cs +++ b/Rdmp.Core/QueryBuilding/PrimaryKeyCollisionResolver.cs @@ -135,7 +135,7 @@ public string GenerateCollisionDetectionSQL() sql += tableNameInRAW + Environment.NewLine; sql += $"group by {pks.Aggregate("", (s, n) => $"{s}{_querySyntaxHelper.EnsureWrapped(n.GetRuntimeName(LoadStage.AdjustRaw))},")}{Environment.NewLine}"; - sql = sql.TrimEnd(new[] { ',', '\r', '\n' }) + Environment.NewLine; + sql = sql.TrimEnd(',', '\r', '\n') + Environment.NewLine; sql += $"having count(*) > 1{Environment.NewLine}"; sql += $") then 1 else 0 end{Environment.NewLine}"; diff --git a/Rdmp.Core/QueryBuilding/QueryBuilder.cs b/Rdmp.Core/QueryBuilding/QueryBuilder.cs index f739e71524..9ddcb0cf79 100644 --- a/Rdmp.Core/QueryBuilding/QueryBuilder.cs +++ b/Rdmp.Core/QueryBuilding/QueryBuilder.cs @@ -8,6 +8,7 @@ using System.Collections.Generic; using System.Linq; using System.Text.RegularExpressions; +using System.Threading; using FAnsi.Discovery.QuerySyntax; using Rdmp.Core.Curation.Data; using Rdmp.Core.MapsDirectlyToDatabaseTable.Injection; @@ -30,14 +31,14 @@ namespace Rdmp.Core.QueryBuilding; public class QueryBuilder : ISqlQueryBuilder { private readonly ITableInfo[] _forceJoinsToTheseTables; - private readonly object oSQLLock = new(); + private readonly Lock _oSQLLock = new(); /// public string SQL { get { - lock (oSQLLock) + lock (_oSQLLock) { if (SQLOutOfDate) RegenerateSQL(); diff --git a/Rdmp.Core/Reports/DitaCatalogueExtractor.cs b/Rdmp.Core/Reports/DitaCatalogueExtractor.cs index 77891366db..b615ebdf07 100644 --- a/Rdmp.Core/Reports/DitaCatalogueExtractor.cs +++ b/Rdmp.Core/Reports/DitaCatalogueExtractor.cs @@ -53,20 +53,20 @@ public DitaCatalogueExtractor(ICatalogueRepository repository, DirectoryInfo fol public void Extract(IDataLoadEventListener listener) { var xml = new StringBuilder(); - xml.Append($""" - - - - HIC Data Catalogue - - Wilfred Bonney; Thomas Nind; Mikhail Ghattas - Health Informatics Centre (HIC), University of Dundee - - - - """); + xml.Append(""" + + + + HIC Data Catalogue + + Wilfred Bonney; Thomas Nind; Mikhail Ghattas + Health Informatics Centre (HIC), University of Dundee + + + + """); GenerateIntroductionFile("introduction.dita"); GenerateDataSetFile("dataset.dita"); diff --git a/Rdmp.Core/Reports/DocXHelper.cs b/Rdmp.Core/Reports/DocXHelper.cs index c48ec02e97..0176d0dfbe 100644 --- a/Rdmp.Core/Reports/DocXHelper.cs +++ b/Rdmp.Core/Reports/DocXHelper.cs @@ -87,6 +87,8 @@ protected static void SetTableCell(XWPFTable table, int row, int col, string val if (fontSize != -1) run.FontSize = fontSize; + + first = false; } } diff --git a/Rdmp.Core/Reports/ExtractionTime/WordDataWriter.cs b/Rdmp.Core/Reports/ExtractionTime/WordDataWriter.cs index 45806e2f09..f469edd732 100644 --- a/Rdmp.Core/Reports/ExtractionTime/WordDataWriter.cs +++ b/Rdmp.Core/Reports/ExtractionTime/WordDataWriter.cs @@ -10,6 +10,7 @@ using System.IO; using System.Linq; using System.Text; +using System.Threading; using NPOI.XWPF.UserModel; using Rdmp.Core.Curation.Data; using Rdmp.Core.DataExport.Data; @@ -51,7 +52,7 @@ public WordDataWriter(ExtractionPipelineUseCase executer) $"{GetType().FullName} only supports destinations which are {typeof(ExecuteDatasetExtractionFlatFileDestination).FullName}"); } - private static readonly object OLockOnWordUsage = new(); + private static readonly Lock OLockOnWordUsage = new(); private readonly IExecuteDatasetExtractionDestination _destination; diff --git a/Rdmp.Core/Repositories/Construction/ObjectConstructor.cs b/Rdmp.Core/Repositories/Construction/ObjectConstructor.cs index 5941ffb6cb..5674c9fae9 100644 --- a/Rdmp.Core/Repositories/Construction/ObjectConstructor.cs +++ b/Rdmp.Core/Repositories/Construction/ObjectConstructor.cs @@ -321,7 +321,7 @@ public static object ConstructIfPossible(Type typeToConstruct, params object[] c compatible.Add(constructor); } - return compatible.Any() ? InvokeBestConstructor(compatible, constructorValues) : null; + return compatible.Count != 0 ? InvokeBestConstructor(compatible, constructorValues) : null; } /// @@ -333,11 +333,10 @@ public static object ConstructIfPossible(Type typeToConstruct, params object[] c public static ConstructorInfo GetRepositoryConstructor(Type type) { var compatible = type.GetConstructors() - .Select(constructorInfo => new { constructorInfo, parameters = constructorInfo.GetParameters() }) - .Where(@t => @t.parameters.All(p => p.GetType() != typeof(ShareManager))) - .Where(@t => @t.parameters.All(p => p.GetType() != typeof(DbDataReader))) - .Where(@t => @t.parameters.Any(p => typeof(IRepository).IsAssignableFrom(p.ParameterType))) - .Select(@t => @t.constructorInfo).ToList(); + .Select(static constructorInfo => new { constructorInfo, parameters = constructorInfo.GetParameters() }) + .Where(static t => t.parameters.All(static p => p.GetType() != typeof(ShareManager) && p.GetType() != typeof(DbDataReader))) + .Where(static t => t.parameters.Any(static p => typeof(IRepository).IsAssignableFrom(p.ParameterType))) + .Select(static t => t.constructorInfo).ToList(); return compatible.Count == 1 ? compatible.Single() diff --git a/Rdmp.Core/Repositories/Construction/UseWithObjectConstructorAttribute.cs b/Rdmp.Core/Repositories/Construction/UseWithObjectConstructorAttribute.cs index 85a3c14de1..34350817cf 100644 --- a/Rdmp.Core/Repositories/Construction/UseWithObjectConstructorAttribute.cs +++ b/Rdmp.Core/Repositories/Construction/UseWithObjectConstructorAttribute.cs @@ -13,6 +13,4 @@ namespace Rdmp.Core.Repositories.Construction; /// This is only needed if you have 2+ constructors in your class. /// [AttributeUsage(AttributeTargets.Constructor)] -public class UseWithObjectConstructorAttribute : Attribute -{ -} \ No newline at end of file +public class UseWithObjectConstructorAttribute : Attribute; \ No newline at end of file diff --git a/Rdmp.Core/Repositories/Managers/DataExportPropertyManager.cs b/Rdmp.Core/Repositories/Managers/DataExportPropertyManager.cs index c6f1cd6b1b..292c76ec63 100644 --- a/Rdmp.Core/Repositories/Managers/DataExportPropertyManager.cs +++ b/Rdmp.Core/Repositories/Managers/DataExportPropertyManager.cs @@ -119,21 +119,19 @@ private void IssueUpdateCommand(string property, string value) private void RefreshCache() { - var repo = (TableRepository)_repository; - using (var con = repo.GetConnection()) + TableRepository repo = _repository; + using var con = repo.GetConnection(); + using var cmd = DatabaseCommandHelper.GetCommand("SELECT * from [ConfigurationProperties]", + con.Connection, con.Transaction); + using var reader = cmd.ExecuteReader(); + _cacheDictionary.Clear(); + + //get cache of all answers + while (reader.Read()) { - using var cmd = DatabaseCommandHelper.GetCommand("SELECT * from [ConfigurationProperties]", - con.Connection, con.Transaction); - using var reader = cmd.ExecuteReader(); - _cacheDictionary.Clear(); - - //get cache of all answers - while (reader.Read()) - { - var val = reader["Value"] as string; - _cacheDictionary.AddOrUpdate(reader["Property"].ToString(), - val, (k, o) => val); - } + var val = reader["Value"] as string; + _cacheDictionary.AddOrUpdate(reader["Property"].ToString(), + val, (k, o) => val); } _cacheOutOfDate = false; diff --git a/Rdmp.Core/Repositories/YamlRepository.cs b/Rdmp.Core/Repositories/YamlRepository.cs index 580a5990b8..c99af4dda0 100644 --- a/Rdmp.Core/Repositories/YamlRepository.cs +++ b/Rdmp.Core/Repositories/YamlRepository.cs @@ -8,6 +8,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using System.Threading; using Rdmp.Core.Curation.Data; using Rdmp.Core.Curation.Data.Aggregation; using Rdmp.Core.Curation.Data.Cohort; @@ -36,7 +37,7 @@ public class YamlRepository : MemoryDataExportRepository public DirectoryInfo Directory { get; } - private object lockFs = new(); + private readonly Lock lockFs = new(); public YamlRepository(DirectoryInfo dir) { @@ -654,7 +655,6 @@ private Dictionary> Load(string filenameWithoutSuffix) catch (KeyNotFoundException) { // skip missing objects (they will disappear next save anyway) - continue; } dictionary.Add(key, set); @@ -662,7 +662,6 @@ private Dictionary> Load(string filenameWithoutSuffix) catch (KeyNotFoundException) { // skip missing container objects (they will disappear next save anyway) - continue; } return dictionary; diff --git a/Rdmp.Core/ReusableLibraryCode/AWS/AWSS3.cs b/Rdmp.Core/ReusableLibraryCode/AWS/AWSS3.cs index 84256759ed..6b5c96b007 100644 --- a/Rdmp.Core/ReusableLibraryCode/AWS/AWSS3.cs +++ b/Rdmp.Core/ReusableLibraryCode/AWS/AWSS3.cs @@ -9,7 +9,6 @@ using Amazon.Runtime; using Amazon.S3; using Amazon.S3.Model; -using Org.BouncyCastle.Security.Certificates; using System; using System.Collections.Generic; using System.IO; diff --git a/Rdmp.Core/ReusableLibraryCode/Annotations/Annotations.cs b/Rdmp.Core/ReusableLibraryCode/Annotations/Annotations.cs index 6589f5a16b..7bcc309ebc 100644 --- a/Rdmp.Core/ReusableLibraryCode/Annotations/Annotations.cs +++ b/Rdmp.Core/ReusableLibraryCode/Annotations/Annotations.cs @@ -22,10 +22,8 @@ namespace Rdmp.Core.ReusableLibraryCode.Annotations; [AttributeUsage( AttributeTargets.Method | AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.Delegate | - AttributeTargets.Field, AllowMultiple = false, Inherited = true)] -public sealed class CanBeNullAttribute : Attribute -{ -} + AttributeTargets.Field)] +public sealed class CanBeNullAttribute : Attribute; /// /// Indicates that the value of the marked element could never be null @@ -38,10 +36,8 @@ public sealed class CanBeNullAttribute : Attribute [AttributeUsage( AttributeTargets.Method | AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.Delegate | - AttributeTargets.Field, AllowMultiple = false, Inherited = true)] -public sealed class NotNullAttribute : Attribute -{ -} + AttributeTargets.Field)] +public sealed class NotNullAttribute : Attribute; /// /// Indicates that the method is contained in a type that implements @@ -79,7 +75,7 @@ public sealed class NotNullAttribute : Attribute /// SetProperty(ref myField, value, "Property") /// /// -[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)] +[AttributeUsage(AttributeTargets.Method)] public sealed class NotifyPropertyChangedInvocatorAttribute : Attribute { public NotifyPropertyChangedInvocatorAttribute() @@ -99,7 +95,7 @@ public NotifyPropertyChangedInvocatorAttribute(string parameterName) /// (e.g. via reflection, in external library), so this symbol /// will not be marked as unused (as well as by other usage inspections) /// -[AttributeUsage(AttributeTargets.All, AllowMultiple = false, Inherited = true)] +[AttributeUsage(AttributeTargets.All)] public sealed class UsedImplicitlyAttribute : Attribute { public UsedImplicitlyAttribute( diff --git a/Rdmp.Core/ReusableLibraryCode/Checks/ToMemoryCheckNotifier.cs b/Rdmp.Core/ReusableLibraryCode/Checks/ToMemoryCheckNotifier.cs index 4520cd1b86..499b618125 100644 --- a/Rdmp.Core/ReusableLibraryCode/Checks/ToMemoryCheckNotifier.cs +++ b/Rdmp.Core/ReusableLibraryCode/Checks/ToMemoryCheckNotifier.cs @@ -5,6 +5,7 @@ // You should have received a copy of the GNU General Public License along with RDMP. If not, see . using System.Collections.Generic; +using System.Threading; namespace Rdmp.Core.ReusableLibraryCode.Checks; @@ -18,7 +19,7 @@ public class ToMemoryCheckNotifier : ICheckNotifier private readonly ICheckNotifier _childToPassEventsTo; public List Messages { get; } = new(); - private readonly object _lockList = new(); + private readonly Lock _lockList = new(); private CheckResult _worst = CheckResult.Success; @@ -31,7 +32,6 @@ public class ToMemoryCheckNotifier : ICheckNotifier public ToMemoryCheckNotifier(ICheckNotifier childToPassEventsTo) { _childToPassEventsTo = childToPassEventsTo; - Messages = new List(); } public ToMemoryCheckNotifier() @@ -40,22 +40,16 @@ public ToMemoryCheckNotifier() public bool OnCheckPerformed(CheckEventArgs args) { - var fix = false; - if (_childToPassEventsTo != null) - { - fix = _childToPassEventsTo.OnCheckPerformed(args); + var fix = _childToPassEventsTo?.OnCheckPerformed(args) == true; - //if child accepted the fix - if (fix && !string.IsNullOrWhiteSpace(args.ProposedFix) && args.Result == CheckResult.Fail) - args.Result = CheckResult.Warning; - } + //if child accepted the fix that reduces a Fail to a Warning + if (fix && !string.IsNullOrWhiteSpace(args.ProposedFix) && args.Result == CheckResult.Fail) + args.Result = CheckResult.Warning; - lock (_lockList) - { - if (args.Result > _worst) - _worst = args.Result; - Messages.Add(args); - } + if (args.Result > _worst) + _worst = args.Result; + + lock (_lockList) Messages.Add(args); return fix; } diff --git a/Rdmp.Core/ReusableLibraryCode/DoNotExtractProperty.cs b/Rdmp.Core/ReusableLibraryCode/DoNotExtractProperty.cs index 8be909c787..f3b6b61fec 100644 --- a/Rdmp.Core/ReusableLibraryCode/DoNotExtractProperty.cs +++ b/Rdmp.Core/ReusableLibraryCode/DoNotExtractProperty.cs @@ -11,7 +11,5 @@ namespace Rdmp.Core.ReusableLibraryCode; /// /// Used to indicate when a property should nto be extracted and passed out to researchers as metadata content (use for internal fields like ValidatorXML) /// -[AttributeUsage(AttributeTargets.Property, Inherited = false, AllowMultiple = false)] -public class DoNotExtractProperty : Attribute -{ -} \ No newline at end of file +[AttributeUsage(AttributeTargets.Property)] +public sealed class DoNotExtractProperty : Attribute; \ No newline at end of file diff --git a/Rdmp.Core/ReusableLibraryCode/IVersionable.cs b/Rdmp.Core/ReusableLibraryCode/IVersionable.cs index b56910eed1..c41cd74ef5 100644 --- a/Rdmp.Core/ReusableLibraryCode/IVersionable.cs +++ b/Rdmp.Core/ReusableLibraryCode/IVersionable.cs @@ -1,17 +1,11 @@ using Rdmp.Core.Curation.Data; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace Rdmp.Core.ReusableLibraryCode; internal interface IVersionable { - /// - /// Interface to provide the SaveNewVersion function + /// Interface to provide the SaveNewVersion function /// /// DatabaseEntity DatabaseEntity SaveNewVersion(); diff --git a/Rdmp.Core/ReusableLibraryCode/Settings/RDMPApplicationSettings.cs b/Rdmp.Core/ReusableLibraryCode/Settings/RDMPApplicationSettings.cs index f638149214..46cc441bad 100644 --- a/Rdmp.Core/ReusableLibraryCode/Settings/RDMPApplicationSettings.cs +++ b/Rdmp.Core/ReusableLibraryCode/Settings/RDMPApplicationSettings.cs @@ -8,23 +8,24 @@ using System.IO; using System.IO.IsolatedStorage; using System.Linq; +using System.Threading; namespace Rdmp.Core.ReusableLibraryCode.Settings; internal sealed class RDMPApplicationSettings { - private readonly IsolatedStorageFile store; - private readonly object locker = new(); + private readonly IsolatedStorageFile _store; + private readonly Lock _locker = new(); public RDMPApplicationSettings() { try { - store = IsolatedStorageFile.GetUserStoreForApplication(); + _store = IsolatedStorageFile.GetUserStoreForApplication(); } catch (Exception) { - store = IsolatedStorageFile.GetUserStoreForAssembly(); + _store = IsolatedStorageFile.GetUserStoreForAssembly(); } } @@ -62,7 +63,7 @@ private bool AddOrUpdateValueInternal(string key, T value) type != typeof(long) && type != typeof(byte)) throw new ArgumentException($"Value of type {type.Name} is not supported."); - lock (locker) + lock (_locker) { string str; @@ -82,14 +83,14 @@ private bool AddOrUpdateValueInternal(string key, T value) string oldValue = null; - if (store.FileExists(key)) + if (_store.FileExists(key)) { - using var stream = store.OpenFile(key, FileMode.Open); + using var stream = _store.OpenFile(key, FileMode.Open); using var sr = new StreamReader(stream); oldValue = sr.ReadToEnd(); } - using (var stream = store.OpenFile(key, FileMode.Create, FileAccess.Write)) + using (var stream = _store.OpenFile(key, FileMode.Create, FileAccess.Write)) { using var sw = new StreamWriter(stream); sw.Write(str); @@ -109,16 +110,16 @@ private bool AddOrUpdateValueInternal(string key, T value) private T GetValueOrDefaultInternal(string key, T defaultValue = default) { object value = null; - lock (locker) + lock (_locker) { try { string str = null; // If the key exists, retrieve the value. - if (store.FileExists(key)) + if (_store.FileExists(key)) { - using var stream = store.OpenFile(key, FileMode.Open); + using var stream = _store.OpenFile(key, FileMode.Open); using var sr = new StreamReader(stream); str = sr.ReadToEnd(); } @@ -216,8 +217,8 @@ private T GetValueOrDefaultInternal(string key, T defaultValue = default) /// Key to remove public void Remove(string key) { - if (store.FileExists(key)) - store.DeleteFile(key); + if (_store.FileExists(key)) + _store.DeleteFile(key); } /// @@ -227,7 +228,7 @@ public void Clear() { try { - foreach (var file in store.GetFileNames()) store.DeleteFile(file); + foreach (var file in _store.GetFileNames()) _store.DeleteFile(file); } catch (Exception ex) { @@ -240,7 +241,7 @@ public void Clear() /// /// Key to check /// True if contains key, else false - public bool Contains(string key) => store.FileExists(key); + public bool Contains(string key) => _store.FileExists(key); #region GetValueOrDefault diff --git a/Rdmp.Core/ReusableLibraryCode/Settings/UserSettings.cs b/Rdmp.Core/ReusableLibraryCode/Settings/UserSettings.cs index ac819fc65f..9b6de0e566 100644 --- a/Rdmp.Core/ReusableLibraryCode/Settings/UserSettings.cs +++ b/Rdmp.Core/ReusableLibraryCode/Settings/UserSettings.cs @@ -8,6 +8,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using System.Threading; using FAnsi.Discovery; using Rdmp.Core.ReusableLibraryCode.Checks; @@ -550,7 +551,7 @@ public static void AddHistoryForControl(Guid guid, string v) public static Tuple GetLastColumnSortForCollection(Guid controlGuid) { - lock (_oLockUserSettings) + lock (OLockUserSettings) { var value = AppSettings.GetValueOrDefault($"LastColumnSort_{controlGuid:N}", null); @@ -575,11 +576,11 @@ public static Tuple GetLastColumnSortForCollection(Guid controlGui return null; } - private static object _oLockUserSettings = new(); + private static readonly Lock OLockUserSettings = new(); public static void SetLastColumnSortForCollection(Guid controlGuid, string columnName, bool ascending) { - lock (_oLockUserSettings) + lock (OLockUserSettings) { AppSettings.AddOrUpdateValue($"LastColumnSort_{controlGuid:N}", $"{columnName}#!#{ascending}"); } @@ -603,7 +604,7 @@ public static int GetSplitterDistance(Guid controlGuid) => /// public static void SetSplitterDistance(Guid controlGuid, int splitterDistance) { - lock (_oLockUserSettings) + lock (OLockUserSettings) { AppSettings.AddOrUpdateValue($"SplitterDistance_{controlGuid:N}", splitterDistance); } diff --git a/Rdmp.Core/ReusableLibraryCode/UsefulStuff.cs b/Rdmp.Core/ReusableLibraryCode/UsefulStuff.cs index 060ecd792b..1131d2864d 100644 --- a/Rdmp.Core/ReusableLibraryCode/UsefulStuff.cs +++ b/Rdmp.Core/ReusableLibraryCode/UsefulStuff.cs @@ -212,6 +212,7 @@ public static string HashFile(string filename, int retryCount = 6) if (retryCount-- > 0) return HashFile(filename, retryCount); //try it again (recursively) + throw; } } @@ -247,8 +248,7 @@ public static string RemoveIllegalFilenameCharacters(string value) { return string.IsNullOrWhiteSpace(value) ? value - : Path.GetInvalidFileNameChars().Aggregate(value, - (current, invalidFileNameChar) => current.Replace(invalidFileNameChar.ToString(), "")); + : Path.GetInvalidFileNameChars().Aggregate(value, static (current, invalidFileNameChar) => current.Replace(invalidFileNameChar.ToString(), "")); } @@ -450,7 +450,7 @@ public static string GetClipboardFormattedHtmlStringFromHtmlString(string s) // {0:D6} is the same length as its own description // {1:D10} is 3 characters longer than its own description, so +3 // {2} on the end adds 3, so the overall prefix length is constant - var template = "Version:1.0\r\nStartHTML:{0:D6}\r\nEndHTML:{1:D10}\r\n{2}"; + const string template = "Version:1.0\r\nStartHTML:{0:D6}\r\nEndHTML:{1:D10}\r\n{2}"; return string.Format( template, template.Length, @@ -503,19 +503,18 @@ public static string SplitByLength(string input, int maxLen, string newline = nu return string.Join(newline ?? Environment.NewLine, Regex.Split(input, $@"(.{{1,{maxLen}}})(?:\s|$)") - .Where(x => x.Length > 0) - .Select(x => x.Trim())); + .Where(static x => x.Length > 0) + .Select(static x => x.Trim())); } public static void ConfirmContentsOfDirectoryAreTheSame(DirectoryInfo first, DirectoryInfo other) { - if (first.EnumerateFiles().Count() != other.EnumerateFiles().Count()) - throw new Exception( - $"found different number of files in Globals directory {first.FullName} and {other.FullName}"); - var filesInFirst = first.EnumerateFiles().ToArray(); var filesInOther = other.EnumerateFiles().ToArray(); + if (filesInFirst.Length != filesInOther.Length) + throw new Exception( + $"found different number of files in Globals directory {first.FullName} and {other.FullName}"); for (var i = 0; i < filesInFirst.Length; i++) { diff --git a/Rdmp.Core/Validation/Constraints/Primary/PluginPrimaryConstraint.cs b/Rdmp.Core/Validation/Constraints/Primary/PluginPrimaryConstraint.cs index 7fbd575624..4fab30c53a 100644 --- a/Rdmp.Core/Validation/Constraints/Primary/PluginPrimaryConstraint.cs +++ b/Rdmp.Core/Validation/Constraints/Primary/PluginPrimaryConstraint.cs @@ -10,6 +10,4 @@ namespace Rdmp.Core.Validation.Constraints.Primary; /// /// Abstract base that allows plugin developers to create new rules /// -public abstract class PluginPrimaryConstraint : PrimaryConstraint -{ -} \ No newline at end of file +public abstract class PluginPrimaryConstraint : PrimaryConstraint; \ No newline at end of file diff --git a/Rdmp.Core/Validation/Constraints/Secondary/PluginSecondaryConstraint.cs b/Rdmp.Core/Validation/Constraints/Secondary/PluginSecondaryConstraint.cs deleted file mode 100644 index e14fcb64de..0000000000 --- a/Rdmp.Core/Validation/Constraints/Secondary/PluginSecondaryConstraint.cs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) The University of Dundee 2018-2019 -// This file is part of the Research Data Management Platform (RDMP). -// 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. -// 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. -// You should have received a copy of the GNU General Public License along with RDMP. If not, see . - - -namespace Rdmp.Core.Validation.Constraints.Secondary; - -/// -/// Abstract base that allows plugin developers to create new rules -/// -public abstract class PluginSecondaryConstraint : SecondaryConstraint -{ -} \ No newline at end of file diff --git a/Rdmp.Core/Validation/Constraints/Secondary/Predictor/PluginPredictionRule.cs b/Rdmp.Core/Validation/Constraints/Secondary/Predictor/PluginPredictionRule.cs deleted file mode 100644 index 11b576831a..0000000000 --- a/Rdmp.Core/Validation/Constraints/Secondary/Predictor/PluginPredictionRule.cs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) The University of Dundee 2018-2019 -// This file is part of the Research Data Management Platform (RDMP). -// 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. -// 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. -// You should have received a copy of the GNU General Public License along with RDMP. If not, see . - - -namespace Rdmp.Core.Validation.Constraints.Secondary.Predictor; - -/// -/// Abstract base for plugin developers to write new for the data quality engine -/// -public abstract class PluginPredictionRule : PredictionRule -{ -} \ No newline at end of file diff --git a/Rdmp.Core/Validation/UIAttributes/Attributes.cs b/Rdmp.Core/Validation/UIAttributes/Attributes.cs index 2cd141ffb4..f057e17a57 100644 --- a/Rdmp.Core/Validation/UIAttributes/Attributes.cs +++ b/Rdmp.Core/Validation/UIAttributes/Attributes.cs @@ -12,22 +12,16 @@ namespace Rdmp.Core.Validation.UIAttributes; /// Attribute for properties which should not be visible in user interfaces /// [System.AttributeUsage(System.AttributeTargets.Property)] -public class HideOnValidationUI : System.Attribute -{ -} +public class HideOnValidationUI : System.Attribute; /// /// Attribute for properties which should store a column name /// [System.AttributeUsage(System.AttributeTargets.Property)] -public class ExpectsColumnNameAsInput : System.Attribute -{ -} +public class ExpectsColumnNameAsInput : System.Attribute; /// /// Attribute for properties which should a large body of user entered text /// [System.AttributeUsage(System.AttributeTargets.Property)] -public class ExpectsLotsOfText : System.Attribute -{ -} \ No newline at end of file +public class ExpectsLotsOfText : System.Attribute; \ No newline at end of file diff --git a/Rdmp.Core/Validation/Validator.cs b/Rdmp.Core/Validation/Validator.cs index a41eb3ffda..529cb0b6b8 100644 --- a/Rdmp.Core/Validation/Validator.cs +++ b/Rdmp.Core/Validation/Validator.cs @@ -11,6 +11,7 @@ using System.IO; using System.Linq; using System.Text; +using System.Threading; using System.Xml; using System.Xml.Serialization; using Rdmp.Core.Repositories; @@ -205,12 +206,12 @@ public string SaveToXml(bool indent = true) return sb.ToString(); } - private static readonly object _oLockExtraTypes = new(); + private static readonly Lock OLockExtraTypes = new(); private static List _extraTypes; private static List RefreshExtraTypes() { - lock (_oLockExtraTypes) + lock (OLockExtraTypes) { return AppDomain.CurrentDomain.GetAssemblies().SelectMany(a => a.GetTypes()).Where( //type is @@ -231,7 +232,7 @@ private static List RefreshExtraTypes() public static List GetExtraTypes() { - lock (_oLockExtraTypes) + lock (OLockExtraTypes) { return _extraTypes ??= RefreshExtraTypes(); } diff --git a/Rdmp.UI.Tests/ChildProviderTests.cs b/Rdmp.UI.Tests/ChildProviderTests.cs index 4e7ac61cce..f2165b3464 100644 --- a/Rdmp.UI.Tests/ChildProviderTests.cs +++ b/Rdmp.UI.Tests/ChildProviderTests.cs @@ -58,19 +58,20 @@ public void ChildProviderGiven_TableInfoWith_NullDatabase() public void TestUpTo() { string[] skip = - { + [ "AllAggregateContainers", "_dataExportFilterManager", "dataExportRepository", "WriteLock", - "_oProjectNumberToCohortsDictionary", "_errorsCheckNotifier", "ProgressStopwatch","CohortIdentificationConfigurationRootFolderWithoutVersionedConfigurations" - }; + "_oProjectNumberToCohortsDictionaryLock", "_oProjectNumberToCohortsDictionary", "_errorsCheckNotifier", "ProgressStopwatch","CohortIdentificationConfigurationRootFolderWithoutVersionedConfigurations" + ]; + var skips = skip.ToHashSet(); // We have 2 providers and want to suck all the data out of one into the other var cp1 = new DataExportChildProvider(RepositoryLocator, null, ThrowImmediatelyCheckNotifier.Quiet, null); var cp2 = new DataExportChildProvider(RepositoryLocator, null, ThrowImmediatelyCheckNotifier.Quiet, null); //to start with let's make sure all fields and properties are different on the two classes except where we expect them to be the same - var bindFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static; + const BindingFlags bindFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static; - foreach (var prop in typeof(DataExportChildProvider).GetProperties().Where(p => !skip.Contains(p.Name))) + foreach (var prop in typeof(DataExportChildProvider).GetProperties().Where(p => !skips.Contains(p.Name))) { var val1 = prop.GetValue(cp1); var val2 = prop.GetValue(cp2); diff --git a/Rdmp.UI.Tests/DesignPatternTests/ClassFileEvaluation/DocumentationCrossExaminationTest.cs b/Rdmp.UI.Tests/DesignPatternTests/ClassFileEvaluation/DocumentationCrossExaminationTest.cs index 31c158d4bc..dee1abe00e 100644 --- a/Rdmp.UI.Tests/DesignPatternTests/ClassFileEvaluation/DocumentationCrossExaminationTest.cs +++ b/Rdmp.UI.Tests/DesignPatternTests/ClassFileEvaluation/DocumentationCrossExaminationTest.cs @@ -11,10 +11,11 @@ using System.Linq; using System.Text; using System.Text.RegularExpressions; +using Match = System.Text.RegularExpressions.Match; namespace Rdmp.UI.Tests.DesignPatternTests.ClassFileEvaluation; -internal class DocumentationCrossExaminationTest +internal partial class DocumentationCrossExaminationTest { private readonly DirectoryInfo _slndir; @@ -333,7 +334,7 @@ public void FindProblems(List csFilesFound) fileCommentTokens.Add(file, new HashSet()); //its a comment extract all pascal case words - foreach (Match word in Regex.Matches(line, @"\b([A-Z]\w+){2,}")) + foreach (Match word in PascalCased().Matches(line)) fileCommentTokens[file].Add(word.Value); } else @@ -476,7 +477,6 @@ private void EnsureMaximumGlossaryUse(string mdFile, List problems) var lineNumber = 0; var allLines = File.ReadAllLines(mdFile); - var allLinesRevised = allLines; var suggestedLinks = new Dictionary(); @@ -492,60 +492,63 @@ private void EnsureMaximumGlossaryUse(string mdFile, List problems) continue; //don't complain about keywords in code blocks - if (line.TrimStart().StartsWith("```") || line.TrimStart().StartsWith("> ```")) + var trimmed = line.TrimStart(); + if (trimmed.StartsWith("```", StringComparison.Ordinal) || trimmed.StartsWith("> ```", StringComparison.Ordinal)) inCodeBlock = !inCodeBlock; + if (inCodeBlock) continue; - if (!inCodeBlock) - foreach (Match match in rWords.Matches(line)) - if (glossaryHeaders.Contains(match.Value)) - { - //It's already got a link on it e.g. [DBMS] or it's "UNION - sometext" - if (match.Index - 1 > 0 - && - (line[match.Index - 1] == '[' || line[match.Index - 1] == '"')) - continue; - - - var path1 = new Uri(mdFile); - var path2 = new Uri(glossaryPath); - var diff = path1.MakeRelativeUri(path2); - var relPath = diff.OriginalString; - - if (!relPath.StartsWith(".")) - relPath = $"./{relPath}"; - - var suggestedLine = $"[{match.Value}]: {relPath}#{match.Value}"; - var markdownLink = $"[{match.Value}]({relPath}#{match.Value})"; - - //if it has spaces on either side - if (line[Math.Max(0, match.Index - 1)] == ' ' && line[ - Math.Min(line.Length - 1, - match.Index + match.Length)] == ' ' - //don't mess with lines that contain an image - && !line.Contains("![")) - allLinesRevised[lineNumber - 1] = line.Replace($" {match.Value} ", $" [{match.Value}] "); - - //also if we have a name like `Catalogue` it should probably be [Catalogue] instead so it works as a link - allLinesRevised[lineNumber - 1] = line.Replace($"`{match.Value}`", $"[{match.Value}]"); - - //if it is a novel occurrence - if (!allLines.Contains(suggestedLine) && !suggestedLinks.ContainsValue(suggestedLine) && !allLines.Contains(markdownLink) && !suggestedLinks.ContainsValue(markdownLink)) - { - suggestedLinks.Add(match.Value, suggestedLine); - problems.Add( - $"Glossary term should be link in {mdFile} line number {lineNumber}. Term is {match.Value}. Suggested link line is:\"{suggestedLine}\""); - } - } + foreach (var match in rWords.Matches(line).Where(match => glossaryHeaders.Contains(match.Value))) + { + //It's already got a link on it e.g. [DBMS] or it's "UNION - sometext" + if (match.Index - 1 > 0 + && + (line[match.Index - 1] == '[' || line[match.Index - 1] == '"')) + continue; + + + var path1 = new Uri(mdFile); + var path2 = new Uri(glossaryPath); + var diff = path1.MakeRelativeUri(path2); + var relPath = diff.OriginalString; + + if (!relPath.StartsWith('.')) + relPath = $"./{relPath}"; + + var suggestedLine = $"[{match.Value}]: {relPath}#{match.Value}"; + var markdownLink = $"[{match.Value}]({relPath}#{match.Value})"; + + //if it has spaces on either side + if (line[Math.Max(0, match.Index - 1)] == ' ' && line[ + Math.Min(line.Length - 1, + match.Index + match.Length)] == ' ' + //don't mess with lines that contain an image + && !line.Contains("![")) + allLines[lineNumber - 1] = line.Replace($" {match.Value} ", $" [{match.Value}] "); + + //also if we have a name like `Catalogue` it should probably be [Catalogue] instead so it works as a link + allLines[lineNumber - 1] = line.Replace($"`{match.Value}`", $"[{match.Value}]"); + + //if it is a novel occurrence + if (!allLines.Contains(suggestedLine) && !suggestedLinks.ContainsValue(suggestedLine) && !allLines.Contains(markdownLink) && !suggestedLinks.ContainsValue(markdownLink)) + { + suggestedLinks.Add(match.Value, suggestedLine); + problems.Add( + $"Glossary term should be link in {mdFile} line number {lineNumber}. Term is {match.Value}. Suggested link line is:\"{suggestedLine}\""); + } + } } // ReSharper disable once RedundantLogicalConditionalExpressionOperand // ReSharper disable once ConditionIsAlwaysTrueOrFalse if (suggestedLinks.Any() && ReWriteMarkdownToReferenceGlossary) { - File.WriteAllLines(mdFile, allLinesRevised); + File.WriteAllLines(mdFile, allLines); File.AppendAllText(mdFile, Environment.NewLine); File.AppendAllLines(mdFile, suggestedLinks.Values.Distinct()); } } + + [GeneratedRegex(@"\b([A-Z]\w+){2,}")] + private static partial Regex PascalCased(); } diff --git a/Rdmp.UI.Tests/DesignPatternTests/MarkdownCodeBlockTests.cs b/Rdmp.UI.Tests/DesignPatternTests/MarkdownCodeBlockTests.cs index 97064b6742..124e089138 100644 --- a/Rdmp.UI.Tests/DesignPatternTests/MarkdownCodeBlockTests.cs +++ b/Rdmp.UI.Tests/DesignPatternTests/MarkdownCodeBlockTests.cs @@ -248,9 +248,7 @@ public override void Activate(AggregateConfiguration target) #region 56df0867990f4b0397e51a6a49f7bdd0 [TypeDescriptionProvider(typeof(AbstractControlDescriptionProvider))] - public abstract class ANOTableUI_Design : RDMPSingleDatabaseObjectControl - { - } + public abstract class ANOTableUI_Design : RDMPSingleDatabaseObjectControl; #endregion } diff --git a/Rdmp.UI/ANOEngineeringUIs/ANOTableUI.cs b/Rdmp.UI/ANOEngineeringUIs/ANOTableUI.cs index 1b4f9773ca..287f8e781d 100644 --- a/Rdmp.UI/ANOEngineeringUIs/ANOTableUI.cs +++ b/Rdmp.UI/ANOEngineeringUIs/ANOTableUI.cs @@ -150,6 +150,4 @@ private void llServer_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e } [TypeDescriptionProvider(typeof(AbstractControlDescriptionProvider))] -public abstract class ANOTableUI_Design : RDMPSingleDatabaseObjectControl -{ -} \ No newline at end of file +public abstract class ANOTableUI_Design : RDMPSingleDatabaseObjectControl; \ No newline at end of file diff --git a/Rdmp.UI/ANOEngineeringUIs/ForwardEngineerANOCatalogueUI.cs b/Rdmp.UI/ANOEngineeringUIs/ForwardEngineerANOCatalogueUI.cs index a52e1f46d1..c32f97259f 100644 --- a/Rdmp.UI/ANOEngineeringUIs/ForwardEngineerANOCatalogueUI.cs +++ b/Rdmp.UI/ANOEngineeringUIs/ForwardEngineerANOCatalogueUI.cs @@ -602,6 +602,4 @@ private void btnLoadPlan_Click(object sender, EventArgs e) } [TypeDescriptionProvider(typeof(AbstractControlDescriptionProvider))] -public abstract class ForwardEngineerANOCatalogueUI_Design : RDMPSingleDatabaseObjectControl -{ -} \ No newline at end of file +public abstract class ForwardEngineerANOCatalogueUI_Design : RDMPSingleDatabaseObjectControl; \ No newline at end of file diff --git a/Rdmp.UI/AggregationUIs/Advanced/AggregateEditorUI.cs b/Rdmp.UI/AggregationUIs/Advanced/AggregateEditorUI.cs index 4805116258..4deeb2a373 100644 --- a/Rdmp.UI/AggregationUIs/Advanced/AggregateEditorUI.cs +++ b/Rdmp.UI/AggregationUIs/Advanced/AggregateEditorUI.cs @@ -544,6 +544,4 @@ private void olvJoin_ItemActivate(object sender, EventArgs e) } [TypeDescriptionProvider(typeof(AbstractControlDescriptionProvider))] -public abstract class AggregateEditor_Design : RDMPSingleDatabaseObjectControl -{ -} \ No newline at end of file +public abstract class AggregateEditor_Design : RDMPSingleDatabaseObjectControl; \ No newline at end of file diff --git a/Rdmp.UI/AggregationUIs/Advanced/SelectColumnUI.cs b/Rdmp.UI/AggregationUIs/Advanced/SelectColumnUI.cs index 2fef95d0fc..1afaad5ccb 100644 --- a/Rdmp.UI/AggregationUIs/Advanced/SelectColumnUI.cs +++ b/Rdmp.UI/AggregationUIs/Advanced/SelectColumnUI.cs @@ -74,24 +74,15 @@ public SelectColumnUI() olvIncluded.AspectGetter = rowObject => _includedColumns.Contains(rowObject) ? "Included" : "Not Included"; - olvGroupBy.AspectGetter = rowObject => + olvGroupBy.AspectGetter = static rowObject => { - var ad = rowObject as AggregateDimension; - if(ad != null) + return rowObject switch { - return ((AggregateDimension)rowObject).GroupBy; - } - var ei = rowObject as ExtractionInformation; - if (ei != null) - { - return ((ExtractionInformation)rowObject).GroupBy; - } - var acc = rowObject as AggregateCountColumn; - if (acc != null) - { - return ((AggregateCountColumn)rowObject).GroupBy; - } - return null; + AggregateDimension ad => ad.GroupBy, + ExtractionInformation ei => ei.GroupBy, + AggregateCountColumn acc => acc.GroupBy, + _ => null + }; }; olvSelectColumns.AlwaysGroupByColumn = olvIncluded; @@ -101,25 +92,20 @@ public SelectColumnUI() olvSelectColumns.CellEditFinished += CellEditFinished; - olvSelectColumns.SubItemChecking += (object sender, SubItemCheckingEventArgs args) => + olvSelectColumns.SubItemChecking += (_, args) => { - if (args.Column == olvGroupBy) + if (args.Column != olvGroupBy) return; + + switch (args.RowObject) { - var ad = args.RowObject as AggregateDimension; - if (ad != null) - { + case AggregateDimension ad: ad.GroupBy = !ad.GroupBy; ad.SaveToDatabase(); return; - } - var ei = args.RowObject as ExtractionInformation; - if (ei != null ) - { + case ExtractionInformation ei: ei.GroupBy = !ei.GroupBy; ei.SaveToDatabase(); return; - } - } }; @@ -169,7 +155,6 @@ private void olvSelectColumns_CellClick(object sender, CellClickEventArgs e) Save(dimension); //object doesn't exist, that might cause problems - return; } } else diff --git a/Rdmp.UI/AggregationUIs/AggregateGraphUI.cs b/Rdmp.UI/AggregationUIs/AggregateGraphUI.cs index 5850f32f4a..1ce7782129 100644 --- a/Rdmp.UI/AggregationUIs/AggregateGraphUI.cs +++ b/Rdmp.UI/AggregationUIs/AggregateGraphUI.cs @@ -292,39 +292,38 @@ private void LoadGraph(bool isRefresh = false, string startDateOverride = null, if (endDateOverride != null) builder.AxisEndDateOverride = endDateOverride; - var dateColumnName = "joinDt"; + const string dateColumnName = "joinDt"; if (isRefresh) { //wipe out data from dt that is between these dates var columnIndex = _dt.Columns.IndexOf(dateColumnName); - var incriment = axis.AxisIncrement; + var increment = axis.AxisIncrement; - var startDate = ConvertAxisOverridetoDate(startDateOverride.Trim('\''), incriment); - var endDate = ConvertAxisOverridetoDate(endDateOverride.Trim('\''), incriment); + var startDate = ConvertAxisOverridetoDate(startDateOverride.Trim('\''), increment); + var endDate = ConvertAxisOverridetoDate(endDateOverride.Trim('\''), increment); var rowsToDelete = _dt.Rows.Cast().Where(r => { //this could maybe be more efficient with some sort of lookup after the first time? var currentDT = new DateTime(); - if (incriment == AxisIncrement.Day) + if (increment == AxisIncrement.Day) { DateTime.TryParseExact(r.ItemArray[columnIndex].ToString(), "yyyy-mm-dd", CultureInfo.InvariantCulture, DateTimeStyles.None, out currentDT); } - if (incriment == AxisIncrement.Month) + if (increment == AxisIncrement.Month) { DateTime.TryParseExact(r.ItemArray[columnIndex].ToString(), "yyyy-mm", CultureInfo.InvariantCulture, DateTimeStyles.None, out currentDT); } - if (incriment == AxisIncrement.Quarter) + if (increment == AxisIncrement.Quarter) { - var year = r.ItemArray[columnIndex].ToString()[0..4]; + var year = r.ItemArray[columnIndex].ToString()[..4]; var asString = r.ItemArray[columnIndex].ToString(); - var quarter = Int32.Parse(asString.Substring(asString.Length - 1)) * 3; + var quarter = int.Parse(asString[^1..]) * 3; DateTime.TryParseExact($"{year}-{quarter}", "yyyy-mm", CultureInfo.InvariantCulture, DateTimeStyles.None, out currentDT); - } - if (incriment == AxisIncrement.Year) + if (increment == AxisIncrement.Year) { DateTime.TryParseExact(r.ItemArray[columnIndex].ToString(), "yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out currentDT); } @@ -432,8 +431,6 @@ private void PopulateGraphResults(QueryTimeColumn countColumn, AggregateContinuo //last column is always the X axis, then for each column before it add a series with Y values coming from that column for (var i = 0; i < _dt.Columns.Count - 1; i++) { - var index = i; - if (!haveSetSource) { try @@ -589,27 +586,27 @@ private void PopulateGraphResults(QueryTimeColumn countColumn, AggregateContinuo chart1.ChartAreas[0].AxisY.LabelStyle.Format = "{0:#,#}"; //avoid buffer overrun - if (index > chart1.Series.Count - 1) + if (i > chart1.Series.Count - 1) chart1.Series.Add(new Series()); chart1.ChartAreas[0].AxisX.ScaleView.Zoomable = true; chart1.ChartAreas[0].CursorX.AutoScroll = true; chart1.ChartAreas[0].CursorX.IsUserSelectionEnabled = true; - chart1.Series[index].XValueMember = _dt.Columns[0].ColumnName; - chart1.Series[index].YValueMembers = _dt.Columns[index + 1].ColumnName; + chart1.Series[i].XValueMember = _dt.Columns[0].ColumnName; + chart1.Series[i].YValueMembers = _dt.Columns[i + 1].ColumnName; if (axis != null) { - chart1.Series[index].ChartType = SeriesChartType.Line; + chart1.Series[i].ChartType = SeriesChartType.Line; //alternate in rotating style the various lines on the graph - chart1.Series[index].BorderDashStyle = _styleList[index % _styleList.Length]; - chart1.Series[index].BorderWidth = 2; + chart1.Series[i].BorderDashStyle = _styleList[i % _styleList.Length]; + chart1.Series[i].BorderWidth = 2; } else { - chart1.Series[index].ChartType = SeriesChartType.Column; + chart1.Series[i].ChartType = SeriesChartType.Column; if (_dt.Columns[0].DataType == typeof(decimal) || _dt.Columns[0].DataType == typeof(int)) @@ -625,7 +622,7 @@ private void PopulateGraphResults(QueryTimeColumn countColumn, AggregateContinuo } //name series based on column 3 or the aggregate name - chart1.Series[index].Name = _dt.Columns[index + 1].ColumnName; + chart1.Series[i].Name = _dt.Columns[i + 1].ColumnName; } //don't show legend if there's only one series @@ -936,7 +933,7 @@ private void btnResendQuery_Click(object sender, EventArgs e) private void btnRefreshData_Click(object sender, EventArgs e) { var axis = AggregateConfiguration.GetAxisIfAny(); - var getDateString = "GETDATE()"; + const string getDateString = "GETDATE()"; var startDate = axis.StartDate == getDateString ? "" : axis.StartDate; var endDate = axis.EndDate == getDateString ? "" : axis.EndDate; var dialog = new AggregateGraphDateSelector(startDate, endDate); @@ -974,6 +971,4 @@ private void btnCache_Click(object sender, EventArgs e) } [TypeDescriptionProvider(typeof(AbstractControlDescriptionProvider))] -public abstract class AggregateGraph_Design : RDMPSingleDatabaseObjectControl -{ -} \ No newline at end of file +public abstract class AggregateGraph_Design : RDMPSingleDatabaseObjectControl; \ No newline at end of file diff --git a/Rdmp.UI/CatalogueSummary/CatalogueDQEResultsUI.cs b/Rdmp.UI/CatalogueSummary/CatalogueDQEResultsUI.cs index 8e4705d884..c276fe8e68 100644 --- a/Rdmp.UI/CatalogueSummary/CatalogueDQEResultsUI.cs +++ b/Rdmp.UI/CatalogueSummary/CatalogueDQEResultsUI.cs @@ -105,6 +105,4 @@ public override void SetDatabaseObject(IActivateItems activator, Catalogue datab } [TypeDescriptionProvider(typeof(AbstractControlDescriptionProvider))] -public abstract class CatalogueSummaryScreen_Design : RDMPSingleDatabaseObjectControl -{ -} \ No newline at end of file +public abstract class CatalogueSummaryScreen_Design : RDMPSingleDatabaseObjectControl; \ No newline at end of file diff --git a/Rdmp.UI/CatalogueSummary/DataQualityReporting/SubComponents/ConsequenceBar.cs b/Rdmp.UI/CatalogueSummary/DataQualityReporting/SubComponents/ConsequenceBar.cs index 1563b9fdc7..10de919a0c 100644 --- a/Rdmp.UI/CatalogueSummary/DataQualityReporting/SubComponents/ConsequenceBar.cs +++ b/Rdmp.UI/CatalogueSummary/DataQualityReporting/SubComponents/ConsequenceBar.cs @@ -106,16 +106,15 @@ protected override void OnPaintBackground(PaintEventArgs e) e.Graphics.FillRectangle(bWrong, new Rectangle(missingRightPoint, 0, wrongWidth, heightOfNullsBarStart)); e.Graphics.FillRectangle(bInvalid, new Rectangle(wrongRightPoint, 0, invalidWidth, heightOfNullsBarStart)); - if (!string.IsNullOrWhiteSpace(Label)) - { - var rect = e.Graphics.MeasureString(Label, Font); + if (string.IsNullOrWhiteSpace(Label)) return; - var textX = 0; - var textY = 2; + var rect = e.Graphics.MeasureString(Label, Font); - e.Graphics.FillRectangle(Brushes.LightGray, textX, textY, rect.Width, rect.Height); - e.Graphics.DrawString(Label, Font, Brushes.Black, textX, textY); - } + const int textX = 0; + const int textY = 2; + + e.Graphics.FillRectangle(Brushes.LightGray, textX, textY, rect.Width, rect.Height); + e.Graphics.DrawString(Label, Font, Brushes.Black, textX, textY); } public void GenerateToolTip() diff --git a/Rdmp.UI/CatalogueSummary/LoadEvents/ResolveFatalErrors.cs b/Rdmp.UI/CatalogueSummary/LoadEvents/ResolveFatalErrors.cs index 083ce5a18c..8db6f705ec 100644 --- a/Rdmp.UI/CatalogueSummary/LoadEvents/ResolveFatalErrors.cs +++ b/Rdmp.UI/CatalogueSummary/LoadEvents/ResolveFatalErrors.cs @@ -57,13 +57,13 @@ public ResolveFatalErrors(IActivateItems activator, LogManager logManager, Archi private void btnSaveAndClose_Click(object sender, EventArgs e) { - var newState = DataLoadInfo.FatalErrorStates.Resolved; + const DataLoadInfo.FatalErrorStates newState = DataLoadInfo.FatalErrorStates.Resolved; if (string.IsNullOrEmpty(Explanation.Text)) Explanation.Text = "No Explanation"; //resolve it in the database - _logManager.ResolveFatalErrors(_toResolve.Select(f => f.ID).ToArray(), newState, Explanation.Text); + _logManager.ResolveFatalErrors(_toResolve.Select(static f => f.ID).ToArray(), newState, Explanation.Text); //resolve it in memory foreach (var error in _toResolve) diff --git a/Rdmp.UI/ChartLookAndFeelSetter.cs b/Rdmp.UI/ChartLookAndFeelSetter.cs index e0644900a5..bf6f793be0 100644 --- a/Rdmp.UI/ChartLookAndFeelSetter.cs +++ b/Rdmp.UI/ChartLookAndFeelSetter.cs @@ -54,7 +54,7 @@ public static void PopulateYearMonthChart(Chart chart, DataTable dt, string yAxi chart.ChartAreas[0].AxisY.TitleForeColor = Color.DarkGray; chart.ChartAreas[0].AxisY.LabelStyle.ForeColor = Color.DarkGray; - var rowsPerYear = 12; + const int rowsPerYear = 12; var datasetLifespanInYears = dt.Rows.Count / rowsPerYear; if (dt.Rows.Count == 0) diff --git a/Rdmp.UI/ChecksUI/ChecksUI.cs b/Rdmp.UI/ChecksUI/ChecksUI.cs index dd490a933f..c87048f6f7 100644 --- a/Rdmp.UI/ChecksUI/ChecksUI.cs +++ b/Rdmp.UI/ChecksUI/ChecksUI.cs @@ -202,12 +202,12 @@ public bool OnCheckPerformed(CheckEventArgs args) return shouldApplyFix; } - private object olockYesNoToAll = new(); + private readonly Lock _olockYesNoToAll = new(); private bool DoesUserWantToApplyFix(CheckEventArgs args) { if (InvokeRequired) - lock (olockYesNoToAll) + lock (_olockYesNoToAll) { return Invoke(() => DoesUserWantToApplyFix(args)); } diff --git a/Rdmp.UI/ChecksUI/RAGSmiley.cs b/Rdmp.UI/ChecksUI/RAGSmiley.cs index 9761fb68a0..cd3346ac88 100644 --- a/Rdmp.UI/ChecksUI/RAGSmiley.cs +++ b/Rdmp.UI/ChecksUI/RAGSmiley.cs @@ -8,10 +8,12 @@ using System.ComponentModel; using System.Drawing; using System.Linq; +using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; using Rdmp.Core.ReusableLibraryCode.Checks; using Rdmp.UI.SimpleDialogs; +using Timer = System.Windows.Forms.Timer; namespace Rdmp.UI.ChecksUI; @@ -154,8 +156,8 @@ public void Reset() private ToMemoryCheckNotifier memoryCheckNotifier = new(); private Task _checkTask; - private object oTaskLock = new(); - private Timer _timer; + private readonly Lock _oTaskLock = new(); + private readonly Timer _timer; private CheckResult _state; private Exception _exception; @@ -218,7 +220,7 @@ public void SetVisible(bool visible) public void StartChecking(ICheckable checkable) { - lock (oTaskLock) + lock (_oTaskLock) { //if there is already a Task and it has not completed if (_checkTask is { IsCompleted: false }) diff --git a/Rdmp.UI/ChecksUI/RAGSmileyToolStrip.cs b/Rdmp.UI/ChecksUI/RAGSmileyToolStrip.cs index 2dffee1d34..4daabb3e4d 100644 --- a/Rdmp.UI/ChecksUI/RAGSmileyToolStrip.cs +++ b/Rdmp.UI/ChecksUI/RAGSmileyToolStrip.cs @@ -7,11 +7,13 @@ using System; using System.Drawing; using System.Linq; +using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; using Rdmp.Core.Icons.IconProvision; using Rdmp.Core.ReusableLibraryCode.Checks; using Rdmp.UI.SimpleDialogs; +using Timer = System.Windows.Forms.Timer; namespace Rdmp.UI.ChecksUI; @@ -84,7 +86,7 @@ private void T_Tick(object sender, EventArgs e) private ToMemoryCheckNotifier memoryCheckNotifier = new(); private Task _checkTask; - private readonly object _oTaskLock = new(); + private readonly Lock _oTaskLock = new(); private readonly Timer _timer; protected override void OnClick(EventArgs e) diff --git a/Rdmp.UI/CohortUI/CohortSourceManagement/ExternalCohortTableUI.cs b/Rdmp.UI/CohortUI/CohortSourceManagement/ExternalCohortTableUI.cs index eb12c0b4ad..81dbab9829 100644 --- a/Rdmp.UI/CohortUI/CohortSourceManagement/ExternalCohortTableUI.cs +++ b/Rdmp.UI/CohortUI/CohortSourceManagement/ExternalCohortTableUI.cs @@ -99,6 +99,4 @@ protected override void SetBindings(BinderWithErrorProviderFactory rules, Extern } [TypeDescriptionProvider(typeof(AbstractControlDescriptionProvider))] -public abstract class ExternalCohortTableUI_Design : RDMPSingleDatabaseObjectControl -{ -} \ No newline at end of file +public abstract class ExternalCohortTableUI_Design : RDMPSingleDatabaseObjectControl; \ No newline at end of file diff --git a/Rdmp.UI/CohortUI/ExtractableCohortUI.cs b/Rdmp.UI/CohortUI/ExtractableCohortUI.cs index 006b1a6078..0202c51ffb 100644 --- a/Rdmp.UI/CohortUI/ExtractableCohortUI.cs +++ b/Rdmp.UI/CohortUI/ExtractableCohortUI.cs @@ -243,6 +243,4 @@ private void btnShowProject_Click(object sender, EventArgs e) } [TypeDescriptionProvider(typeof(AbstractControlDescriptionProvider))] -public abstract class ExtractableCohortUI_Design : RDMPSingleDatabaseObjectControl -{ -} \ No newline at end of file +public abstract class ExtractableCohortUI_Design : RDMPSingleDatabaseObjectControl; \ No newline at end of file diff --git a/Rdmp.UI/Collections/CohortIdentificationCollectionUI.cs b/Rdmp.UI/Collections/CohortIdentificationCollectionUI.cs index ef5157a26c..2c1b98d16e 100644 --- a/Rdmp.UI/Collections/CohortIdentificationCollectionUI.cs +++ b/Rdmp.UI/Collections/CohortIdentificationCollectionUI.cs @@ -74,9 +74,9 @@ public override void SetItemActivator(IActivateItems activator) tlvCohortIdentificationConfigurations.CanExpandGetter = delegate (object x) { - if (x is CohortIdentificationConfiguration) + if (x is CohortIdentificationConfiguration configuration) { - return ((CohortIdentificationConfiguration)x).GetVersions().Count > 0; + return configuration.GetVersions().Count > 0; } return Activator.CoreChildProvider.GetChildren(x).Length > 0; @@ -84,11 +84,11 @@ public override void SetItemActivator(IActivateItems activator) tlvCohortIdentificationConfigurations.ChildrenGetter = delegate (object x) { - if (x is CohortIdentificationConfiguration) + if (x is CohortIdentificationConfiguration cic) { - CohortIdentificationConfiguration cic = (CohortIdentificationConfiguration)x; return cic.GetVersions(); } + return Activator.CoreChildProvider.GetChildren(x); }; diff --git a/Rdmp.UI/Collections/DataExportCollectionUI.cs b/Rdmp.UI/Collections/DataExportCollectionUI.cs index 4b1a7ee567..cf57595211 100644 --- a/Rdmp.UI/Collections/DataExportCollectionUI.cs +++ b/Rdmp.UI/Collections/DataExportCollectionUI.cs @@ -156,30 +156,16 @@ private void SetupToolStrip() CommonFunctionality.Add(_refresh); CommonFunctionality.Add(new ExecuteCommandCreateNewCohortIdentificationConfiguration(Activator) - { PromptToPickAProject = true }, "Cohort Builder Query", null, NewMenu); + { PromptToPickAProject = true }, "Cohort Builder Query", null, NewMenu); var uiFactory = new AtomicCommandUIFactory(Activator); var cohortSubmenu = new ToolStripMenuItem("Cohort"); - cohortSubmenu.DropDownItems.AddRange( - new[] - { - // from cic - uiFactory.CreateMenuItem( - new ExecuteCommandCreateNewCohortByExecutingACohortIdentificationConfiguration(Activator, null) - { OverrideCommandName = "From Cohort Builder Query" }), - - // from file - uiFactory.CreateMenuItem(new ExecuteCommandCreateNewCohortFromFile(Activator, null) - { OverrideCommandName = "From File" }), - - // from catalogue - uiFactory.CreateMenuItem(new ExecuteCommandCreateNewCohortFromCatalogue(Activator, (Catalogue)null) - { OverrideCommandName = "From Catalogue" }), - - // from table - uiFactory.CreateMenuItem(new ExecuteCommandCreateNewCohortFromTable(Activator, null) - { OverrideCommandName = "From Table" }) - }); + cohortSubmenu.DropDownItems.AddRange(uiFactory.CreateMenuItem( + new ExecuteCommandCreateNewCohortByExecutingACohortIdentificationConfiguration(Activator, null) + { OverrideCommandName = "From Cohort Builder Query" }), uiFactory.CreateMenuItem(new ExecuteCommandCreateNewCohortFromFile(Activator, null) + { OverrideCommandName = "From File" }), uiFactory.CreateMenuItem(new ExecuteCommandCreateNewCohortFromCatalogue(Activator, (Catalogue)null) + { OverrideCommandName = "From Catalogue" }), uiFactory.CreateMenuItem(new ExecuteCommandCreateNewCohortFromTable(Activator, null) + { OverrideCommandName = "From Table" })); CommonFunctionality.Add(cohortSubmenu, NewMenu); CommonFunctionality.Add(new ToolStripSeparator(), NewMenu); diff --git a/Rdmp.UI/Collections/Providers/CheckColumnProvider.cs b/Rdmp.UI/Collections/Providers/CheckColumnProvider.cs index b0914241a9..76a6a87db2 100644 --- a/Rdmp.UI/Collections/Providers/CheckColumnProvider.cs +++ b/Rdmp.UI/Collections/Providers/CheckColumnProvider.cs @@ -7,6 +7,7 @@ using System.Collections.Generic; using System.Drawing; using System.Linq; +using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; using BrightIdeasSoftware; @@ -55,9 +56,9 @@ public void CheckCheckables() } //reset the dictionary - lock (ocheckResultsDictionaryLock) + lock (_ocheckResultsDictionaryLock) { - checkResultsDictionary = new Dictionary(); + _checkResultsDictionary = new Dictionary(); } checkingTask = new Task(() => @@ -68,9 +69,9 @@ public void CheckCheckables() var notifier = new ToMemoryCheckNotifier(); checkable.Check(notifier); - lock (ocheckResultsDictionaryLock) + lock (_ocheckResultsDictionaryLock) { - checkResultsDictionary.Add(checkable, notifier.GetWorst()); + _checkResultsDictionary.Add(checkable, notifier.GetWorst()); } } }); @@ -100,14 +101,14 @@ public void EnsureChecksColumnVisible() } } - private object ocheckResultsDictionaryLock = new(); - private Dictionary checkResultsDictionary = new(); + private readonly Lock _ocheckResultsDictionaryLock = new(); + private Dictionary _checkResultsDictionary = new(); public void RecordWorst(ICheckable o, CheckResult result) { - lock (checkResultsDictionary) + lock (_checkResultsDictionary) { - checkResultsDictionary[o] = result; + _checkResultsDictionary[o] = result; if (_tree.IndexOf(o) != -1) _tree.RefreshObject(o); @@ -121,9 +122,9 @@ private Bitmap CheckImageGetter(object rowobject) if (rowobject is not ICheckable checkable) return null; - lock (ocheckResultsDictionaryLock) + lock (_ocheckResultsDictionaryLock) { - if (checkResultsDictionary.TryGetValue(checkable, out var value)) + if (_checkResultsDictionary.TryGetValue(checkable, out var value)) return _iconProvider.GetImage(value).ImageToBitmap(); } diff --git a/Rdmp.UI/Collections/RDMPCollectionCommonFunctionality.cs b/Rdmp.UI/Collections/RDMPCollectionCommonFunctionality.cs index d59d007b4f..0dd041d10d 100644 --- a/Rdmp.UI/Collections/RDMPCollectionCommonFunctionality.cs +++ b/Rdmp.UI/Collections/RDMPCollectionCommonFunctionality.cs @@ -465,7 +465,7 @@ private void CreateColorIndicator(TreeListView tree, RDMPCollection collection) if (Tree.Parent == null || collection == RDMPCollection.None) return; - var indicatorHeight = BackColorProvider.IndicatorBarSuggestedHeight; + const int indicatorHeight = BackColorProvider.IndicatorBarSuggestedHeight; var ctrl = new Control { diff --git a/Rdmp.UI/Collections/RDMPCollectionUI.cs b/Rdmp.UI/Collections/RDMPCollectionUI.cs index 0afcde5309..d413b25be8 100644 --- a/Rdmp.UI/Collections/RDMPCollectionUI.cs +++ b/Rdmp.UI/Collections/RDMPCollectionUI.cs @@ -34,6 +34,4 @@ public virtual void ConsultAboutClosing(object sender, FormClosingEventArgs e) } [TypeDescriptionProvider(typeof(AbstractControlDescriptionProvider))] -public class RDMPCollectionUI_Design : RDMPUserControl -{ -} \ No newline at end of file +public class RDMPCollectionUI_Design : RDMPUserControl; \ No newline at end of file diff --git a/Rdmp.UI/Collections/SessionCollectionUI.cs b/Rdmp.UI/Collections/SessionCollectionUI.cs index 797f31df20..9e154817ea 100644 --- a/Rdmp.UI/Collections/SessionCollectionUI.cs +++ b/Rdmp.UI/Collections/SessionCollectionUI.cs @@ -170,17 +170,14 @@ private void InitializeComponent() { olvTree = new BrightIdeasSoftware.TreeListView(); olvName = new BrightIdeasSoftware.OLVColumn(); - ((System.ComponentModel.ISupportInitialize)olvTree).BeginInit(); + ((ISupportInitialize)olvTree).BeginInit(); SuspendLayout(); // // olvRecent // olvTree.AllColumns.Add(olvName); olvTree.CellEditUseWholeCell = false; - olvTree.Columns.AddRange(new ColumnHeader[] - { - olvName - }); + olvTree.Columns.AddRange(olvName); olvTree.Cursor = Cursors.Default; olvTree.Dock = DockStyle.Fill; olvTree.FullRowSelect = true; diff --git a/Rdmp.UI/CommandExecution/AtomicCommands/ExecuteCommandReOrderAggregate.cs b/Rdmp.UI/CommandExecution/AtomicCommands/ExecuteCommandReOrderAggregate.cs index ae5049b68a..967cc15dbd 100644 --- a/Rdmp.UI/CommandExecution/AtomicCommands/ExecuteCommandReOrderAggregate.cs +++ b/Rdmp.UI/CommandExecution/AtomicCommands/ExecuteCommandReOrderAggregate.cs @@ -38,7 +38,6 @@ public ExecuteCommandReOrderAggregate(IActivateItems activator, { SetImpossible( "Cannot ReOrder, you should first move both objects into the same container (UNION / EXCEPT / INTERSECT)"); - return; } } @@ -54,7 +53,6 @@ public ExecuteCommandReOrderAggregate(IActivateItems activator, { SetImpossible( "Cannot ReOrder, you should first move both objects into the same container (UNION / EXCEPT / INTERSECT)"); - return; } } diff --git a/Rdmp.UI/CommandExecution/AtomicCommands/ExecuteCommandReorderFilter.cs b/Rdmp.UI/CommandExecution/AtomicCommands/ExecuteCommandReorderFilter.cs index 7db441b3a8..57297d5a80 100644 --- a/Rdmp.UI/CommandExecution/AtomicCommands/ExecuteCommandReorderFilter.cs +++ b/Rdmp.UI/CommandExecution/AtomicCommands/ExecuteCommandReorderFilter.cs @@ -7,7 +7,6 @@ using Rdmp.Core.Curation.Data; using Rdmp.Core.MapsDirectlyToDatabaseTable; using Rdmp.UI.ItemActivation; -using System; using System.Linq; namespace Rdmp.UI.CommandExecution.AtomicCommands; diff --git a/Rdmp.UI/CommandExecution/AtomicCommands/ExecuteCommandViewCatalogueExtractionSqlUI.cs b/Rdmp.UI/CommandExecution/AtomicCommands/ExecuteCommandViewCatalogueExtractionSqlUI.cs index 812826157f..cb81d51765 100644 --- a/Rdmp.UI/CommandExecution/AtomicCommands/ExecuteCommandViewCatalogueExtractionSqlUI.cs +++ b/Rdmp.UI/CommandExecution/AtomicCommands/ExecuteCommandViewCatalogueExtractionSqlUI.cs @@ -12,7 +12,6 @@ using Rdmp.Core.ReusableLibraryCode.Icons.IconProvision; using Rdmp.UI.ExtractionUIs; using Rdmp.UI.ItemActivation; -using Rdmp.UI.Overview; using SixLabors.ImageSharp; using SixLabors.ImageSharp.PixelFormats; diff --git a/Rdmp.UI/CommandExecution/Proposals/ProposeExecutionWhenTargetIsCatalogue.cs b/Rdmp.UI/CommandExecution/Proposals/ProposeExecutionWhenTargetIsCatalogue.cs index 9b2a9a3a6d..c96f1c40a6 100644 --- a/Rdmp.UI/CommandExecution/Proposals/ProposeExecutionWhenTargetIsCatalogue.cs +++ b/Rdmp.UI/CommandExecution/Proposals/ProposeExecutionWhenTargetIsCatalogue.cs @@ -11,7 +11,6 @@ using Rdmp.Core.Curation.Data; using Rdmp.UI.ItemActivation; using Rdmp.UI.MainFormUITabs; -using Rdmp.UI.Overview; namespace Rdmp.UI.CommandExecution.Proposals; diff --git a/Rdmp.UI/CommandExecution/Proposals/ProposeExecutionWhenTargetIsConcreteFilter.cs b/Rdmp.UI/CommandExecution/Proposals/ProposeExecutionWhenTargetIsConcreteFilter.cs index 98d290b1b0..c3f169ae89 100644 --- a/Rdmp.UI/CommandExecution/Proposals/ProposeExecutionWhenTargetIsConcreteFilter.cs +++ b/Rdmp.UI/CommandExecution/Proposals/ProposeExecutionWhenTargetIsConcreteFilter.cs @@ -32,9 +32,8 @@ public override ICommandExecution ProposeExecution(ICombineToMakeCommand cmd, Co return cmd switch { FilterCombineable sourceFilterCommand => - !sourceFilterCommand.Filter.Equals(targetFilter) && sourceFilterCommand.Filter is ConcreteFilter && sourceFilterCommand.Filter.FilterContainer_ID == targetFilter.FilterContainer_ID ? - new ExecuteCommandReorderFilter(ItemActivator, (ConcreteFilter)sourceFilterCommand.Filter, targetFilter, insertOption) - : null, + !sourceFilterCommand.Filter.Equals(targetFilter) && sourceFilterCommand.Filter is ConcreteFilter filter && sourceFilterCommand.Filter.FilterContainer_ID == targetFilter.FilterContainer_ID ? new ExecuteCommandReorderFilter(ItemActivator, filter, targetFilter, insertOption) + : null, _ => null }; } diff --git a/Rdmp.UI/CommandExecution/RDMPCommandExecutionFactory.cs b/Rdmp.UI/CommandExecution/RDMPCommandExecutionFactory.cs index 56428ec692..c14c03dd44 100644 --- a/Rdmp.UI/CommandExecution/RDMPCommandExecutionFactory.cs +++ b/Rdmp.UI/CommandExecution/RDMPCommandExecutionFactory.cs @@ -7,6 +7,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Threading; using Rdmp.Core.CommandExecution; using Rdmp.Core.CommandExecution.AtomicCommands; using Rdmp.Core.CommandExecution.Combining; @@ -25,9 +26,9 @@ namespace Rdmp.UI.CommandExecution; public class RDMPCommandExecutionFactory : ICommandExecutionFactory { private readonly IActivateItems _activator; - private Dictionary> _cachedAnswers = new(); - private object oLockCachedAnswers = new(); - private List _proposers = new(); + private readonly Dictionary> _cachedAnswers = new(); + private readonly Lock _oLockCachedAnswers = new(); + private readonly List _proposers = []; public RDMPCommandExecutionFactory(IActivateItems activator) { @@ -49,7 +50,7 @@ public RDMPCommandExecutionFactory(IActivateItems activator) public ICommandExecution Create(ICombineToMakeCommand cmd, object targetModel, InsertOption insertOption = InsertOption.Default) { - lock (oLockCachedAnswers) + lock (_oLockCachedAnswers) { var proposition = new CachedDropTarget(targetModel, insertOption); diff --git a/Rdmp.UI/CredentialsUIs/DataAccessCredentialsUI.cs b/Rdmp.UI/CredentialsUIs/DataAccessCredentialsUI.cs index 61e58806a2..42c13283b9 100644 --- a/Rdmp.UI/CredentialsUIs/DataAccessCredentialsUI.cs +++ b/Rdmp.UI/CredentialsUIs/DataAccessCredentialsUI.cs @@ -38,6 +38,4 @@ protected override void SetBindings(BinderWithErrorProviderFactory rules, DataAc } [TypeDescriptionProvider(typeof(AbstractControlDescriptionProvider))] -public abstract class DataAccessCredentialsUI_Design : RDMPSingleDatabaseObjectControl -{ -} \ No newline at end of file +public abstract class DataAccessCredentialsUI_Design : RDMPSingleDatabaseObjectControl; \ No newline at end of file diff --git a/Rdmp.UI/DashboardTabs/DashboardLayoutUI.cs b/Rdmp.UI/DashboardTabs/DashboardLayoutUI.cs index 83f036955e..d766e08075 100644 --- a/Rdmp.UI/DashboardTabs/DashboardLayoutUI.cs +++ b/Rdmp.UI/DashboardTabs/DashboardLayoutUI.cs @@ -143,6 +143,4 @@ private void btnAddDashboardControl_Click(object sender, EventArgs e) } [TypeDescriptionProvider(typeof(AbstractControlDescriptionProvider))] -public abstract class DashboardLayoutUI_Design : RDMPSingleDatabaseObjectControl -{ -} \ No newline at end of file +public abstract class DashboardLayoutUI_Design : RDMPSingleDatabaseObjectControl; \ No newline at end of file diff --git a/Rdmp.UI/DataLoadUIs/ANOUIs/ANOTableManagement/ColumnInfoToANOTableConverterUI.cs b/Rdmp.UI/DataLoadUIs/ANOUIs/ANOTableManagement/ColumnInfoToANOTableConverterUI.cs index 1ae048184f..3526967942 100644 --- a/Rdmp.UI/DataLoadUIs/ANOUIs/ANOTableManagement/ColumnInfoToANOTableConverterUI.cs +++ b/Rdmp.UI/DataLoadUIs/ANOUIs/ANOTableManagement/ColumnInfoToANOTableConverterUI.cs @@ -445,6 +445,4 @@ private void tbSuffix_TextChanged(object sender, EventArgs e) [TypeDescriptionProvider( typeof(AbstractControlDescriptionProvider))] -public abstract class ColumnInfoToANOTableConverterUI_Design : RDMPSingleDatabaseObjectControl -{ -} \ No newline at end of file +public abstract class ColumnInfoToANOTableConverterUI_Design : RDMPSingleDatabaseObjectControl; \ No newline at end of file diff --git a/Rdmp.UI/DataLoadUIs/ANOUIs/PreLoadDiscarding/PreLoadDiscardedColumnUI.cs b/Rdmp.UI/DataLoadUIs/ANOUIs/PreLoadDiscarding/PreLoadDiscardedColumnUI.cs index fcc3d0d2ec..59baadc991 100644 --- a/Rdmp.UI/DataLoadUIs/ANOUIs/PreLoadDiscarding/PreLoadDiscardedColumnUI.cs +++ b/Rdmp.UI/DataLoadUIs/ANOUIs/PreLoadDiscarding/PreLoadDiscardedColumnUI.cs @@ -81,6 +81,4 @@ protected override void SetBindings(BinderWithErrorProviderFactory rules, PreLoa } [TypeDescriptionProvider(typeof(AbstractControlDescriptionProvider))] -public abstract class PreLoadDiscardedColumnUI_Design : RDMPSingleDatabaseObjectControl -{ -} \ No newline at end of file +public abstract class PreLoadDiscardedColumnUI_Design : RDMPSingleDatabaseObjectControl; \ No newline at end of file diff --git a/Rdmp.UI/DataLoadUIs/LoadMetadataUIs/LoadDiagram/LoadDiagramServerNode.cs b/Rdmp.UI/DataLoadUIs/LoadMetadataUIs/LoadDiagram/LoadDiagramServerNode.cs index 350d940476..7904e5cf52 100644 --- a/Rdmp.UI/DataLoadUIs/LoadMetadataUIs/LoadDiagram/LoadDiagramServerNode.cs +++ b/Rdmp.UI/DataLoadUIs/LoadMetadataUIs/LoadDiagram/LoadDiagramServerNode.cs @@ -37,7 +37,6 @@ public LoadDiagramServerNode(LoadBubble bubble, DiscoveredDatabase database, Tab { _bubble = bubble; _database = database; - var config1 = config; var serverName = database.Server.Name; _description = bubble switch @@ -73,9 +72,9 @@ public LoadDiagramServerNode(LoadBubble bubble, DiscoveredDatabase database, Tab //if it is live yield all the lookups if (_bubble == LoadBubble.Live) foreach (var kvp in _liveDatabaseDictionary) - Children.Add(new LoadDiagramDatabaseNode(_bubble, kvp.Key, kvp.Value, config1)); + Children.Add(new LoadDiagramDatabaseNode(_bubble, kvp.Key, kvp.Value, config)); else - Children.Add(new LoadDiagramDatabaseNode(_bubble, _database, loadTables, config1)); + Children.Add(new LoadDiagramDatabaseNode(_bubble, _database, loadTables, config)); } public IEnumerable GetChildren() => Children; diff --git a/Rdmp.UI/DataLoadUIs/LoadMetadataUIs/LoadDiagram/LoadDiagramUI.cs b/Rdmp.UI/DataLoadUIs/LoadMetadataUIs/LoadDiagram/LoadDiagramUI.cs index 8b11a83fdc..81a28e0e5a 100644 --- a/Rdmp.UI/DataLoadUIs/LoadMetadataUIs/LoadDiagram/LoadDiagramUI.cs +++ b/Rdmp.UI/DataLoadUIs/LoadMetadataUIs/LoadDiagram/LoadDiagramUI.cs @@ -352,6 +352,4 @@ private void tbFilter_TextChanged(object sender, EventArgs e) } [TypeDescriptionProvider(typeof(AbstractControlDescriptionProvider))] -public abstract class LoadDiagram_Design : RDMPSingleDatabaseObjectControl -{ -} \ No newline at end of file +public abstract class LoadDiagram_Design : RDMPSingleDatabaseObjectControl; \ No newline at end of file diff --git a/Rdmp.UI/DataLoadUIs/LoadMetadataUIs/LoadMetadataUI.cs b/Rdmp.UI/DataLoadUIs/LoadMetadataUIs/LoadMetadataUI.cs index 0222ebd5d0..cb6950804d 100644 --- a/Rdmp.UI/DataLoadUIs/LoadMetadataUIs/LoadMetadataUI.cs +++ b/Rdmp.UI/DataLoadUIs/LoadMetadataUIs/LoadMetadataUI.cs @@ -37,6 +37,4 @@ protected override void SetBindings(BinderWithErrorProviderFactory rules, LoadMe } [TypeDescriptionProvider(typeof(AbstractControlDescriptionProvider))] -public abstract class LoadMetadataUI_Design : RDMPSingleDatabaseObjectControl -{ -} \ No newline at end of file +public abstract class LoadMetadataUI_Design : RDMPSingleDatabaseObjectControl; \ No newline at end of file diff --git a/Rdmp.UI/DataLoadUIs/LoadMetadataUIs/LoadProgressAndCacheUIs/CacheProgressUI.cs b/Rdmp.UI/DataLoadUIs/LoadMetadataUIs/LoadProgressAndCacheUIs/CacheProgressUI.cs index 33185ae87b..f77fa852f4 100644 --- a/Rdmp.UI/DataLoadUIs/LoadMetadataUIs/LoadProgressAndCacheUIs/CacheProgressUI.cs +++ b/Rdmp.UI/DataLoadUIs/LoadMetadataUIs/LoadProgressAndCacheUIs/CacheProgressUI.cs @@ -229,6 +229,4 @@ private void tbChunkPeriod_TextChanged(object sender, EventArgs e) } [TypeDescriptionProvider(typeof(AbstractControlDescriptionProvider))] -public abstract class CacheProgressUI_Design : RDMPSingleDatabaseObjectControl -{ -} \ No newline at end of file +public abstract class CacheProgressUI_Design : RDMPSingleDatabaseObjectControl; \ No newline at end of file diff --git a/Rdmp.UI/DataLoadUIs/LoadMetadataUIs/LoadProgressAndCacheUIs/LoadProgressUI.cs b/Rdmp.UI/DataLoadUIs/LoadMetadataUIs/LoadProgressAndCacheUIs/LoadProgressUI.cs index 1f73be6ab5..d7b1ab255c 100644 --- a/Rdmp.UI/DataLoadUIs/LoadMetadataUIs/LoadProgressAndCacheUIs/LoadProgressUI.cs +++ b/Rdmp.UI/DataLoadUIs/LoadMetadataUIs/LoadProgressAndCacheUIs/LoadProgressUI.cs @@ -119,6 +119,4 @@ protected override void SetBindings(BinderWithErrorProviderFactory rules, LoadPr } [TypeDescriptionProvider(typeof(AbstractControlDescriptionProvider))] -public abstract class LoadProgressUI_Design : RDMPSingleDatabaseObjectControl -{ -} \ No newline at end of file +public abstract class LoadProgressUI_Design : RDMPSingleDatabaseObjectControl; \ No newline at end of file diff --git a/Rdmp.UI/DataLoadUIs/LoadMetadataUIs/LoadProgressAndCacheUIs/PermissionWindowUI.cs b/Rdmp.UI/DataLoadUIs/LoadMetadataUIs/LoadProgressAndCacheUIs/PermissionWindowUI.cs index a647f4b73e..78b0f2b354 100644 --- a/Rdmp.UI/DataLoadUIs/LoadMetadataUIs/LoadProgressAndCacheUIs/PermissionWindowUI.cs +++ b/Rdmp.UI/DataLoadUIs/LoadMetadataUIs/LoadProgressAndCacheUIs/PermissionWindowUI.cs @@ -125,6 +125,4 @@ private void tbDay_TextChanged(object sender, EventArgs e) } [TypeDescriptionProvider(typeof(AbstractControlDescriptionProvider))] -public abstract class PermissionWindowUI_Design : RDMPSingleDatabaseObjectControl -{ -} \ No newline at end of file +public abstract class PermissionWindowUI_Design : RDMPSingleDatabaseObjectControl; \ No newline at end of file diff --git a/Rdmp.UI/DataLoadUIs/LoadMetadataUIs/ProcessTasks/ExeProcessTaskUI.cs b/Rdmp.UI/DataLoadUIs/LoadMetadataUIs/ProcessTasks/ExeProcessTaskUI.cs index ec41c11563..904df0322f 100644 --- a/Rdmp.UI/DataLoadUIs/LoadMetadataUIs/ProcessTasks/ExeProcessTaskUI.cs +++ b/Rdmp.UI/DataLoadUIs/LoadMetadataUIs/ProcessTasks/ExeProcessTaskUI.cs @@ -146,6 +146,4 @@ private void btnBrowse_Click(object sender, EventArgs e) } [TypeDescriptionProvider(typeof(AbstractControlDescriptionProvider))] -public abstract class ExeProcessTaskUI_Design : RDMPSingleDatabaseObjectControl -{ -} \ No newline at end of file +public abstract class ExeProcessTaskUI_Design : RDMPSingleDatabaseObjectControl; \ No newline at end of file diff --git a/Rdmp.UI/DataLoadUIs/LoadMetadataUIs/ProcessTasks/PluginProcessTaskUI.cs b/Rdmp.UI/DataLoadUIs/LoadMetadataUIs/ProcessTasks/PluginProcessTaskUI.cs index bf78323be1..9166c9d6fd 100644 --- a/Rdmp.UI/DataLoadUIs/LoadMetadataUIs/ProcessTasks/PluginProcessTaskUI.cs +++ b/Rdmp.UI/DataLoadUIs/LoadMetadataUIs/ProcessTasks/PluginProcessTaskUI.cs @@ -148,6 +148,4 @@ private void tbName_TextChanged(object sender, EventArgs e) } [TypeDescriptionProvider(typeof(AbstractControlDescriptionProvider))] -public abstract class PluginProcessTaskUI_Design : RDMPSingleDatabaseObjectControl -{ -} \ No newline at end of file +public abstract class PluginProcessTaskUI_Design : RDMPSingleDatabaseObjectControl; \ No newline at end of file diff --git a/Rdmp.UI/DataLoadUIs/LoadMetadataUIs/ProcessTasks/SqlBakFileProcessTaskUI.cs b/Rdmp.UI/DataLoadUIs/LoadMetadataUIs/ProcessTasks/SqlBakFileProcessTaskUI.cs index 01a39a833b..406eb628bd 100644 --- a/Rdmp.UI/DataLoadUIs/LoadMetadataUIs/ProcessTasks/SqlBakFileProcessTaskUI.cs +++ b/Rdmp.UI/DataLoadUIs/LoadMetadataUIs/ProcessTasks/SqlBakFileProcessTaskUI.cs @@ -123,6 +123,4 @@ private void label3_Click(object sender, EventArgs e) } [TypeDescriptionProvider(typeof(AbstractControlDescriptionProvider))] -public abstract class SqlBakFileProcessTask_Design : RDMPSingleDatabaseObjectControl -{ -} \ No newline at end of file +public abstract class SqlBakFileProcessTask_Design : RDMPSingleDatabaseObjectControl; \ No newline at end of file diff --git a/Rdmp.UI/DataLoadUIs/LoadMetadataUIs/ProcessTasks/SqlProcessTaskUI.cs b/Rdmp.UI/DataLoadUIs/LoadMetadataUIs/ProcessTasks/SqlProcessTaskUI.cs index f4d43b3089..68cd3279e6 100644 --- a/Rdmp.UI/DataLoadUIs/LoadMetadataUIs/ProcessTasks/SqlProcessTaskUI.cs +++ b/Rdmp.UI/DataLoadUIs/LoadMetadataUIs/ProcessTasks/SqlProcessTaskUI.cs @@ -168,6 +168,4 @@ private void btnBrowse_Click(object sender, EventArgs e) } [TypeDescriptionProvider(typeof(AbstractControlDescriptionProvider))] -public abstract class SqlProcessTaskUI_Design : RDMPSingleDatabaseObjectControl -{ -} \ No newline at end of file +public abstract class SqlProcessTaskUI_Design : RDMPSingleDatabaseObjectControl; \ No newline at end of file diff --git a/Rdmp.UI/DataLoadUIs/ModuleUIs/DataFlowSources/ExplicitColumnTypeUI.cs b/Rdmp.UI/DataLoadUIs/ModuleUIs/DataFlowSources/ExplicitColumnTypeUI.cs index 5be89567ab..7a2ec78195 100644 --- a/Rdmp.UI/DataLoadUIs/ModuleUIs/DataFlowSources/ExplicitColumnTypeUI.cs +++ b/Rdmp.UI/DataLoadUIs/ModuleUIs/DataFlowSources/ExplicitColumnTypeUI.cs @@ -23,14 +23,7 @@ public ExplicitColumnTypeUI(string name, Type t) { InitializeComponent(); - ddType.Items.AddRange( - new[] - { - typeof(string), - typeof(double), - typeof(bool), - typeof(DateTime) - }); + ddType.Items.AddRange(typeof(string), typeof(double), typeof(bool), typeof(DateTime)); textBox1.Text = name; ddType.SelectedItem = t; diff --git a/Rdmp.UI/DataQualityUIs/DQEExecutionControlUI.cs b/Rdmp.UI/DataQualityUIs/DQEExecutionControlUI.cs index 79fff65145..30ba364ba0 100644 --- a/Rdmp.UI/DataQualityUIs/DQEExecutionControlUI.cs +++ b/Rdmp.UI/DataQualityUIs/DQEExecutionControlUI.cs @@ -69,6 +69,4 @@ public override void ConsultAboutClosing(object sender, FormClosingEventArgs e) } [TypeDescriptionProvider(typeof(AbstractControlDescriptionProvider))] -public abstract class DQEExecutionControl_Design : RDMPSingleDatabaseObjectControl -{ -} \ No newline at end of file +public abstract class DQEExecutionControl_Design : RDMPSingleDatabaseObjectControl; \ No newline at end of file diff --git a/Rdmp.UI/DataRelease/DataReleaseUI.cs b/Rdmp.UI/DataRelease/DataReleaseUI.cs index 2a45103cf4..8e3b4bb91b 100644 --- a/Rdmp.UI/DataRelease/DataReleaseUI.cs +++ b/Rdmp.UI/DataRelease/DataReleaseUI.cs @@ -266,6 +266,4 @@ private void ResetChecksUI(object sender, EventArgs e) } [TypeDescriptionProvider(typeof(AbstractControlDescriptionProvider))] -public abstract class DataReleaseUI_Design : RDMPSingleDatabaseObjectControl -{ -} \ No newline at end of file +public abstract class DataReleaseUI_Design : RDMPSingleDatabaseObjectControl; \ No newline at end of file diff --git a/Rdmp.UI/DataViewing/ViewSQLAndResultsWithDataGridUI.cs b/Rdmp.UI/DataViewing/ViewSQLAndResultsWithDataGridUI.cs index 43122441bd..f887d327f2 100644 --- a/Rdmp.UI/DataViewing/ViewSQLAndResultsWithDataGridUI.cs +++ b/Rdmp.UI/DataViewing/ViewSQLAndResultsWithDataGridUI.cs @@ -275,23 +275,24 @@ private void LoadDataTableAsync(DiscoveredServer server, string sql) private static void MorphBinaryColumns(DataTable table) { - var targetNames = table.Columns.Cast() - .Where(col => col.DataType.Equals(typeof(byte[]))) - .Select(col => col.ColumnName).ToList(); - foreach (var colName in targetNames) + var dataColumns = table.Columns.Cast() + .Where(static col => col.DataType == typeof(byte[])) + .ToList(); + foreach (var column in dataColumns) { // add new column and put it where the old column was - var tmpName = "new"; - table.Columns.Add(new DataColumn(tmpName, typeof(string))); - table.Columns[tmpName].SetOrdinal(table.Columns[colName].Ordinal); + const string tmpName = "new"; + var newCol = new DataColumn(tmpName, typeof(string)); + table.Columns.Add(newCol); + newCol.SetOrdinal(column.Ordinal); // fill in values in new column for every row foreach (DataRow row in table.Rows) - row[tmpName] = $"0x{string.Join("", ((byte[])row[colName]).Select(b => b.ToString("X2")).ToArray())}"; + row[newCol] = $"0x{string.Join("", ((byte[])row[column]).Select(static b => b.ToString("X2")).ToArray())}"; // cleanup - table.Columns.Remove(colName); - table.Columns[tmpName].ColumnName = colName; + table.Columns.Remove(column); + newCol.ColumnName = column.ColumnName; } } diff --git a/Rdmp.UI/ExtractionUIs/ExtractionInformationUI.cs b/Rdmp.UI/ExtractionUIs/ExtractionInformationUI.cs index 7da337c7eb..9e8519b482 100644 --- a/Rdmp.UI/ExtractionUIs/ExtractionInformationUI.cs +++ b/Rdmp.UI/ExtractionUIs/ExtractionInformationUI.cs @@ -310,6 +310,4 @@ public override string GetTabName() } [TypeDescriptionProvider(typeof(AbstractControlDescriptionProvider))] -public abstract class ExtractionInformationUI_Design : RDMPSingleDatabaseObjectControl -{ -} \ No newline at end of file +public abstract class ExtractionInformationUI_Design : RDMPSingleDatabaseObjectControl; \ No newline at end of file diff --git a/Rdmp.UI/ExtractionUIs/FilterUIs/ExtractionFilterUI.cs b/Rdmp.UI/ExtractionUIs/FilterUIs/ExtractionFilterUI.cs index f6315e0070..1c73b1dcc6 100644 --- a/Rdmp.UI/ExtractionUIs/FilterUIs/ExtractionFilterUI.cs +++ b/Rdmp.UI/ExtractionUIs/FilterUIs/ExtractionFilterUI.cs @@ -229,6 +229,4 @@ public void RefreshBus_RefreshObject(object sender, RefreshObjectEventArgs e) } [TypeDescriptionProvider(typeof(AbstractControlDescriptionProvider))] -public abstract class ExtractionFilterUI_Design : RDMPSingleDatabaseObjectControl -{ -} \ No newline at end of file +public abstract class ExtractionFilterUI_Design : RDMPSingleDatabaseObjectControl; \ No newline at end of file diff --git a/Rdmp.UI/ExtractionUIs/FilterUIs/ParameterUIs/ExtractionFilterParameterSetUI.cs b/Rdmp.UI/ExtractionUIs/FilterUIs/ParameterUIs/ExtractionFilterParameterSetUI.cs index ee98f1d455..73800f7420 100644 --- a/Rdmp.UI/ExtractionUIs/FilterUIs/ParameterUIs/ExtractionFilterParameterSetUI.cs +++ b/Rdmp.UI/ExtractionUIs/FilterUIs/ParameterUIs/ExtractionFilterParameterSetUI.cs @@ -83,6 +83,4 @@ public override void SetDatabaseObject(IActivateItems activator, ExtractionFilte [TypeDescriptionProvider( typeof(AbstractControlDescriptionProvider))] public abstract class - ExtractionFilterParameterSetUI_Design : RDMPSingleDatabaseObjectControl -{ -} \ No newline at end of file + ExtractionFilterParameterSetUI_Design : RDMPSingleDatabaseObjectControl; \ No newline at end of file diff --git a/Rdmp.UI/ExtractionUIs/FilterUIs/ParameterUIs/ParameterCollectionUI.cs b/Rdmp.UI/ExtractionUIs/FilterUIs/ParameterUIs/ParameterCollectionUI.cs index de702ad19f..e331be1d7b 100644 --- a/Rdmp.UI/ExtractionUIs/FilterUIs/ParameterUIs/ParameterCollectionUI.cs +++ b/Rdmp.UI/ExtractionUIs/FilterUIs/ParameterUIs/ParameterCollectionUI.cs @@ -375,7 +375,6 @@ private void olvParameters_CellToolTipShowing(object sender, ToolTipShowingEvent e.Title = "Parameter is declared at a higher level"; e.Text = $"This parameter is declared at {Options.ParameterManager.GetLevelForParameter(sqlParameter)} level which is higher than the level you are editing ({Options.CurrentLevel}). You cannot change higher level parameters from here, look at the 'Owner' column to see which object the global belongs to"; - return; } } diff --git a/Rdmp.UI/ExtractionUIs/JoinsAndLookups/JoinConfigurationUI.cs b/Rdmp.UI/ExtractionUIs/JoinsAndLookups/JoinConfigurationUI.cs index c4c3097053..f620ee9a23 100644 --- a/Rdmp.UI/ExtractionUIs/JoinsAndLookups/JoinConfigurationUI.cs +++ b/Rdmp.UI/ExtractionUIs/JoinsAndLookups/JoinConfigurationUI.cs @@ -271,6 +271,4 @@ private void olv_ItemActivate(object sender, EventArgs e) } [TypeDescriptionProvider(typeof(AbstractControlDescriptionProvider))] -public abstract class JoinConfiguration_Design : RDMPSingleDatabaseObjectControl -{ -} \ No newline at end of file +public abstract class JoinConfiguration_Design : RDMPSingleDatabaseObjectControl; \ No newline at end of file diff --git a/Rdmp.UI/ExtractionUIs/JoinsAndLookups/LookupBrowserUI.cs b/Rdmp.UI/ExtractionUIs/JoinsAndLookups/LookupBrowserUI.cs index 3219a8c8da..1e29a7b812 100644 --- a/Rdmp.UI/ExtractionUIs/JoinsAndLookups/LookupBrowserUI.cs +++ b/Rdmp.UI/ExtractionUIs/JoinsAndLookups/LookupBrowserUI.cs @@ -4,7 +4,6 @@ // 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. // You should have received a copy of the GNU General Public License along with RDMP. If not, see . -using System.ComponentModel; using System.Data; using System.Windows.Forms; using Rdmp.Core.Curation.Data; @@ -14,7 +13,6 @@ using Rdmp.Core.ReusableLibraryCode.DataAccess; using Rdmp.UI.ItemActivation; using Rdmp.UI.ScintillaHelper; -using Rdmp.UI.TestsAndSetup.ServicePropogation; using ScintillaNET; namespace Rdmp.UI.ExtractionUIs.JoinsAndLookups; @@ -120,9 +118,4 @@ private void SendQuery() foreach (DataGridViewColumn column in dataGridView1.Columns) column.AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells; } -} - -[TypeDescriptionProvider(typeof(AbstractControlDescriptionProvider))] -public abstract class LookupBrowserUI_Design : RDMPSingleDatabaseObjectControl -{ } \ No newline at end of file diff --git a/Rdmp.UI/ExtractionUIs/JoinsAndLookups/LookupBrowserUI_Design.cs b/Rdmp.UI/ExtractionUIs/JoinsAndLookups/LookupBrowserUI_Design.cs new file mode 100644 index 0000000000..5d8b9c2833 --- /dev/null +++ b/Rdmp.UI/ExtractionUIs/JoinsAndLookups/LookupBrowserUI_Design.cs @@ -0,0 +1,9 @@ +using System.ComponentModel; +using System.Windows.Forms; +using Rdmp.Core.Curation.Data; +using Rdmp.UI.TestsAndSetup.ServicePropogation; + +namespace Rdmp.UI.ExtractionUIs.JoinsAndLookups; + +[TypeDescriptionProvider(typeof(AbstractControlDescriptionProvider))] +public abstract class LookupBrowserUI_Design : RDMPSingleDatabaseObjectControl; \ No newline at end of file diff --git a/Rdmp.UI/ExtractionUIs/JoinsAndLookups/LookupConfigurationUI.cs b/Rdmp.UI/ExtractionUIs/JoinsAndLookups/LookupConfigurationUI.cs index 02ebde98f1..f03f50a644 100644 --- a/Rdmp.UI/ExtractionUIs/JoinsAndLookups/LookupConfigurationUI.cs +++ b/Rdmp.UI/ExtractionUIs/JoinsAndLookups/LookupConfigurationUI.cs @@ -369,6 +369,4 @@ private void pictureBox4_Click(object sender, EventArgs e) } [TypeDescriptionProvider(typeof(AbstractControlDescriptionProvider))] -public abstract class LookupConfiguration_Design : RDMPSingleDatabaseObjectControl -{ -} \ No newline at end of file +public abstract class LookupConfiguration_Design : RDMPSingleDatabaseObjectControl; \ No newline at end of file diff --git a/Rdmp.UI/ExtractionUIs/JoinsAndLookups/LookupUI.cs b/Rdmp.UI/ExtractionUIs/JoinsAndLookups/LookupUI.cs index f8ec00c3e3..33c125de23 100644 --- a/Rdmp.UI/ExtractionUIs/JoinsAndLookups/LookupUI.cs +++ b/Rdmp.UI/ExtractionUIs/JoinsAndLookups/LookupUI.cs @@ -84,6 +84,4 @@ private void olv_KeyUp(object sender, KeyEventArgs e) } [TypeDescriptionProvider(typeof(AbstractControlDescriptionProvider))] -public abstract class LookupUI_Design : RDMPSingleDatabaseObjectControl -{ -} \ No newline at end of file +public abstract class LookupUI_Design : RDMPSingleDatabaseObjectControl; \ No newline at end of file diff --git a/Rdmp.UI/ExtractionUIs/ReOrderCatalogueItemsUI.cs b/Rdmp.UI/ExtractionUIs/ReOrderCatalogueItemsUI.cs index c4a104c6b6..a6b58a8c48 100644 --- a/Rdmp.UI/ExtractionUIs/ReOrderCatalogueItemsUI.cs +++ b/Rdmp.UI/ExtractionUIs/ReOrderCatalogueItemsUI.cs @@ -9,6 +9,7 @@ using System.ComponentModel; using System.Drawing; using System.Linq; +using System.Threading; using System.Windows.Forms; using BrightIdeasSoftware; using Rdmp.Core; @@ -94,7 +95,7 @@ private void RefreshUIFromDatabase() private void lbDesiredOrder_KeyUp(object sender, KeyEventArgs e) { if (e.KeyCode == Keys.Delete) - lock (oDrawLock) + lock (_oDrawLock) { var toDelete = lbDesiredOrder.SelectedIndices.Cast().OrderByDescending(i => i).ToArray(); @@ -104,7 +105,7 @@ private void lbDesiredOrder_KeyUp(object sender, KeyEventArgs e) RecomputeOrderAndHighlight(); } else if (e.KeyCode == Keys.V && e.Control) - lock (oDrawLock) + lock (_oDrawLock) { lbDesiredOrder.Items.AddRange(UsefulStuff .GetArrayOfColumnNamesFromStringPastedInByUser(Clipboard.GetText()).ToArray()); @@ -220,7 +221,7 @@ private void WorkOutNewOrderAndAddToNewOrderListbox() private void lbCurrentOrder_DrawItem(object sender, DrawItemEventArgs e) { - lock (oDrawLock) + lock (_oDrawLock) { var listBox = sender as ListBox; @@ -258,12 +259,12 @@ private void lbCurrentOrder_DrawItem(object sender, DrawItemEventArgs e) } } - private object oDrawLock = new(); + private readonly Lock _oDrawLock = new(); private void lbDesiredOrder_DrawItem(object sender, DrawItemEventArgs e) { - lock (oDrawLock) + lock (_oDrawLock) { if (e.Index == -1) return; @@ -375,6 +376,4 @@ private void olvExtractionInformations_ItemActivate(object sender, EventArgs e) } [TypeDescriptionProvider(typeof(AbstractControlDescriptionProvider))] -public abstract class ReOrderCatalogueItems_Design : RDMPSingleDatabaseObjectControl -{ -} \ No newline at end of file +public abstract class ReOrderCatalogueItems_Design : RDMPSingleDatabaseObjectControl; \ No newline at end of file diff --git a/Rdmp.UI/ExtractionUIs/ViewExtractionSqlUI.cs b/Rdmp.UI/ExtractionUIs/ViewExtractionSqlUI.cs index 0fc43738a3..13aef59edc 100644 --- a/Rdmp.UI/ExtractionUIs/ViewExtractionSqlUI.cs +++ b/Rdmp.UI/ExtractionUIs/ViewExtractionSqlUI.cs @@ -227,6 +227,4 @@ private void olvFilters_ItemChecked(object sender, ItemCheckedEventArgs e) } [TypeDescriptionProvider(typeof(AbstractControlDescriptionProvider))] -public abstract class ViewExtractionSql_Design : RDMPSingleDatabaseObjectControl -{ -} \ No newline at end of file +public abstract class ViewExtractionSql_Design : RDMPSingleDatabaseObjectControl; \ No newline at end of file diff --git a/Rdmp.UI/LoadExecutionUIs/ExecuteCacheProgressUI.cs b/Rdmp.UI/LoadExecutionUIs/ExecuteCacheProgressUI.cs index fb3a2c1bcd..b67369d32a 100644 --- a/Rdmp.UI/LoadExecutionUIs/ExecuteCacheProgressUI.cs +++ b/Rdmp.UI/LoadExecutionUIs/ExecuteCacheProgressUI.cs @@ -65,6 +65,4 @@ public override void ConsultAboutClosing(object sender, FormClosingEventArgs e) } [TypeDescriptionProvider(typeof(AbstractControlDescriptionProvider))] -public abstract class CachingEngineUI_Design : RDMPSingleDatabaseObjectControl -{ -} \ No newline at end of file +public abstract class CachingEngineUI_Design : RDMPSingleDatabaseObjectControl; \ No newline at end of file diff --git a/Rdmp.UI/LoadExecutionUIs/ExecuteLoadMetadataUI.cs b/Rdmp.UI/LoadExecutionUIs/ExecuteLoadMetadataUI.cs index 424f03fd44..4e2ea60784 100644 --- a/Rdmp.UI/LoadExecutionUIs/ExecuteLoadMetadataUI.cs +++ b/Rdmp.UI/LoadExecutionUIs/ExecuteLoadMetadataUI.cs @@ -203,6 +203,4 @@ private void btnRefreshLoadProgresses_Click(object sender, EventArgs e) } [TypeDescriptionProvider(typeof(AbstractControlDescriptionProvider))] -public abstract class DatasetLoadControl_Design : RDMPSingleDatabaseObjectControl -{ -} \ No newline at end of file +public abstract class DatasetLoadControl_Design : RDMPSingleDatabaseObjectControl; \ No newline at end of file diff --git a/Rdmp.UI/LocationsMenu/ChoosePlatformDatabasesUI.cs b/Rdmp.UI/LocationsMenu/ChoosePlatformDatabasesUI.cs index 2704913e81..6727db88b2 100644 --- a/Rdmp.UI/LocationsMenu/ChoosePlatformDatabasesUI.cs +++ b/Rdmp.UI/LocationsMenu/ChoosePlatformDatabasesUI.cs @@ -384,39 +384,40 @@ private void btnUseYamlFile_Click(object sender, EventArgs e) { using var fb = new OpenFileDialog(); var result = fb.ShowDialog(); - if (result == DialogResult.OK) + if (result != DialogResult.OK) return; + + try { - try + var location = new DirectoryInfo(fb.FileName); + using var reader = new StreamReader(location.FullName); + // Load the stream + var yaml = new YamlStream(); + yaml.Load(reader); + var docs = yaml.Documents.First().AllNodes.Select(static n => n.ToString()).ToList(); + string catalogueConnectionString = null; + string dataExportConnectionString = null; + foreach (var item in docs.Select(static (value, i) => new { i, value })) { - var location = new DirectoryInfo(fb.FileName); - using (var reader = new StreamReader(location.FullName)) + switch (item.value) { - // Load the stream - var yaml = new YamlStream(); - yaml.Load(reader); - var docs = yaml.Documents.First().AllNodes.Select(n => n.ToString()); - string catalogueConnectionString = null; - string dataExportConnectionString = null; - foreach (var item in docs.Select((value, i) => new { i, value })) - { - var value = item.value; - - if (value == "CatalogueConnectionString") catalogueConnectionString = docs.ToList()[item.i + 1]; - if (value == "DataExportConnectionString") dataExportConnectionString = docs.ToList()[item.i + 1]; - } - if (catalogueConnectionString != null) tbCatalogueConnectionString.Text = catalogueConnectionString; - if (dataExportConnectionString != null) tbDataExportManagerConnectionString.Text = dataExportConnectionString; - + case "CatalogueConnectionString": + catalogueConnectionString = docs[item.i + 1]; + break; + case "DataExportConnectionString": + dataExportConnectionString = docs[item.i + 1]; + break; } } - catch (Exception) - { - //Unable to parse yaml file - tbCatalogueConnectionString.Text = null; - tbDataExportManagerConnectionString.Text = null; - } - }; + if (catalogueConnectionString != null) tbCatalogueConnectionString.Text = catalogueConnectionString; + if (dataExportConnectionString != null) tbDataExportManagerConnectionString.Text = dataExportConnectionString; + } + catch (Exception) + { + //Unable to parse yaml file + tbCatalogueConnectionString.Text = null; + tbDataExportManagerConnectionString.Text = null; + } } private void btnBrowseForCatalogue_Click(object sender, EventArgs e) diff --git a/Rdmp.UI/LocationsMenu/Ticketing/TicketingSystemConfigurationUI.cs b/Rdmp.UI/LocationsMenu/Ticketing/TicketingSystemConfigurationUI.cs index 7402177e20..9023dbf62a 100644 --- a/Rdmp.UI/LocationsMenu/Ticketing/TicketingSystemConfigurationUI.cs +++ b/Rdmp.UI/LocationsMenu/Ticketing/TicketingSystemConfigurationUI.cs @@ -161,7 +161,7 @@ private void btnCheck_Click(object sender, EventArgs e) { var knownStatuses = instance.GetAvailableStatuses(); var requestedStatuses = tbReleases.Text.Split(',').Where(s => s.Trim() != ""); - if (!requestedStatuses.Any()) checksUI1.OnCheckPerformed(new CheckEventArgs($"No Release status set", CheckResult.Fail)); + if (!requestedStatuses.Any()) checksUI1.OnCheckPerformed(new CheckEventArgs("No Release status set", CheckResult.Fail)); foreach (var status in requestedStatuses.Where(s => !knownStatuses.Contains(s.Trim()))) { diff --git a/Rdmp.UI/Logging/LoggingTabUI.cs b/Rdmp.UI/Logging/LoggingTabUI.cs index 6fe1746f25..05dac409e4 100644 --- a/Rdmp.UI/Logging/LoggingTabUI.cs +++ b/Rdmp.UI/Logging/LoggingTabUI.cs @@ -38,11 +38,11 @@ namespace Rdmp.UI.Logging; /// public class LoggingTabUI : LoggingTab_Design { - private ToolStripTextBox tbContentFilter = new(); - private ToolStripLabel label1 = new("Filter:"); - private ToolStripLabel label2 = new("Top:"); - private ToolStripTextBox tbTop = new() { Text = "10000" }; - private ToolStripButton cbPreferNewer = new("Newest") { CheckOnClick = true, Checked = true }; + private readonly ToolStripTextBox tbContentFilter = new(); + private readonly ToolStripLabel label1 = new("Filter:"); + private readonly ToolStripLabel label2 = new("Top:"); + private readonly ToolStripTextBox tbTop = new() { Text = "10000" }; + private readonly ToolStripButton cbPreferNewer = new("Newest") { CheckOnClick = true, Checked = true }; private Label lblCurrentFilter; private PictureBox pbRemoveFilter; @@ -170,9 +170,10 @@ private IEnumerable GetCommands(int rowIdnex) private static void AddFreeTextSearchColumn(DataTable dt) { var dcRowString = dt.Columns.Add("_RowString", typeof(string)); + var sb = new StringBuilder(); foreach (DataRow dataRow in dt.Rows) { - var sb = new StringBuilder(); + sb.Clear(); for (var i = 0; i < dt.Columns.Count - 1; i++) { sb.Append(dataRow[i]); @@ -217,7 +218,7 @@ private void InitializeComponent() // // pbRemoveFilter // - pbRemoveFilter.Anchor = (AnchorStyles)(AnchorStyles.Top | AnchorStyles.Right); + pbRemoveFilter.Anchor = AnchorStyles.Top | AnchorStyles.Right; pbRemoveFilter.BackColor = Color.Goldenrod; pbRemoveFilter.Image = (Image)resources.GetObject("pbRemoveFilter.Image"); pbRemoveFilter.Location = new Point(820, 3); @@ -230,8 +231,8 @@ private void InitializeComponent() // // lblCurrentFilter // - lblCurrentFilter.Anchor = (AnchorStyles)(AnchorStyles.Top | AnchorStyles.Left - | AnchorStyles.Right); + lblCurrentFilter.Anchor = AnchorStyles.Top | AnchorStyles.Left + | AnchorStyles.Right; lblCurrentFilter.BackColor = Color.Goldenrod; lblCurrentFilter.ForeColor = SystemColors.ControlLightLight; lblCurrentFilter.Location = new Point(3, 3); @@ -307,7 +308,7 @@ public void SetFilter(LogViewerFilter filter) //push the old filter _navigationTrack?.Append(Filter); if (_back != null) - _back.Enabled = _navigationTrack.CanBack(); + _back.Enabled = _navigationTrack?.CanBack() == true; if (filter.IsEmpty) { @@ -439,6 +440,4 @@ private void cbPreferNewer_CheckedChanged(object sender, EventArgs e) } [TypeDescriptionProvider(typeof(AbstractControlDescriptionProvider))] -public abstract class LoggingTab_Design : RDMPSingleDatabaseObjectControl -{ -} \ No newline at end of file +public abstract class LoggingTab_Design : RDMPSingleDatabaseObjectControl; \ No newline at end of file diff --git a/Rdmp.UI/MainFormUITabs/CatalogueItemUI.cs b/Rdmp.UI/MainFormUITabs/CatalogueItemUI.cs index 983f0b20c5..4c534ca172 100644 --- a/Rdmp.UI/MainFormUITabs/CatalogueItemUI.cs +++ b/Rdmp.UI/MainFormUITabs/CatalogueItemUI.cs @@ -135,6 +135,4 @@ private void splitContainer1_SplitterMoved(object sender, SplitterEventArgs e) } [TypeDescriptionProvider(typeof(AbstractControlDescriptionProvider))] -public abstract class CatalogueItemUI_Design : RDMPSingleDatabaseObjectControl -{ -} \ No newline at end of file +public abstract class CatalogueItemUI_Design : RDMPSingleDatabaseObjectControl; \ No newline at end of file diff --git a/Rdmp.UI/MainFormUITabs/CatalogueUI.cs b/Rdmp.UI/MainFormUITabs/CatalogueUI.cs index fd74e9144e..01e7ca655e 100644 --- a/Rdmp.UI/MainFormUITabs/CatalogueUI.cs +++ b/Rdmp.UI/MainFormUITabs/CatalogueUI.cs @@ -272,6 +272,4 @@ private void c_tbSourceUrl_TextChanged(object sender, EventArgs e) } [TypeDescriptionProvider(typeof(AbstractControlDescriptionProvider))] -public abstract class CatalogueUI_Design : RDMPSingleDatabaseObjectControl -{ -} \ No newline at end of file +public abstract class CatalogueUI_Design : RDMPSingleDatabaseObjectControl; \ No newline at end of file diff --git a/Rdmp.UI/MainFormUITabs/ConnectionStringKeywordUI.cs b/Rdmp.UI/MainFormUITabs/ConnectionStringKeywordUI.cs index 8ba575d491..e3a3928c10 100644 --- a/Rdmp.UI/MainFormUITabs/ConnectionStringKeywordUI.cs +++ b/Rdmp.UI/MainFormUITabs/ConnectionStringKeywordUI.cs @@ -72,6 +72,4 @@ private void ddDatabaseType_SelectedIndexChanged(object sender, EventArgs e) } [TypeDescriptionProvider(typeof(AbstractControlDescriptionProvider))] -public abstract class ConnectionStringKeywordUI_Design : RDMPSingleDatabaseObjectControl -{ -} \ No newline at end of file +public abstract class ConnectionStringKeywordUI_Design : RDMPSingleDatabaseObjectControl; \ No newline at end of file diff --git a/Rdmp.UI/MainFormUITabs/ExtractionProgressUI.cs b/Rdmp.UI/MainFormUITabs/ExtractionProgressUI.cs index 548965b935..ddc1e3360b 100644 --- a/Rdmp.UI/MainFormUITabs/ExtractionProgressUI.cs +++ b/Rdmp.UI/MainFormUITabs/ExtractionProgressUI.cs @@ -147,6 +147,4 @@ private void ddRetry_SelectedIndexChanged(object sender, EventArgs e) } [TypeDescriptionProvider(typeof(AbstractControlDescriptionProvider))] -public abstract class ExtractionProgressUI_Design : RDMPSingleDatabaseObjectControl -{ -} \ No newline at end of file +public abstract class ExtractionProgressUI_Design : RDMPSingleDatabaseObjectControl; \ No newline at end of file diff --git a/Rdmp.UI/MainFormUITabs/SubComponents/ExternalDatabaseServerUI.cs b/Rdmp.UI/MainFormUITabs/SubComponents/ExternalDatabaseServerUI.cs index 90c794f77b..4a386b62e3 100644 --- a/Rdmp.UI/MainFormUITabs/SubComponents/ExternalDatabaseServerUI.cs +++ b/Rdmp.UI/MainFormUITabs/SubComponents/ExternalDatabaseServerUI.cs @@ -115,6 +115,4 @@ private void ddDatabaseType_SelectedIndexChanged(object sender, EventArgs e) } [TypeDescriptionProvider(typeof(AbstractControlDescriptionProvider))] -public abstract class ExternalDatabaseServerUI_Design : RDMPSingleDatabaseObjectControl -{ -} \ No newline at end of file +public abstract class ExternalDatabaseServerUI_Design : RDMPSingleDatabaseObjectControl; \ No newline at end of file diff --git a/Rdmp.UI/MainFormUITabs/SubComponents/TableInfoUI.cs b/Rdmp.UI/MainFormUITabs/SubComponents/TableInfoUI.cs index b20a0eabda..919242cb2b 100644 --- a/Rdmp.UI/MainFormUITabs/SubComponents/TableInfoUI.cs +++ b/Rdmp.UI/MainFormUITabs/SubComponents/TableInfoUI.cs @@ -5,7 +5,6 @@ // You should have received a copy of the GNU General Public License along with RDMP. If not, see . using System; -using System.ComponentModel; using System.Windows.Forms; using Rdmp.Core; using Rdmp.Core.Curation; @@ -17,7 +16,6 @@ using Rdmp.UI.ItemActivation; using Rdmp.UI.SimpleControls; using Rdmp.UI.SimpleDialogs; -using Rdmp.UI.TestsAndSetup.ServicePropogation; namespace Rdmp.UI.MainFormUITabs.SubComponents; @@ -162,9 +160,4 @@ private void btnSynchronize_Click(object sender, EventArgs e) ExceptionViewer.Show(exception); } } -} - -[TypeDescriptionProvider(typeof(AbstractControlDescriptionProvider))] -public abstract class TableInfoUI_Design : RDMPSingleDatabaseObjectControl -{ } \ No newline at end of file diff --git a/Rdmp.UI/MainFormUITabs/SubComponents/TableInfoUI_Design.cs b/Rdmp.UI/MainFormUITabs/SubComponents/TableInfoUI_Design.cs new file mode 100644 index 0000000000..f4c713a032 --- /dev/null +++ b/Rdmp.UI/MainFormUITabs/SubComponents/TableInfoUI_Design.cs @@ -0,0 +1,9 @@ +using System.ComponentModel; +using System.Windows.Forms; +using Rdmp.Core.Curation.Data; +using Rdmp.UI.TestsAndSetup.ServicePropogation; + +namespace Rdmp.UI.MainFormUITabs.SubComponents; + +[TypeDescriptionProvider(typeof(AbstractControlDescriptionProvider))] +public abstract class TableInfoUI_Design : RDMPSingleDatabaseObjectControl; \ No newline at end of file diff --git a/Rdmp.UI/Overview/DataLoadsGraph.cs b/Rdmp.UI/Overview/DataLoadsGraph.cs index b901c24641..790fd66ec8 100644 --- a/Rdmp.UI/Overview/DataLoadsGraph.cs +++ b/Rdmp.UI/Overview/DataLoadsGraph.cs @@ -207,8 +207,8 @@ public void RefreshChartAsync() dt.Columns.Add("Category"); dt.Columns.Add("NumberOfDataLoadsAtStatus"); - dt.Rows.Add(new object[] { "Manual Successful", countManualLoadsuccessful }); - dt.Rows.Add(new object[] { "Manual Fail", countManualLoadFailure }); + dt.Rows.Add("Manual Successful", countManualLoadsuccessful); + dt.Rows.Add("Manual Fail", countManualLoadFailure); Invoke(new MethodInvoker(() => diff --git a/Rdmp.UI/Overview/DataLoadsGraphObjectCollection.cs b/Rdmp.UI/Overview/DataLoadsGraphObjectCollection.cs index 51407a3d8f..9531471f04 100644 --- a/Rdmp.UI/Overview/DataLoadsGraphObjectCollection.cs +++ b/Rdmp.UI/Overview/DataLoadsGraphObjectCollection.cs @@ -11,6 +11,4 @@ namespace Rdmp.UI.Overview; /// /// Input/persistence object for (no objects get persisted). /// -public class DataLoadsGraphObjectCollection : PersistableObjectCollection -{ -} \ No newline at end of file +public sealed class DataLoadsGraphObjectCollection : PersistableObjectCollection; \ No newline at end of file diff --git a/Rdmp.UI/Overview/ViewCatalogueOverviewUI.cs b/Rdmp.UI/Overview/ViewCatalogueOverviewUI.cs index 5ec04c1c47..c3d875d35c 100644 --- a/Rdmp.UI/Overview/ViewCatalogueOverviewUI.cs +++ b/Rdmp.UI/Overview/ViewCatalogueOverviewUI.cs @@ -7,27 +7,14 @@ using System; using System.Collections.Generic; using System.ComponentModel; -using System.Data; -using System.Drawing; using System.Linq; using System.Windows.Forms; -using BrightIdeasSoftware; -using Rdmp.Core; -using Rdmp.Core.CommandExecution; using Rdmp.Core.Curation.Data; using Rdmp.Core.Curation.Data.Overview; -using Rdmp.Core.DataViewing; -using Rdmp.Core.Icons.IconProvision; -using Rdmp.Core.MapsDirectlyToDatabaseTable; using Rdmp.Core.ReusableLibraryCode.DataAccess; -using Rdmp.Core.ReusableLibraryCode.Icons.IconProvision; -using Rdmp.UI.CommandExecution.AtomicCommands; using Rdmp.UI.ItemActivation; using Rdmp.UI.MainFormUITabs; -using Rdmp.UI.ScintillaHelper; using Rdmp.UI.TestsAndSetup.ServicePropogation; -using ScintillaNET; -using SixLabors.ImageSharp.PixelFormats; namespace Rdmp.UI.Overview; @@ -200,6 +187,4 @@ private void label4_Click(object sender, EventArgs e) } } [TypeDescriptionProvider(typeof(AbstractControlDescriptionProvider))] -public abstract class ViewCatalogueOverviewUI_Design : RDMPSingleDatabaseObjectControl -{ -} \ No newline at end of file +public abstract class ViewCatalogueOverviewUI_Design : RDMPSingleDatabaseObjectControl; \ No newline at end of file diff --git a/Rdmp.UI/PieCharts/CatalogueToDatasetLinkageObjectCollection.cs b/Rdmp.UI/PieCharts/CatalogueToDatasetLinkageObjectCollection.cs deleted file mode 100644 index 9911e1c867..0000000000 --- a/Rdmp.UI/PieCharts/CatalogueToDatasetLinkageObjectCollection.cs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) The University of Dundee 2018-2023 -// This file is part of the Research Data Management Platform (RDMP). -// 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. -// 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. -// You should have received a copy of the GNU General Public License along with RDMP. If not, see .using Rdmp.Core.Curation.Data.Dashboarding; -using Rdmp.Core.Curation.Data.Dashboarding; - -namespace Rdmp.UI.PieCharts; - -/// -/// Input object for . -/// -public class CatalogueToDatasetLinkageObjectCollection : PersistableObjectCollection -{ -} diff --git a/Rdmp.UI/PieCharts/CatalogueToDatasetLinkagePieChartUI.cs b/Rdmp.UI/PieCharts/CatalogueToDatasetLinkagePieChartUI.cs index e08d7786ae..ff4a1ddaa5 100644 --- a/Rdmp.UI/PieCharts/CatalogueToDatasetLinkagePieChartUI.cs +++ b/Rdmp.UI/PieCharts/CatalogueToDatasetLinkagePieChartUI.cs @@ -142,8 +142,8 @@ private void PopulateAsEmptyDescriptionsChart() dt.Columns.Add("Count"); dt.Columns.Add("State"); - dt.Rows.Add(new object[] { countNotPopulated, $"Missing ({countNotPopulated})" }); - dt.Rows.Add(new object[] { countPopulated, $"Populated ({countPopulated})" }); + dt.Rows.Add(countNotPopulated, $"Missing ({countNotPopulated})"); + dt.Rows.Add(countPopulated, $"Populated ({countPopulated})"); chart1.Series[0].XValueMember = dt.Columns[1].ColumnName; chart1.Series[0].YValueMembers = dt.Columns[0].ColumnName; diff --git a/Rdmp.UI/PieCharts/GoodBadCataloguePieChart.cs b/Rdmp.UI/PieCharts/GoodBadCataloguePieChart.cs index 0b126d190f..ba36eb2e55 100644 --- a/Rdmp.UI/PieCharts/GoodBadCataloguePieChart.cs +++ b/Rdmp.UI/PieCharts/GoodBadCataloguePieChart.cs @@ -143,8 +143,8 @@ private void PopulateAsEmptyDescriptionsChart() dt.Columns.Add("Count"); dt.Columns.Add("State"); - dt.Rows.Add(new object[] { countNotPopulated, $"Missing ({countNotPopulated})" }); - dt.Rows.Add(new object[] { countPopulated, $"Populated ({countPopulated})" }); + dt.Rows.Add(countNotPopulated, $"Missing ({countNotPopulated})"); + dt.Rows.Add(countPopulated, $"Populated ({countPopulated})"); chart1.Series[0].XValueMember = dt.Columns[1].ColumnName; chart1.Series[0].YValueMembers = dt.Columns[0].ColumnName; diff --git a/Rdmp.UI/PipelineUIs/Pipelines/ConfigurePipelineUI.cs b/Rdmp.UI/PipelineUIs/Pipelines/ConfigurePipelineUI.cs index b2f10312d6..8e69a8f029 100644 --- a/Rdmp.UI/PipelineUIs/Pipelines/ConfigurePipelineUI.cs +++ b/Rdmp.UI/PipelineUIs/Pipelines/ConfigurePipelineUI.cs @@ -24,7 +24,7 @@ public partial class ConfigurePipelineUI : Form private readonly IPipeline _pipeline; private readonly IPipelineUseCase _useCase; - private PipelineWorkAreaUI _workArea; + private readonly PipelineWorkAreaUI _workArea; public ConfigurePipelineUI(IActivateItems activator, IPipeline pipeline, IPipelineUseCase useCase, ICatalogueRepository repository) @@ -46,13 +46,10 @@ public ConfigurePipelineUI(IActivateItems activator, IPipeline pipeline, IPipeli protected override bool ProcessCmdKey(ref Message msg, Keys keyData) { - if (keyData == (Keys.Control | Keys.W)) - { - Close(); - return true; - } + if (keyData != (Keys.Control | Keys.W)) return base.ProcessCmdKey(ref msg, keyData); - return base.ProcessCmdKey(ref msg, keyData); + Close(); + return true; } @@ -67,10 +64,9 @@ private void tbName_TextChanged(object sender, EventArgs e) if (string.IsNullOrWhiteSpace(tbName.Text)) tbName.Text = "NoName"; - if (tbName.Text.StartsWith("TO DO:") || tbName.Text.Equals("NoName")) - tbName.ForeColor = Color.Red; - else - tbName.ForeColor = Color.Black; + tbName.ForeColor = tbName.Text.StartsWith("TO DO:", StringComparison.Ordinal) || tbName.Text.Equals("NoName") + ? Color.Red + : Color.Black; try { diff --git a/Rdmp.UI/PipelineUIs/Pipelines/PipelineDiagramUI.Designer.cs b/Rdmp.UI/PipelineUIs/Pipelines/PipelineDiagramUI.Designer.cs index c009ccf4de..6e86b16428 100644 --- a/Rdmp.UI/PipelineUIs/Pipelines/PipelineDiagramUI.Designer.cs +++ b/Rdmp.UI/PipelineUIs/Pipelines/PipelineDiagramUI.Designer.cs @@ -1,6 +1,6 @@ namespace Rdmp.UI.PipelineUIs.Pipelines { - partial class PipelineDiagramUI + sealed partial class PipelineDiagramUI { /// /// Required designer variable. diff --git a/Rdmp.UI/PipelineUIs/Pipelines/PipelineDiagramUI.cs b/Rdmp.UI/PipelineUIs/Pipelines/PipelineDiagramUI.cs index c56a8c5f22..a08069b968 100644 --- a/Rdmp.UI/PipelineUIs/Pipelines/PipelineDiagramUI.cs +++ b/Rdmp.UI/PipelineUIs/Pipelines/PipelineDiagramUI.cs @@ -31,7 +31,7 @@ namespace Rdmp.UI.PipelineUIs.Pipelines; /// you are selecting an IPipeline you will see the diagram rendered readonly. If you are editing (See PipelineWorkAreaUI and ConfigurePipelineUI) then you will be able to select /// and drag and drop in new components to make an IPipeline configuration. On such a dialog you can also select a component to change the components arguments (See ArgumentCollection). /// -public partial class PipelineDiagramUI : UserControl +public sealed partial class PipelineDiagramUI : UserControl { private IPipeline _pipeline; @@ -41,7 +41,7 @@ public partial class PipelineDiagramUI : UserControl [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public bool AllowReOrdering { get; set; } - private RAGSmiley pipelineSmiley = new(); + private readonly RAGSmiley pipelineSmiley = new(); public IPipelineComponent SelectedComponent; public event PipelineComponentSelectedHandler SelectedComponentChanged; @@ -49,7 +49,7 @@ public partial class PipelineDiagramUI : UserControl private IPipelineUseCase _useCase; private DataFlowPipelineEngineFactory _pipelineFactory; - private ToolStripMenuItem _deleteSelectedMenuItem; + private readonly ToolStripMenuItem _deleteSelectedMenuItem; private readonly IActivateItems _activator; public PipelineDiagramUI(IActivateItems activator) @@ -77,30 +77,29 @@ public PipelineDiagramUI(IActivateItems activator) private void DeleteSelectedComponent(object sender, EventArgs e) { - if (SelectedComponent != null) - if (MessageBox.Show($"Do you want to delete {SelectedComponent.Class}?", "Confirm Delete", - MessageBoxButtons.YesNo) == DialogResult.Yes) - { - //if they are deleting the destination - if (SelectedComponent.ID == _pipeline.DestinationPipelineComponent_ID) - { - _pipeline.DestinationPipelineComponent_ID = null; - _pipeline.SaveToDatabase(); - } + if (SelectedComponent == null || MessageBox.Show($"Do you want to delete {SelectedComponent.Class}?", + "Confirm Delete", + MessageBoxButtons.YesNo) != DialogResult.Yes) return; - //if they are deleting the source - if (SelectedComponent.ID == _pipeline.SourcePipelineComponent_ID) - { - _pipeline.SourcePipelineComponent_ID = null; - _pipeline.SaveToDatabase(); - } + //if they are deleting the destination + if (SelectedComponent.ID == _pipeline.DestinationPipelineComponent_ID) + { + _pipeline.DestinationPipelineComponent_ID = null; + _pipeline.SaveToDatabase(); + } - SelectedComponent.DeleteInDatabase(); - RefreshUIFromDatabase(); + //if they are deleting the source + if (SelectedComponent.ID == _pipeline.SourcePipelineComponent_ID) + { + _pipeline.SourcePipelineComponent_ID = null; + _pipeline.SaveToDatabase(); + } - SelectedComponent = null; - _deleteSelectedMenuItem.Enabled = false; - } + SelectedComponent.DeleteInDatabase(); + RefreshUIFromDatabase(); + + SelectedComponent = null; + _deleteSelectedMenuItem.Enabled = false; } @@ -343,10 +342,11 @@ private DragDropEffects component_shouldAllowDrop(DragEventArgs arg, DataFlowCom var obj = GetAdvertisedObjectFromDragOperation(arg); //if they are dragging a new component - if (obj != null) - //of the correct role and the source/destination is empty - if (sender.Value == null && obj.GetRole() == sender.GetRole()) - return DragDropEffects.Move; + if (obj == null) return DragDropEffects.None; + + //of the correct role and the source/destination is empty + if (sender.Value == null && obj.GetRole() == sender.GetRole()) + return DragDropEffects.Move; return DragDropEffects.None; } diff --git a/Rdmp.UI/Progress/ProgressUI.cs b/Rdmp.UI/Progress/ProgressUI.cs index a7e7a9b4c3..329acf02db 100644 --- a/Rdmp.UI/Progress/ProgressUI.cs +++ b/Rdmp.UI/Progress/ProgressUI.cs @@ -9,6 +9,7 @@ using System.Data; using System.Drawing; using System.Linq; +using System.Threading; using System.Windows.Forms; using BrightIdeasSoftware; using Rdmp.Core.Icons.IconProvision; @@ -17,6 +18,7 @@ using Rdmp.UI.Collections; using Rdmp.UI.SimpleDialogs; using Rdmp.UI.Theme; +using Timer = System.Windows.Forms.Timer; namespace Rdmp.UI.Progress; @@ -151,9 +153,9 @@ public void Clear() } private readonly Dictionary> _jobsReceivedFromSender = new(); - private readonly object _oProgressQueueLock = new(); + private readonly Lock _oProgressQueueLock = new(); private readonly Dictionary _progressQueue = new(); - private readonly object _oNotifyQueLock = new(); + private readonly Lock _oNotifyQueLock = new(); private readonly List _notificationQueue = new(); public void Progress(object sender, ProgressEventArgs args) @@ -233,7 +235,7 @@ private void ProcessAndClearQueuedProgressMessages(object sender, EventArgs e) if (!handledByFlood) if (!progress.Rows.Contains(args.TaskDescription)) { - progress.Rows.Add(new object[] { args.TaskDescription, args.Progress.Value, label }); + progress.Rows.Add(args.TaskDescription, args.Progress.Value, label); } else { @@ -330,7 +332,7 @@ private void MergeAllJobsForSenderIntoSingleRowAndCumulateResult(object sender, progress.Rows.Find(floodJob)["Count"] = Convert.ToInt32(progress.Rows.Find(floodJob)["Count"]) + progressAmountToAdd; else - progress.Rows.Add(new object[] { floodJob, startAtProgressAmount + progressAmountToAdd, label }); + progress.Rows.Add(floodJob, startAtProgressAmount + progressAmountToAdd, label); } private void olvProgressEvents_ItemActivate(object sender, EventArgs e) diff --git a/Rdmp.UI/ProjectUI/Datasets/ConfigureDatasetUI.cs b/Rdmp.UI/ProjectUI/Datasets/ConfigureDatasetUI.cs index cd344ca07e..ac1f2bef9a 100644 --- a/Rdmp.UI/ProjectUI/Datasets/ConfigureDatasetUI.cs +++ b/Rdmp.UI/ProjectUI/Datasets/ConfigureDatasetUI.cs @@ -256,10 +256,12 @@ private void SetupUserInterface() foreach (var ec in allExtractableColumns) { if (ec.CatalogueExtractionInformation_ID == null) continue; + var eiDict = Activator.CoreChildProvider.AllExtractionInformationsDictionary; var ciDict = Activator.CoreChildProvider.AllCatalogueItemsDictionary; if (!eiDict.TryGetValue(ec.CatalogueExtractionInformation_ID.Value, out var ei)) continue; + ec.InjectKnown(ei); ec.InjectKnown(ei.ColumnInfo); @@ -754,11 +756,11 @@ private void tbSearch_TextChanged(object sender, EventArgs e) ObjectListView tree; var senderTb = (TextBox)sender; - if (sender == tbSearchAvailable) + if (ReferenceEquals(sender, tbSearchAvailable)) tree = olvAvailable; - else if (sender == tbSearchSelected) + else if (ReferenceEquals(sender, tbSearchSelected)) tree = olvSelected; - else if (sender == tbSearchTables) + else if (ReferenceEquals(sender, tbSearchTables)) tree = olvJoin; else throw new Exception($"Unexpected sender {sender}"); @@ -782,12 +784,11 @@ public void RefreshBus_RefreshObject(object sender, RefreshObjectEventArgs e) //if an ExtractionInformation is being refreshed if (e.Object is ExtractionInformation ei) //We should clear any old cached values for this ExtractionInformation amongst selected column - foreach (var c in olvSelected.Objects.OfType().ToArray()) - if (c.CatalogueExtractionInformation_ID == ei.ID) - { - c.InjectKnown(ei); - olvSelected.RefreshObject(c); - } + foreach (var c in olvSelected.Objects.OfType().Where(c => c.CatalogueExtractionInformation_ID == ei.ID).ToArray()) + { + c.InjectKnown(ei); + olvSelected.RefreshObject(c); + } UpdateJoins(); } @@ -800,6 +801,4 @@ private void CbShowProjectSpecific_CheckedChanged(object sender, EventArgs e) } [TypeDescriptionProvider(typeof(AbstractControlDescriptionProvider))] -public abstract class ConfigureDatasetUI_Design : RDMPSingleDatabaseObjectControl -{ -} \ No newline at end of file +public abstract class ConfigureDatasetUI_Design : RDMPSingleDatabaseObjectControl; \ No newline at end of file diff --git a/Rdmp.UI/ProjectUI/ExecuteExtractionUI.cs b/Rdmp.UI/ProjectUI/ExecuteExtractionUI.cs index 7517ad5d0f..c487502d92 100644 --- a/Rdmp.UI/ProjectUI/ExecuteExtractionUI.cs +++ b/Rdmp.UI/ProjectUI/ExecuteExtractionUI.cs @@ -405,6 +405,4 @@ public override string GetTabToolTip() => } [TypeDescriptionProvider(typeof(AbstractControlDescriptionProvider))] -public abstract class ExecuteExtractionUI_Design : RDMPSingleDatabaseObjectControl -{ -} +public abstract class ExecuteExtractionUI_Design : RDMPSingleDatabaseObjectControl; diff --git a/Rdmp.UI/ProjectUI/ExtractionConfigurationUI.cs b/Rdmp.UI/ProjectUI/ExtractionConfigurationUI.cs index b8b503e504..74c997577f 100644 --- a/Rdmp.UI/ProjectUI/ExtractionConfigurationUI.cs +++ b/Rdmp.UI/ProjectUI/ExtractionConfigurationUI.cs @@ -227,6 +227,4 @@ public override string GetTabToolTip() => } [TypeDescriptionProvider(typeof(AbstractControlDescriptionProvider))] -public abstract class ExtractionConfigurationUI_Design : RDMPSingleDatabaseObjectControl -{ -} \ No newline at end of file +public abstract class ExtractionConfigurationUI_Design : RDMPSingleDatabaseObjectControl; \ No newline at end of file diff --git a/Rdmp.UI/ProjectUI/ProjectUI.cs b/Rdmp.UI/ProjectUI/ProjectUI.cs index 2b0036301f..3358d15493 100644 --- a/Rdmp.UI/ProjectUI/ProjectUI.cs +++ b/Rdmp.UI/ProjectUI/ProjectUI.cs @@ -367,6 +367,4 @@ private void btnBrowse_Click(object sender, EventArgs e) } [TypeDescriptionProvider(typeof(AbstractControlDescriptionProvider))] -public abstract class ProjectUI_Design : RDMPSingleDatabaseObjectControl -{ -} \ No newline at end of file +public abstract class ProjectUI_Design : RDMPSingleDatabaseObjectControl; \ No newline at end of file diff --git a/Rdmp.UI/Raceway/RacewayRenderAreaUI.cs b/Rdmp.UI/Raceway/RacewayRenderAreaUI.cs index 3f7430075f..689b40965a 100644 --- a/Rdmp.UI/Raceway/RacewayRenderAreaUI.cs +++ b/Rdmp.UI/Raceway/RacewayRenderAreaUI.cs @@ -9,6 +9,7 @@ using System.Drawing; using System.Drawing.Drawing2D; using System.Linq; +using System.Threading; using System.Windows.Forms; using Rdmp.Core.CommandExecution; using Rdmp.Core.Curation.Data; @@ -17,6 +18,7 @@ using Rdmp.UI.DashboardTabs.Construction; using Rdmp.UI.ItemActivation; using Rdmp.UI.SimpleControls; +using Timer = System.Windows.Forms.Timer; namespace Rdmp.UI.Raceway; @@ -61,7 +63,7 @@ public void NotifyEditModeChange(bool isEditmodeOn) Invalidate(); } - private object oPeriodicityDictionaryLock = new(); + private readonly Lock _oPeriodicityDictionaryLock = new(); private bool _ignoreRowCounts; private bool _isEditModeOn; @@ -89,7 +91,7 @@ public void AddTracks(IActivateItems activator, _activator = activator; _buckets = buckets; _ignoreRowCounts = ignoreRows; - lock (oPeriodicityDictionaryLock) + lock (_oPeriodicityDictionaryLock) { _periodicityDictionary = periodicityDictionary; } @@ -129,7 +131,7 @@ protected override void OnMouseClick(MouseEventArgs e) foreach (var kvp in rectDeleteButtons.Where(r => r.Key.Contains(e.Location)).ToList()) if (RequestDeletion != null) - lock (oPeriodicityDictionaryLock) + lock (_oPeriodicityDictionaryLock) { RequestDeletion(kvp.Value); //stop rendering this Catalogue @@ -275,7 +277,7 @@ protected override void OnPaint(PaintEventArgs e) //draw the tracks - lock (oPeriodicityDictionaryLock) + lock (_oPeriodicityDictionaryLock) { var eachRaceLaneHasThisMuchYSpace = Math.Max(MinimumRowHeight, Math.Min(MaximumRaceLaneRenderSpace, (float)Height / (_periodicityDictionary.Count + 1))); @@ -362,13 +364,11 @@ protected override void OnPaint(PaintEventArgs e) var heightOfBarToDraw = eachRaceLaneHasThisMuchYSpace * thicknessRatio; var emptyYSpace = eachRaceLaneHasThisMuchYSpace - heightOfBarToDraw; - var widthOfBarToDraw = eachBucketHasThisManyPixelsOfX; - - var rectToFill = new RectangleF(i * widthOfBarToDraw, startDrawingLaneAtY + emptyYSpace, - widthOfBarToDraw, heightOfBarToDraw); + var rectToFill = new RectangleF(i * eachBucketHasThisManyPixelsOfX, startDrawingLaneAtY + emptyYSpace, + eachBucketHasThisManyPixelsOfX, heightOfBarToDraw); e.Graphics.FillRectangle(brush, rectToFill); - var fullRectHitbox = new RectangleF(rectToFill.X, startDrawingLaneAtY, widthOfBarToDraw, + var fullRectHitbox = new RectangleF(rectToFill.X, startDrawingLaneAtY, eachBucketHasThisManyPixelsOfX, eachRaceLaneHasThisMuchYSpace); if (fullRectHitbox.Contains(mousePosition)) { @@ -384,7 +384,7 @@ protected override void OnPaint(PaintEventArgs e) if (hoverLabel != null) { - float labelPadding = 3; + const float labelPadding = 3; var labelSize = e.Graphics.MeasureString(hoverLabel, Font); var valueSize = e.Graphics.MeasureString(hoverValue, Font); diff --git a/Rdmp.UI/Refreshing/ILifetimeSubscriber.cs b/Rdmp.UI/Refreshing/ILifetimeSubscriber.cs index b3492b2a9e..fc51277ec5 100644 --- a/Rdmp.UI/Refreshing/ILifetimeSubscriber.cs +++ b/Rdmp.UI/Refreshing/ILifetimeSubscriber.cs @@ -16,6 +16,4 @@ namespace Rdmp.UI.Refreshing; /// /// See /// -public interface ILifetimeSubscriber : IContainerControl, IRefreshBusSubscriber -{ -} \ No newline at end of file +public interface ILifetimeSubscriber : IContainerControl, IRefreshBusSubscriber; \ No newline at end of file diff --git a/Rdmp.UI/Refreshing/RefreshBus.cs b/Rdmp.UI/Refreshing/RefreshBus.cs index 590342de85..f744b52542 100644 --- a/Rdmp.UI/Refreshing/RefreshBus.cs +++ b/Rdmp.UI/Refreshing/RefreshBus.cs @@ -7,6 +7,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Threading; using System.Windows.Forms; using Rdmp.Core.Curation.Data; using Rdmp.Core.Providers; @@ -34,7 +35,7 @@ public class RefreshBus public ICoreChildProvider ChildProvider { get; set; } - private object oPublishLock = new(); + private readonly Lock _oPublishLock = new(); public void Publish(object sender, RefreshObjectEventArgs e) { @@ -42,7 +43,7 @@ public void Publish(object sender, RefreshObjectEventArgs e) throw new SubscriptionException( $"Refresh Publish Cascade error. Subscriber {sender} just attempted a publish during an existing publish execution, cyclic inception publishing is not allowed, you cannot respond to a refresh callback by issuing more refresh publishes"); - lock (oPublishLock) + lock (_oPublishLock) { BeforePublish?.Invoke(sender, e); diff --git a/Rdmp.UI/SimpleControls/HeatmapUI.cs b/Rdmp.UI/SimpleControls/HeatmapUI.cs index 4924809800..9bbf8be15b 100644 --- a/Rdmp.UI/SimpleControls/HeatmapUI.cs +++ b/Rdmp.UI/SimpleControls/HeatmapUI.cs @@ -10,6 +10,7 @@ using System.Drawing.Imaging; using System.Linq; using System.Text.RegularExpressions; +using System.Threading; using System.Windows.Forms; using Rdmp.Core.ReusableLibraryCode.Settings; using Rdmp.UI.SimpleDialogs; @@ -70,7 +71,7 @@ public partial class HeatmapUI : UserControl private double _currentLabelsWidth; - private object oDataTableLock = new(); + private readonly Lock _oDataTableLock = new(); public HeatmapUI() { @@ -109,7 +110,7 @@ public void SetDataTable(DataTable dataTable) } } - lock (oDataTableLock) + lock (_oDataTableLock) { _dataTable = dataTable; @@ -184,7 +185,7 @@ private void hoverToolTipTimer_Tick(object sender, EventArgs e) _lastHoverTickCount = Environment.TickCount; object value = null; - lock (oDataTableLock) + lock (_oDataTableLock) { value = GetValueFromClientPosition(pos); } @@ -241,7 +242,7 @@ protected override void OnPaint(PaintEventArgs e) return; try { - lock (oDataTableLock) + lock (_oDataTableLock) { //draw background e.Graphics.FillRectangle(Brushes.White, new Rectangle(0, 0, Width, Height)); @@ -400,7 +401,7 @@ public static void CalculateLayout() public void Clear() { - lock (oDataTableLock) + lock (_oDataTableLock) { _dataTable = null; } diff --git a/Rdmp.UI/SimpleDialogs/BulkProcessCatalogueItemsUI.cs b/Rdmp.UI/SimpleDialogs/BulkProcessCatalogueItemsUI.cs index b2089655c3..294733c9c9 100644 --- a/Rdmp.UI/SimpleDialogs/BulkProcessCatalogueItemsUI.cs +++ b/Rdmp.UI/SimpleDialogs/BulkProcessCatalogueItemsUI.cs @@ -298,6 +298,4 @@ private void cbExactMatch_CheckedChanged(object sender, EventArgs e) } [TypeDescriptionProvider(typeof(AbstractControlDescriptionProvider))] -public class BulkProcessCatalogueItems_Design : RDMPSingleDatabaseObjectControl -{ -} \ No newline at end of file +public class BulkProcessCatalogueItems_Design : RDMPSingleDatabaseObjectControl; \ No newline at end of file diff --git a/Rdmp.UI/SimpleDialogs/CommitsUI.cs b/Rdmp.UI/SimpleDialogs/CommitsUI.cs index 68e49a455f..49db810a91 100644 --- a/Rdmp.UI/SimpleDialogs/CommitsUI.cs +++ b/Rdmp.UI/SimpleDialogs/CommitsUI.cs @@ -136,6 +136,4 @@ private void btnExpandAll_Click(object sender, EventArgs e) } [TypeDescriptionProvider(typeof(AbstractControlDescriptionProvider))] -public abstract class CommitsUI_Design : RDMPUserControl -{ -} \ No newline at end of file +public abstract class CommitsUI_Design : RDMPUserControl; \ No newline at end of file diff --git a/Rdmp.UI/SimpleDialogs/Governance/GovernanceDocumentUI.cs b/Rdmp.UI/SimpleDialogs/Governance/GovernanceDocumentUI.cs index 6350741923..373e2fd3ac 100644 --- a/Rdmp.UI/SimpleDialogs/Governance/GovernanceDocumentUI.cs +++ b/Rdmp.UI/SimpleDialogs/Governance/GovernanceDocumentUI.cs @@ -67,6 +67,4 @@ private void btnOpenContainingFolder_Click(object sender, EventArgs e) } [TypeDescriptionProvider(typeof(AbstractControlDescriptionProvider))] -public abstract class GovernanceDocumentUI_Design : RDMPSingleDatabaseObjectControl -{ -} \ No newline at end of file +public abstract class GovernanceDocumentUI_Design : RDMPSingleDatabaseObjectControl; \ No newline at end of file diff --git a/Rdmp.UI/SimpleDialogs/Governance/GovernancePeriodUI.cs b/Rdmp.UI/SimpleDialogs/Governance/GovernancePeriodUI.cs index c843c2e50a..1062237e7c 100644 --- a/Rdmp.UI/SimpleDialogs/Governance/GovernancePeriodUI.cs +++ b/Rdmp.UI/SimpleDialogs/Governance/GovernancePeriodUI.cs @@ -222,6 +222,4 @@ private void olvCatalogues_ItemActivate(object sender, EventArgs e) } [TypeDescriptionProvider(typeof(AbstractControlDescriptionProvider))] -public abstract class GovernancePeriodUI_Design : RDMPSingleDatabaseObjectControl -{ -} \ No newline at end of file +public abstract class GovernancePeriodUI_Design : RDMPSingleDatabaseObjectControl; \ No newline at end of file diff --git a/Rdmp.UI/SimpleDialogs/NewfindUI.cs b/Rdmp.UI/SimpleDialogs/NewfindUI.cs index 4b285105ec..fc7236ce37 100644 --- a/Rdmp.UI/SimpleDialogs/NewfindUI.cs +++ b/Rdmp.UI/SimpleDialogs/NewfindUI.cs @@ -14,7 +14,6 @@ using Rdmp.UI.Theme; using System; using System.Collections.Generic; -using System.Data; using System.Drawing; using System.Linq; using System.Text.RegularExpressions; @@ -230,7 +229,7 @@ private void tbFilter_TextChanged(object sender, EventArgs e) if (cbRegex.Checked) { - folv.ModelFilter = new CompositeAllFilter(new List() { TextMatchFilter.Regex(folv, new[] { tbFind.Text }), catalogueFilter, aggregateFilter }); + folv.ModelFilter = new CompositeAllFilter(new List() { TextMatchFilter.Regex(folv, tbFind.Text), catalogueFilter, aggregateFilter }); } else { diff --git a/Rdmp.UI/SimpleDialogs/RedactCatalogueUI.cs b/Rdmp.UI/SimpleDialogs/RedactCatalogueUI.cs index 912b331f3a..463a387432 100644 --- a/Rdmp.UI/SimpleDialogs/RedactCatalogueUI.cs +++ b/Rdmp.UI/SimpleDialogs/RedactCatalogueUI.cs @@ -7,7 +7,6 @@ using System; using System.Collections.Generic; using System.ComponentModel; -using System.Data; using System.Diagnostics; using System.Linq; using System.Windows.Forms; @@ -137,6 +136,4 @@ private void btnRestoreAll_Click(object sender, EventArgs e) } [TypeDescriptionProvider(typeof(AbstractControlDescriptionProvider))] -public abstract class RedactCatalogueUI_Design : RDMPSingleDatabaseObjectControl -{ -} \ No newline at end of file +public abstract class RedactCatalogueUI_Design : RDMPSingleDatabaseObjectControl; \ No newline at end of file diff --git a/Rdmp.UI/SimpleDialogs/Remoting/RemoteRDMPUI.cs b/Rdmp.UI/SimpleDialogs/Remoting/RemoteRDMPUI.cs index d5d81456d6..1fa8f3c70a 100644 --- a/Rdmp.UI/SimpleDialogs/Remoting/RemoteRDMPUI.cs +++ b/Rdmp.UI/SimpleDialogs/Remoting/RemoteRDMPUI.cs @@ -39,6 +39,4 @@ protected override void SetBindings(BinderWithErrorProviderFactory rules, Remote } [TypeDescriptionProvider(typeof(AbstractControlDescriptionProvider))] -public abstract class RemoteRDMPUI_Design : RDMPSingleDatabaseObjectControl -{ -} \ No newline at end of file +public abstract class RemoteRDMPUI_Design : RDMPSingleDatabaseObjectControl; \ No newline at end of file diff --git a/Rdmp.UI/SimpleDialogs/SelectDialog.cs b/Rdmp.UI/SimpleDialogs/SelectDialog.cs index 6d1fb0c3b2..0ab4f48d3e 100644 --- a/Rdmp.UI/SimpleDialogs/SelectDialog.cs +++ b/Rdmp.UI/SimpleDialogs/SelectDialog.cs @@ -40,7 +40,7 @@ public partial class SelectDialog : Form, IVirtualListDataSource where T : cl private readonly AttributePropertyFinder _usefulPropertyFinder; private const int MaxMatches = 500; - private object oMatches = new(); + private readonly Lock _oMatches = new(); private Task _lastFetchTask; private CancellationTokenSource _lastCancellationToken; @@ -333,7 +333,7 @@ private Bitmap GetHierarchyImage(object rowObject) if (rowObject is not IMapsDirectlyToDatabaseTable m) return null; - lock (oMatches) + lock (_oMatches) { if (_searchables?.TryGetValue(m, out var searchable) != true) return null; @@ -349,7 +349,7 @@ private object GetHierarchy(object rowObject) if (rowObject is not IMapsDirectlyToDatabaseTable m) return null; - lock (oMatches) + lock (_oMatches) { if (_searchables?.TryGetValue(m, out var descendancy) == true) return descendancy != null @@ -565,7 +565,7 @@ private void FetchMatches(string text, CancellationToken cancellationToken) return; } - lock (oMatches) + lock (_oMatches) { _tempMatches = SearchablesMatchScorer.ShortList(scores, MaxMatches, _activator); } @@ -665,7 +665,7 @@ private void EnumCheckedChanged(object sender, EventArgs e) { var button = (ToolStripButton)sender; - var togglingType = (Type)button.Tag; ; + var togglingType = (Type)button.Tag; if (button.Checked) if (showOnlyEnums.TryGetValue(togglingType, out var value)) @@ -726,7 +726,7 @@ private void tbFilter_TextChanged(object sender, EventArgs e) return; if (s.IsCompleted) - lock (oMatches) + lock (_oMatches) { // updates the list _matches = _tempMatches; @@ -745,7 +745,7 @@ public void AddObjects(ICollection modelObjects) public object GetNthObject(int n) { - lock (oMatches) + lock (_oMatches) { return n >= _objectsToDisplay.Count ? null : _objectsToDisplay[n]; } @@ -754,7 +754,7 @@ public object GetNthObject(int n) public int GetObjectCount() { - lock (oMatches) + lock (_oMatches) { // regenerate the _toDisplayList because the state has changed if (stateChanged) diff --git a/Rdmp.UI/SimpleDialogs/SupportingDocumentUI.cs b/Rdmp.UI/SimpleDialogs/SupportingDocumentUI.cs index ec643ee867..59510f79ec 100644 --- a/Rdmp.UI/SimpleDialogs/SupportingDocumentUI.cs +++ b/Rdmp.UI/SimpleDialogs/SupportingDocumentUI.cs @@ -132,6 +132,4 @@ private void btnBrowse_Click(object sender, EventArgs e) } [TypeDescriptionProvider(typeof(AbstractControlDescriptionProvider))] -public abstract class SupportingDocumentUI_Design : RDMPSingleDatabaseObjectControl -{ -} \ No newline at end of file +public abstract class SupportingDocumentUI_Design : RDMPSingleDatabaseObjectControl; \ No newline at end of file diff --git a/Rdmp.UI/SimpleDialogs/SupportingSQLTableUI.cs b/Rdmp.UI/SimpleDialogs/SupportingSQLTableUI.cs index 4f34909e48..68272373a1 100644 --- a/Rdmp.UI/SimpleDialogs/SupportingSQLTableUI.cs +++ b/Rdmp.UI/SimpleDialogs/SupportingSQLTableUI.cs @@ -188,6 +188,4 @@ private void btnAdd_Click(object sender, EventArgs e) } [TypeDescriptionProvider(typeof(AbstractControlDescriptionProvider))] -public abstract class SupportingSQLTableUI_Design : RDMPSingleDatabaseObjectControl -{ -} \ No newline at end of file +public abstract class SupportingSQLTableUI_Design : RDMPSingleDatabaseObjectControl; \ No newline at end of file diff --git a/Rdmp.UI/SimpleDialogs/ViewParentTreeDialog.cs b/Rdmp.UI/SimpleDialogs/ViewParentTreeDialog.cs index e40b395f12..d631787466 100644 --- a/Rdmp.UI/SimpleDialogs/ViewParentTreeDialog.cs +++ b/Rdmp.UI/SimpleDialogs/ViewParentTreeDialog.cs @@ -1,18 +1,9 @@ using BrightIdeasSoftware; using Rdmp.Core.CommandExecution; -using Rdmp.Core.CommandExecution.AtomicCommands; using Rdmp.Core.Curation.Data; -using Rdmp.Core.Icons.IconProvision; using Rdmp.Core.MapsDirectlyToDatabaseTable; -using Rdmp.Core.Providers; -using System; using System.Collections.Generic; -using System.ComponentModel; -using System.Data; using System.Drawing; -using System.Linq; -using System.Text; -using System.Threading.Tasks; using System.Windows.Forms; namespace Rdmp.UI.SimpleDialogs @@ -27,11 +18,8 @@ public ViewParentTreeDialog(IBasicActivateItems activator, List tree) _tree = tree; _activator = activator; InitializeComponent(); - this.tlv.CanExpandGetter = delegate (object x) - { - return tree.IndexOf(x) < tree.Count() - 1; - }; - this.tlv.ChildrenGetter = delegate (object x) + this.tlv.CanExpandGetter = x => tree.IndexOf(x) < tree.Count - 1; + this.tlv.ChildrenGetter = x => { var item = tree[tree.IndexOf(x) + 1]; return new List() { item }; diff --git a/Rdmp.UI/SimpleDialogs/ViewSourceCodeDialog.cs b/Rdmp.UI/SimpleDialogs/ViewSourceCodeDialog.cs index 16d236581f..4a0fdd04d3 100644 --- a/Rdmp.UI/SimpleDialogs/ViewSourceCodeDialog.cs +++ b/Rdmp.UI/SimpleDialogs/ViewSourceCodeDialog.cs @@ -11,6 +11,7 @@ using System.IO; using System.IO.Compression; using System.Linq; +using System.Threading; using System.Windows.Forms; using BrightIdeasSoftware; using Rdmp.UI.ScintillaHelper; @@ -27,13 +28,13 @@ public partial class ViewSourceCodeDialog : Form { private readonly Scintilla _queryEditor; - private static readonly HashSet SupplementalSourceZipFiles = new(); - private static readonly object oSupplementalSourceZipFilesLock = new(); + private static readonly HashSet SupplementalSourceZipFiles = []; + private static readonly Lock OSupplementalSourceZipFilesLock = new(); private const string MainSourceCodeRepo = "SourceCodeForSelfAwareness.zip"; public static void AddSupplementalSourceZipFile(FileInfo f) { - lock (oSupplementalSourceZipFilesLock) + lock (OSupplementalSourceZipFilesLock) { SupplementalSourceZipFiles.Add(f); } @@ -66,7 +67,7 @@ public ViewSourceCodeDialog(string filename, int lineNumber, Color highlightColo private void LoadSourceCode(string toFind, int lineNumber, Color highlightColor) { - lock (oSupplementalSourceZipFilesLock) + lock (OSupplementalSourceZipFilesLock) { var readToEnd = GetSourceForFile(toFind); diff --git a/Rdmp.UI/SimpleDialogs/WideMessageBox.cs b/Rdmp.UI/SimpleDialogs/WideMessageBox.cs index 4e8813f211..ff17b8f80e 100644 --- a/Rdmp.UI/SimpleDialogs/WideMessageBox.cs +++ b/Rdmp.UI/SimpleDialogs/WideMessageBox.cs @@ -435,8 +435,8 @@ private static Size GetPreferredSizeOfTextControl(Control c) var graphics = c.CreateGraphics(); var measureString = graphics.MeasureString(c.Text, c.Font); - var minimumWidth = 400; - var minimumHeight = 150; + const int minimumWidth = 400; + const int minimumHeight = 150; var maxSize = Screen.GetBounds(c); maxSize.Height = Math.Min(maxSize.Height, 800); diff --git a/Rdmp.UI/SimpleDialogs/YesNoYesToAllDialog.cs b/Rdmp.UI/SimpleDialogs/YesNoYesToAllDialog.cs index d92c341f7b..4a9a3aa991 100644 --- a/Rdmp.UI/SimpleDialogs/YesNoYesToAllDialog.cs +++ b/Rdmp.UI/SimpleDialogs/YesNoYesToAllDialog.cs @@ -6,6 +6,7 @@ using System; using System.Drawing; +using System.Threading; using System.Windows.Forms; namespace Rdmp.UI.SimpleDialogs; @@ -16,16 +17,16 @@ namespace Rdmp.UI.SimpleDialogs; [TechnicalUI] public class YesNoYesToAllDialog : WideMessageBox { - private bool YesToAllClicked; - private bool NoToAllClicked; - private object lockShowDialog = new(); + private bool _yesToAllClicked; + private bool _noToAllClicked; + private readonly Lock _lockShowDialog = new(); private FlowLayoutPanel p = new(); - private Button btnYes = new() { Text = "Yes" }; - private Button btnYesToAll = new() { Text = "Yes To All" }; - private Button btnNo = new() { Text = "No" }; - private Button btnNoToAll = new() { Text = "No To All" }; + private readonly Button _btnYes = new() { Text = "Yes" }; + private readonly Button _btnYesToAll = new() { Text = "Yes To All" }; + private readonly Button _btnNo = new() { Text = "No" }; + private readonly Button _btnNoToAll = new() { Text = "No To All" }; /// /// The number of pixels to allow outside of the text width when auto sizing buttons @@ -39,10 +40,10 @@ public YesNoYesToAllDialog() : this(new WideMessageBoxArgs("YesNo", "Unknown", E private YesNoYesToAllDialog(WideMessageBoxArgs wideMessageBoxArgs) : base(wideMessageBoxArgs) { - AddButton(btnYes); - AddButton(btnYesToAll); - AddButton(btnNo); - AddButton(btnNoToAll); + AddButton(_btnYes); + AddButton(_btnYesToAll); + AddButton(_btnNo); + AddButton(_btnNoToAll); p.Dock = DockStyle.Fill; @@ -64,9 +65,9 @@ private void AddButton(Button button) private new DialogResult ShowDialog() { - if (YesToAllClicked) + if (_yesToAllClicked) return DialogResult.Yes; - if (NoToAllClicked) + if (_noToAllClicked) return DialogResult.No; return InvokeRequired ? Invoke(ShowDialog) : base.ShowDialog(); @@ -81,7 +82,7 @@ public DialogResult ShowDialog(string message, string caption) Args.Message = message; Setup(Args); - lock (lockShowDialog) + lock (_lockShowDialog) { return ShowDialog(); } @@ -89,22 +90,22 @@ public DialogResult ShowDialog(string message, string caption) private void btn_Click(object sender, EventArgs e) { - if (sender == btnYes) + if (sender == _btnYes) { DialogResult = DialogResult.Yes; } - else if (sender == btnNo) + else if (sender == _btnNo) { DialogResult = DialogResult.No; } - else if (sender == btnYesToAll) + else if (sender == _btnYesToAll) { - YesToAllClicked = true; + _yesToAllClicked = true; DialogResult = DialogResult.Yes; } - else if (sender == btnNoToAll) + else if (sender == _btnNoToAll) { - NoToAllClicked = true; + _noToAllClicked = true; DialogResult = DialogResult.No; } diff --git a/Rdmp.UI/SubComponents/CohortIdentificationConfigurationUI.cs b/Rdmp.UI/SubComponents/CohortIdentificationConfigurationUI.cs index 558ab5a393..bd46cfca03 100644 --- a/Rdmp.UI/SubComponents/CohortIdentificationConfigurationUI.cs +++ b/Rdmp.UI/SubComponents/CohortIdentificationConfigurationUI.cs @@ -412,13 +412,10 @@ private static void ViewCrashMessage(ICompileable compilable) private void cbKnownVersions_SelectedIndexChanged(object sender, EventArgs e) { - } } [TypeDescriptionProvider( typeof(AbstractControlDescriptionProvider))] public abstract class - CohortIdentificationConfigurationUI_Design : RDMPSingleDatabaseObjectControl -{ -} \ No newline at end of file + CohortIdentificationConfigurationUI_Design : RDMPSingleDatabaseObjectControl; \ No newline at end of file diff --git a/Rdmp.UI/SubComponents/DatasetConfigurationUI.cs b/Rdmp.UI/SubComponents/DatasetConfigurationUI.cs index dc7315fb89..7f1c0fa302 100644 --- a/Rdmp.UI/SubComponents/DatasetConfigurationUI.cs +++ b/Rdmp.UI/SubComponents/DatasetConfigurationUI.cs @@ -9,6 +9,7 @@ using Rdmp.UI.ItemActivation; namespace Rdmp.UI.SubComponents; + public partial class DatasetConfigurationUI : DatsetConfigurationUI_Design, IRefreshBusSubscriber { private readonly DatasetConfigurationUICommon _common; @@ -43,7 +44,6 @@ public override void SetDatabaseObject(IActivateItems activator, Dataset databas var s = GetObjectSaverButton(); s.SetupFor(this, databaseObject, activator); GetObjectSaverButton()?.Enable(false); - } @@ -53,17 +53,14 @@ public void RefreshBus_RefreshObject(object sender, RefreshObjectEventArgs e) private void label1_Click(object sender, EventArgs e) { - } private void label4_Click(object sender, EventArgs e) { - } } + [TypeDescriptionProvider( typeof(AbstractControlDescriptionProvider))] public abstract class - DatsetConfigurationUI_Design : RDMPSingleDatabaseObjectControl -{ -} \ No newline at end of file + DatsetConfigurationUI_Design : RDMPSingleDatabaseObjectControl; \ No newline at end of file diff --git a/Rdmp.UI/SubComponents/RegexRedactionConfigurationUI.cs b/Rdmp.UI/SubComponents/RegexRedactionConfigurationUI.cs index 9b47649ed4..3f64fc1668 100644 --- a/Rdmp.UI/SubComponents/RegexRedactionConfigurationUI.cs +++ b/Rdmp.UI/SubComponents/RegexRedactionConfigurationUI.cs @@ -50,6 +50,4 @@ private void label5_Click(object sender, EventArgs e) [TypeDescriptionProvider( typeof(AbstractControlDescriptionProvider))] public abstract class - RegexRedactionConfigurationUI_Design : RDMPSingleDatabaseObjectControl -{ -} \ No newline at end of file + RegexRedactionConfigurationUI_Design : RDMPSingleDatabaseObjectControl; \ No newline at end of file diff --git a/Rdmp.UI/TechnicalUI.cs b/Rdmp.UI/TechnicalUI.cs index d6c56366b2..0710c4fbbd 100644 --- a/Rdmp.UI/TechnicalUI.cs +++ b/Rdmp.UI/TechnicalUI.cs @@ -12,6 +12,4 @@ namespace Rdmp.UI; /// Used to indicate when a property does not map to an underlying data table /// [AttributeUsage(AttributeTargets.Class, Inherited = false)] -public sealed class TechnicalUI : Attribute -{ -} \ No newline at end of file +public sealed class TechnicalUI : Attribute; \ No newline at end of file diff --git a/Rdmp.UI/Validation/StandardRegexUI.cs b/Rdmp.UI/Validation/StandardRegexUI.cs index ac5d9c8794..15e399859a 100644 --- a/Rdmp.UI/Validation/StandardRegexUI.cs +++ b/Rdmp.UI/Validation/StandardRegexUI.cs @@ -80,6 +80,4 @@ private void btnTest_Click(object sender, EventArgs e) } [TypeDescriptionProvider(typeof(AbstractControlDescriptionProvider))] -public abstract class StandardRegexUI_Design : RDMPSingleDatabaseObjectControl -{ -} \ No newline at end of file +public abstract class StandardRegexUI_Design : RDMPSingleDatabaseObjectControl; \ No newline at end of file diff --git a/Rdmp.UI/Validation/ValidationSetupUI.cs b/Rdmp.UI/Validation/ValidationSetupUI.cs index 7e43c2406c..eace5381ec 100644 --- a/Rdmp.UI/Validation/ValidationSetupUI.cs +++ b/Rdmp.UI/Validation/ValidationSetupUI.cs @@ -424,6 +424,4 @@ private void lblPickPivotColumn_Click(object sender, EventArgs e) } [TypeDescriptionProvider(typeof(AbstractControlDescriptionProvider))] -public abstract class ValidationSetupForm_Design : RDMPSingleDatabaseObjectControl -{ -} \ No newline at end of file +public abstract class ValidationSetupForm_Design : RDMPSingleDatabaseObjectControl; \ No newline at end of file diff --git a/Rdmp.UI/Versioning/PatchingUI.cs b/Rdmp.UI/Versioning/PatchingUI.cs index 47e9ba8a4c..6e42d19090 100644 --- a/Rdmp.UI/Versioning/PatchingUI.cs +++ b/Rdmp.UI/Versioning/PatchingUI.cs @@ -12,7 +12,6 @@ using Rdmp.Core.MapsDirectlyToDatabaseTable; using Rdmp.Core.MapsDirectlyToDatabaseTable.Versioning; using Rdmp.Core.ReusableLibraryCode.Checks; -using Rdmp.UI.SimpleDialogs.SqlDialogs; namespace Rdmp.UI.Versioning; @@ -68,8 +67,7 @@ private void btnAttemptPatching_Click(object sender, EventArgs e) var mds = new MasterDatabaseScriptExecutor(_database); - mds.PatchDatabase(_patcher, toMem, (Patch p) => true, - () => false); + mds.PatchDatabase(_patcher, toMem, static _ => true, static () => false); //if it crashed during patching if (toMem.GetWorst() == CheckResult.Fail) diff --git a/Tests.Common/GovernancePeriod_Catalogue.cs b/Tests.Common/GovernancePeriod_Catalogue.cs deleted file mode 100644 index 4a79c4be5c..0000000000 --- a/Tests.Common/GovernancePeriod_Catalogue.cs +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright (c) The University of Dundee 2018-2019 -// This file is part of the Research Data Management Platform (RDMP). -// 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. -// 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. -// You should have received a copy of the GNU General Public License along with RDMP. If not, see . - -namespace Tests.Common; - -internal class GovernancePeriod_Catalogue -{ -} \ No newline at end of file diff --git a/Tests.Common/Scenarios/TestsRequiringACohort.cs b/Tests.Common/Scenarios/TestsRequiringACohort.cs index 01e8001251..51c377df0d 100644 --- a/Tests.Common/Scenarios/TestsRequiringACohort.cs +++ b/Tests.Common/Scenarios/TestsRequiringACohort.cs @@ -187,8 +187,8 @@ private void SetupCohortDefinitionAndCustomTable(DbConnection con) dt.Columns.Add("SuperSecretThing"); dt.Columns.Add("PrivateID"); - dt.Rows.Add(new[] { "monkeys can all secretly fly", "Priv_12345" }); - dt.Rows.Add(new[] { "the wizard of OZ was a man behind a machine", "Priv_wtf11" }); + dt.Rows.Add("monkeys can all secretly fly", "Priv_12345"); + dt.Rows.Add("the wizard of OZ was a man behind a machine", "Priv_wtf11"); CustomTable = _cohortDatabase.CreateTable("custTable99", dt); } diff --git a/Tests.Common/Scenarios/TestsRequiringADle.cs b/Tests.Common/Scenarios/TestsRequiringADle.cs index 9b28077b7d..9753f16e8b 100644 --- a/Tests.Common/Scenarios/TestsRequiringADle.cs +++ b/Tests.Common/Scenarios/TestsRequiringADle.cs @@ -56,12 +56,7 @@ protected override void SetUp() Clear(LoadDirectory); LiveTable = CreateDataset(Database, 500, 5000, new Random(190)); - LiveTable.CreatePrimaryKey(new DiscoveredColumn[] - { - LiveTable.DiscoverColumn("chi"), - LiveTable.DiscoverColumn("dtCreated"), - LiveTable.DiscoverColumn("hb_extract") - }); + LiveTable.CreatePrimaryKey(LiveTable.DiscoverColumn("chi"), LiveTable.DiscoverColumn("dtCreated"), LiveTable.DiscoverColumn("hb_extract")); TestCatalogue = Import(LiveTable); RowsBefore = 5000; diff --git a/Tests.Common/Scenarios/TestsRequiringAnExtractionConfiguration.cs b/Tests.Common/Scenarios/TestsRequiringAnExtractionConfiguration.cs index 2f9beb3a47..0c4a6897f8 100644 --- a/Tests.Common/Scenarios/TestsRequiringAnExtractionConfiguration.cs +++ b/Tests.Common/Scenarios/TestsRequiringAnExtractionConfiguration.cs @@ -134,7 +134,7 @@ private void SetupCatalogueConfigurationEtc() dt.Columns.Add("Name"); dt.Columns.Add("DateOfBirth"); - dt.Rows.Add(new object[] { _cohortKeysGenerated.Keys.First(), "Dave", "2001-01-01" }); + dt.Rows.Add(_cohortKeysGenerated.Keys.First(), "Dave", "2001-01-01"); var tbl = Database.CreateTable("TestTable", dt, new[] { new DatabaseColumnRequest("Name", new DatabaseTypeRequest(typeof(string), 50)) }); diff --git a/Tools/rdmp/CommandLine/ColorSettings.cs b/Tools/rdmp/CommandLine/ColorSettings.cs index 198438eed5..2dc7c3b631 100644 --- a/Tools/rdmp/CommandLine/ColorSettings.cs +++ b/Tools/rdmp/CommandLine/ColorSettings.cs @@ -6,6 +6,7 @@ using System; using System.IO; +using System.Threading; using Terminal.Gui; using YamlDotNet.Serialization; using Attribute = Terminal.Gui.Attribute; @@ -20,14 +21,14 @@ namespace Rdmp.Core.CommandLine; /// public class ColorSettings { - private static object oLockInstance = new(); + private static readonly Lock OLockInstance = new(); private static ColorSettings _instance; public static ColorSettings Instance { get { - lock (oLockInstance) + lock (OLockInstance) { // if not first time, return existing value if (_instance != null) return _instance; diff --git a/Tools/rdmp/CommandLine/Gui/ConsoleGuiBigListBox.cs b/Tools/rdmp/CommandLine/Gui/ConsoleGuiBigListBox.cs index 4586d0005c..b8de0569f6 100644 --- a/Tools/rdmp/CommandLine/Gui/ConsoleGuiBigListBox.cs +++ b/Tools/rdmp/CommandLine/Gui/ConsoleGuiBigListBox.cs @@ -38,10 +38,10 @@ internal class ConsoleGuiBigListBox /// /// Ongoing filtering of a large collection should be cancelled when the user changes the filter even if it is not completed yet /// - private ConcurrentBag _cancelFiltering = new(); + private readonly ConcurrentBag _cancelFiltering = []; private Task _currentFilterTask; - private object _taskCancellationLock = new(); + private readonly Lock _taskCancellationLock = new(); private ListView _listView; private bool _changes; diff --git a/Tools/rdmp/CommandLine/Gui/ConsoleGuiViewGraph.cs b/Tools/rdmp/CommandLine/Gui/ConsoleGuiViewGraph.cs index 54d25b43c1..7156e5cd8e 100644 --- a/Tools/rdmp/CommandLine/Gui/ConsoleGuiViewGraph.cs +++ b/Tools/rdmp/CommandLine/Gui/ConsoleGuiViewGraph.cs @@ -274,7 +274,7 @@ private void SetupMultiBarSeries(DataTable dt, string countColumnName, int bound { var numberOfBars = dt.Columns.Count - 1; var colors = GetColors(numberOfBars).ToArray(); - var mediumStiple = '\u2592'; + const char mediumStiple = '\u2592'; graphView.GraphColor = Driver.MakeAttribute(Color.White, Color.Black); // Configure legend diff --git a/Tools/rdmp/CommandLine/Gui/Windows/RunnerWindows/RunDleWindow.cs b/Tools/rdmp/CommandLine/Gui/Windows/RunnerWindows/RunDleWindow.cs index 446de5ef13..6631f55b68 100644 --- a/Tools/rdmp/CommandLine/Gui/Windows/RunnerWindows/RunDleWindow.cs +++ b/Tools/rdmp/CommandLine/Gui/Windows/RunnerWindows/RunDleWindow.cs @@ -44,8 +44,6 @@ protected override void AdjustCommand(DleOptions opts, CommandLineActivity activ if (BasicActivator.SelectValueType("Days to Load", typeof(int), lp.DefaultNumberOfDaysToLoadEachTime, out var chosen)) opts.DaysToLoad = (int)chosen; - else - return; } } } \ No newline at end of file diff --git a/Tools/rdmp/CommandLine/Gui/Windows/RunnerWindows/RunEngineWindow.cs b/Tools/rdmp/CommandLine/Gui/Windows/RunnerWindows/RunEngineWindow.cs index 5f4fc734ae..f52ec166c2 100644 --- a/Tools/rdmp/CommandLine/Gui/Windows/RunnerWindows/RunEngineWindow.cs +++ b/Tools/rdmp/CommandLine/Gui/Windows/RunnerWindows/RunEngineWindow.cs @@ -9,6 +9,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.IO; +using System.Threading; using System.Threading.Tasks; using Rdmp.Core.CommandExecution; using Rdmp.Core.CommandExecution.AtomicCommands.Automation; @@ -21,19 +22,20 @@ namespace Rdmp.Core.CommandLine.Gui.Windows.RunnerWindows; internal class RunEngineWindow : Window, IListDataSource where T : RDMPCommandLineOptions { - private Process process; - private ListView _results; + private Process _process; + private readonly ListView _results; protected readonly IBasicActivateItems BasicActivator; - private readonly Func commandGetter; + private readonly Func _commandGetter; - private object lockList = new(); - private List consoleOutput = new(); - private ColorScheme _red; - private ColorScheme _yellow; - private ColorScheme _white; + private readonly Lock _lockList = new(); + private readonly List _consoleOutput = []; + private readonly ColorScheme _red; + private readonly ColorScheme _yellow; + private readonly ColorScheme _white; - public int Count => consoleOutput.Count; - public int Length => consoleOutput.Count; + public int Count { get; private set; } + + public int Length => Count; public RunEngineWindow(IBasicActivateItems activator, Func commandGetter) { @@ -70,32 +72,32 @@ public RunEngineWindow(IBasicActivateItems activator, Func commandGetter) _results.KeyPress += Results_KeyPress; BasicActivator = activator; - this.commandGetter = commandGetter; + this._commandGetter = commandGetter; } private void Results_KeyPress(KeyEventEventArgs obj) { - if (obj.KeyEvent.Key == Key.Enter && _results.HasFocus) - { - var listIdx = _results.SelectedItem; - var list = _results.Source.ToList(); + if (obj.KeyEvent.Key != Key.Enter || !_results.HasFocus) return; - if (listIdx < list.Count) - { - var selected = list[listIdx]; - BasicActivator.Show(selected.ToString()); - } + var listIdx = _results.SelectedItem; + var list = _results.Source.ToList(); - obj.Handled = true; + if (listIdx < list.Count) + { + var selected = list[listIdx]; + BasicActivator.Show(selected.ToString()); } + + obj.Handled = true; } private void ClearOutput() { - lock (lockList) + lock (_lockList) { _results.SelectedItem = 0; - consoleOutput.Clear(); + _consoleOutput.Clear(); + Count = 0; _results.SetNeedsDisplay(); } } @@ -104,7 +106,7 @@ private void Abort() { try { - process?.Kill(); + _process?.Kill(); } catch (Exception ex) { @@ -116,7 +118,7 @@ private void Execute() { try { - var opts = commandGetter(); + var opts = _commandGetter(); opts.Command = CommandLineActivity.run; AdjustCommand(opts, opts.Command); @@ -141,7 +143,7 @@ private void Check() { try { - var opts = commandGetter(); + var opts = _commandGetter(); opts.Command = CommandLineActivity.check; AdjustCommand(opts, opts.Command); @@ -176,7 +178,7 @@ private void Run(Func commandGetter) var cmd = new ExecuteCommandGenerateRunCommand(BasicActivator, commandGetter); var args = cmd.GetCommandText(true); - process = new Process + _process = new Process { StartInfo = new ProcessStartInfo { @@ -190,15 +192,16 @@ private void Run(Func commandGetter) Task.Run(() => { - process.Start(); + _process.Start(); - while (!process.StandardOutput.EndOfStream) + while (!_process.StandardOutput.EndOfStream) { - var line = process.StandardOutput.ReadLine().Trim(); + var line = _process.StandardOutput.ReadLine().Trim(); - lock (lockList) + lock (_lockList) { - consoleOutput.Insert(0, line); + _consoleOutput.Insert(0, line); + Count++; Application.MainLoop.Invoke(() => _results.SetNeedsDisplay()); } } @@ -208,11 +211,11 @@ private void Run(Func commandGetter) public void Render(ListView container, ConsoleDriver driver, bool selected, int item, int col, int line, int width, int start = 0) { - lock (lockList) + lock (_lockList) { - if (item >= consoleOutput.Count) return; + if (item >= Count) return; - var str = consoleOutput[item]; + var str = _consoleOutput[item]; str = str.Length > width ? str[..width] : str.PadRight(width, ' '); @@ -237,5 +240,9 @@ public void SetMark(int item, bool value) { } - public IList ToList() => consoleOutput; + public IList ToList() + { + lock (_lockList) + return _consoleOutput.AsReadOnly(); + } } \ No newline at end of file